Rolldown cuts plugin change round-trip by 26x with field-level diffing
Rolldown is the bundler inside Vite 8, so large Vite production builds get this speedup without changing a line of plugin code: the `generateBundle` phase drops roughly 40%, and a single round-trip step falls from about a second to 39 ms. The 26x figure covers only the prepare-changes step, not the whole hook.
Rolldown's next release replaces the coarse plugin callback with field-level diffing. Previously any plugin mutation on a chunk, even a trivial filter on `imports`, reserialized the entire chunk including its sourcemap across the Rust/JS boundary, and invalidated the code cache so the next `chunk.code` read had to copy everything again. The fix transmits only the fields that changed; untouched chunks send nothing at all.
Benchmarks on an interleaved A/B build of 2182 chunks and 136 MB of hidden sourcemaps show the `generateBundle` phase falling from 1256 ms to 752 ms, a 40.1% reduction, with total build time down 20% to 25%. Tests on a large Vite production app bring the `collectChangedBundle` step from 1015 ms and 720 ms down to 39 ms and 28 ms across two CPU sampling runs, and reading `chunk.map` drops from 866 ms to 97 ms. Output hashes match across runs: all but 5 of 10,958 files are identical after normalization, and those 5 also differ between the two baseline builds.
The change merged on November 6 and ships with the next Rolldown release, which Vite 8 will use. Small projects won't feel it; the win is for large, chunk-heavy builds with hidden sourcemaps. The maintainers also added guard rails: writing a non-string into `chunk.code` or a non-array into `imports` now throws a `TypeError` naming the chunk and property, instead of silently accepting the bad value.
Vite itself was paying this cost in practice: `vite:css-post` filters `chunk.imports` on every chunk with pure CSS, even though most filenames never change, so the optimization fixes real behavior inside the default toolchain rather than a hypothetical worst case.
The new type guards harden the plugin boundary: invalid writes that were silently accepted now fail with a specific `TypeError` at hook time, which pushes plugin authors to catch mistakes before they reach the final output.
The maintainers' honesty about the benchmark matters: 26x is only one step inside `generateBundle`, and quoting that multiplier as a global build speedup would misrepresent the actual 40% hook-level improvement.