esbuild
esbuild copied to clipboard
[BUG] `serve` does not work with `onEnd`
I've found that serve
happens before or ignores what happens in onEnd()
? I've have this simple plugin that uses onEnd
to modify the output slightly. But I can't get it to work in combination with serve
. In my file system the output file(s) are modified, but the files served are not.
I'm using version 0.17.18
.
Below is a minimum example project.
// build.js
import * as esbuild from 'esbuild';
import fs from "fs";
import path from "path";
let ctx = await esbuild.context({
entryPoints: ['src/index.ts'],
bundle: true,
outdir: 'dist',
write: false,
plugins: [{
name: 'format',
setup(build) {
build.onEnd(result => {
return new Promise(async (resolve) => {
for (const [index, outFile] of result.outputFiles.entries()) {
// Only modify `.js` files
if (outFile.path.match(/\.js$/)) {
// You cannot modify .text because its only a getter.
// Also see: https://github.com/evanw/esbuild/issues/1792
result.outputFiles[index].contents = Buffer.from("console.log('hello world');");
}
}
for (const outFile of result.outputFiles) {
const dirName = path.dirname(outFile.path);
//Check if path exits
if (!fs.existsSync(dirName)) {
// If not, create directory.
fs.mkdirSync(dirName, { recursive: true });
}
fs.writeFileSync(outFile.path, outFile.text, 'utf8');
}
resolve();
});
});
}
}]
})
await ctx.watch()
let { host, port } = await ctx.serve({
servedir: '.',
});
// index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="./dist/index.js"></script>
</head>
<body>
</body>
</html>
// src/index.ts
console.log('hello world');
// dist/index.js
console.log('hello world');
I have the same issue, I was trying to use an onEnd
callback to perform simple string find/replace. It seems like serve caches the build result before the onEnd
callbacks run?
As a workaround you can either try switching to an onLoad
callback (which may not work because I think only one onLoad
callback can return content for a given path), or hook into another plugin. In my case, I am using Svelte so I was able to write a custom Svelte preprocessor to do my find/replace in the Svelte compiler instead of from esbuild. Probably a better solution anyway, but this does feel like an esbuild bug.
For the moment I'm not using the esbuild server but express
.
// configure esbuild.context()
const app = express();
function startExpressServer() {
app.use(express.static('.'));
app.listen(port, () => {
console.log(`Listening on port: ${port}`);
});
app.get('/express', (req, res) => {
// send headers to keep connection alive
const headers = {
'Content-Type': 'text/event-stream',
Connection: 'keep-alive',
'Cache-Control': 'no-cache',
};
res.writeHead(200, headers);
// store `res` of client to let us send events at will
client = res;
// listen for client 'close' requests
req.on('close', () => {
client = null;
});
});
}
await esbuildContext.watch();
startExpressServer();
I have the same issue, I was trying to use an
onEnd
callback to perform simple string find/replace. It seems like serve caches the build result before theonEnd
callbacks run?As a workaround you can either try switching to an
onLoad
callback (which may not work because I think only oneonLoad
callback can return content for a given path), or hook into another plugin. In my case, I am using Svelte so I was able to write a custom Svelte preprocessor to do my find/replace in the Svelte compiler instead of from esbuild. Probably a better solution anyway, but this does feel like an esbuild bug.
I try to write outputFiles ,but not working...
outputFiles[i].contents = new Uint8Array(Buffer.from(code))
const app = express();
function startExpressServer() { app.use(express.static('.'));
app.listen(port, () => { console.log(`Listening on port: ${port}`); }); app.get('/express', (req, res) => { // send headers to keep connection alive const headers = { 'Content-Type': 'text/event-stream', Connection: 'keep-alive', 'Cache-Control': 'no-cache', }; res.writeHead(200, headers); // store `res` of client to let us send events at will client = res; // listen for client 'close' requests req.on('close', () => { client = null; }); });
}
@evanw pls provide a API to change the code in esbuild server memory code ... I may very much need to modify the content after the construction is completed.