Rolldown cuts plugin change round-trip by 26x with field-level diffing
Rolldown 把插件改动回传提速 26 倍
Rolldown's next version will make the round-trip of plugin changes finer-grained, sending only the fields that actually changed back to Rust. In large projects, this step drops from 1015 milliseconds to 39 milliseconds.
The news was announced by Rolldown maintainer hyfdev, and the change comes from anonrig, i.e. Yagiz Nizipli, who now leads X's web frontend.
First, let's clarify what exactly is being saved here.
Rolldown writes the bundling core in Rust, while the plugin ecosystem is still JavaScript; data must pass back and forth between the two sides.
After the two output hooks generateBundle and writeBundle finish running, plugin modifications to the output have to be sent back to Rust before they can be written into the final files.
The old approach was crude: if a plugin touched any single field on a chunk, the entire chunk went back along with all of its properties.
Where does the cost lie? The PR spells it out in detail.
Rust serializes the chunk's sourcemap once, JavaScript parses it once, and Rust parses it once again.
Fields such as code, moduleIds, and exports get copied in both directions, while update_output_chunk on the Rust side does not look at most of them at all.
The caching problem is worse. After Rust replaces the chunk data, the previous code cache is invalidated, and the next plugin that reads chunk.code has to copy the whole code again.
Vite itself steps on this: whenever there is a pure-CSS chunk, vite:css-post executes chunk.imports = chunk.imports.filter(...) on every chunk, even though most chunk filenames never change.
So the fix is straightforward: send only the fields that actually changed; for unchanged chunks, not a single byte is transmitted.
Existing behavior still works: in-place modification of the imports array when read, setting map to null, renaming, and deleting outputs all preserve the original semantics.
The author also added guard rails. Writing a non-string into chunk.code or a non-array into imports now throws a TypeError that says which property of which chunk, instead of silently writing with the old value.
How much faster is it?
The PR ran interleaved A/B tests on a build with 2182 chunks, 30 MB of compressed JS, and 136 MB of hidden sourcemaps.
In the generate() round, the entire generateBundle phase dropped from 1256 ms to 752 ms, a 40.1% reduction, and the total time from 2392 ms to 1862 ms.
The other two rounds went from 1400 to 798 ms and from 1036 to 644 ms, with total time down 20% to 25%.
Output hashes were identical in every round.
Real applications show even more dramatic results.
Taking the production build of that large Vite application itself and running two CPU sampling rounds, the callback segment collectChangedBundle dropped from 1015 ms and 720 ms to 39 ms and 28 ms.
Reading chunk.map went from 866 ms to 97 ms, and reading chunk.code from 387 ms to 189 ms.
hyfdev added a note: the 26x figure applies only to this “prepare changes” step, not the whole hook. The entire output hook is about 40% faster; that multiplier should not be taken as a global number.
That the output did not change was also verified. After normalizing hashes, all but 5 of the 10,958 files matched.
Those 5 also differed between the two baseline builds: one is a script the application re-obfuscates every run, and one is the client manifest.
When can you use it? The change was merged on November 6 and will ship with the next version; Vite 8 uses Rolldown.
If you write small or medium projects, you won't notice much; there are few chunks and few hooks.
What is really affected is large projects with thousands of chunks and hidden sourcemaps, where generateBundle takes seconds to run and plugins have to be written differently per environment.
This change does not touch the hook objects themselves; it only refines the round-trip, checking which fields changed before deciding what to send.
PR address: https://github.com/rolldown/rolldown/pull/11488.
Where does your project's build time get stuck? Feel free to share in the comments.
About me:
- Rural programmer (
returned to the countryside in 2020, hasn't left the village since) - Independent developer (
working toward 1000 small products) - Technology observer (
sharing programming knowledge, industry news, etc.) - Frontend Tiger Chen Suiyi (
self-proclaimed) - My website is:
https://yicode.tech