esbuild icon indicating copy to clipboard operation
esbuild copied to clipboard

Serve mode does not pick up changes made to the output files in the onEnd callback

Open vassbence opened this issue 8 months ago • 4 comments

I'm modifying the content of one of my files in the bundle in the onEnd callback and serve mode does not seem to pick up on the changes. Is this expected?

vassbence avatar Apr 09 '25 11:04 vassbence

It is expected. You may want to check out the serve and watch methods details but here's the quick explanation:

  • The serve mode runs build only when each time the browser requests the bundle file. So if you do not refresh the web page it will not do anything.
  • The watch mode runs build when each time the referenced files changed.
  • serve and watch can be used together.

References:

  • https://esbuild.github.io/api/#serve:~:text=each%20incoming%20request%20starts%20a%20rebuild
  • https://esbuild.github.io/api/#watch

hyrious avatar Apr 10 '25 13:04 hyrious

I think the issue is not necessarily about when each of these run, but rather if changes made to the bundle inside of the onEnd callback should be served by esbuild or not.

The docs say this about On-end callbacks:

It can modify the build result before returning and can delay the end of the build by returning a promise.

I assume currently the changes are not getting picked up because JS doesn't send back the output to the Go server running locally thus it never knows about if I change something.

vassbence avatar Apr 10 '25 16:04 vassbence

I assume currently the changes are not getting picked up because JS doesn't send back the output to the Go server running locally thus it never knows about if I change something.

Yes. I was mis-understanding your purpose above.

The doc says "It can modify the build result...". I think the "build result" means the result object in JavaScript. It will contains an outputFiles field only if "write": false.

So the ideal usage for the on-end callback to modify results is like:

import { build } from 'esbuild'

let result = await build({
  entryPoints: ['index.js'],
  bundle: true,
  outfile: 'bundle.js',
  write: false, // <-- required
  plugins: [{
    name: 'modify-on-end',
    setup({ onEnd }) {
      onEnd(result => {
        let file = result.outputFiles[0]
        file.contents = new TextEncoder().encode(file.text + `\nconsole.log('modified');`)
      })
    }
  }]
})

console.log(result.outputFiles[0].text)
/** logs:
(() => {
  // index.js
  console.log(1);
})();

console.log('modified');
*/

It doesn't interfere the server inside esbuild.

hyrious avatar Apr 11 '25 06:04 hyrious

I think it would be really powerful if changes would actually get served by esbuild thru the serve API. Otherwise "It can modify the build result..." is a bit misleading imho.

@evanw would this be out of scope?

vassbence avatar Apr 12 '25 11:04 vassbence