Update the advice on which bundler to use to `esbuild` instead of `rollup`.
Closed this issue · 3 comments
I've been using esbuild pretty much since it came out, and the speed is just unmatched. If I use rollup
, as mentioned as the preferred method over on https://codemirror.net/examples/bundle/ then the rebuild takes 400+ milliseconds on a high end M2 Macbook Pro, and 833 milliseconds on a desktop workstation with Win10 pro running on a Ryzen 5950X (a "traditional" cpu that predates the M2 by 2 years as well as an entire "real" generational leap).
If I run the same bundling using esbuild
, targeting ESM instead of IIFE (because it's 2024) then the bundling times are 688ms on the desktop and 183 milliseconds on the mac. On the desktop, that's 25% faster. On the M2, that's 60% faster. No matter how you benchmark this, rollup is no longer the right tool to recommend, and switching the advice to using esbuild instead makes a ton of sense. Because these differences matter a lot: if you're doing a lot of watch-rebuilding, those extra hundreds of milliseconds really add up to a sense of frustration with rollup that just isn't there (or is drastically less) with esbuild.
Rollup was a great at showing how poorly Webpack (and Browserify) performed, but esbuild showed how fast bundling can actually be.
For concrete comparison, I'm using the following scripts in my own project:
{
...
"scripts": {
"build:rollup": "rollup script.js -f iife -o prebaked/editor.bundle.js -p @rollup/plugin-node-resolve",
"build:esbuild": "esbuild --log-level=info --bundle --format=esm script.js > prebaked/editor.bundle.js",
"start": "node server.js"
},
...
}
With my server.js doing the watching, rather than relying on --watch flags:
...
const toWatch = [`./script.js`, ...];
app.listen(8000, () => {
console.log(`http://127.0.0.1:8000`);
rebuild();
toWatch.forEach((filename) => watch(filename, () => rebuild()));
});
...
function rebuild() {
const start = Date.now();
spawnSync(isWindows ? `npm.cmd` : `npm`, [`run`, `build:esbuild`], {
stdio: `inherit`,
});
console.log(`Build took ${Date.now() - start}ms`);
}
So as an added benefit, we also don't need the additional rollup dependency either, it just compiles to ESM and we load our bundle using a modern <script>
tag:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<script src="./editor.bundle.js" async defer type="module"></script>
...
</head>
<body>
...
</body>
</html>
People are free to use esbuild, but Rollup is still my tool of choice and the one I have the most experience with, as well as the one that Lezer has a plugin for, so I am not changing this.
Your call, but I would strongly recommend you start giving esbuild a try, especially if you use rollup for everything, like I used to. Especially since these examples are for everyone's benefit, and esbuild is objectively the better tool to recommend to people these days.
(And I can guarantee you it'll be a near-dropin replacement for Lezer, too, and it'll be much faster.)