Highlights 💡
More reliable HMR, fewer full-page reloads
HMR now handles code-splitting changes more reliably, reducing unnecessary full-page reloads when chunks are added or rearranged. Newly required chunks are loaded before HMR accept callbacks run, and changes to async chunk dependencies no longer cause unnecessary update propagation.
Experimental rule.as
The experimental rule.as option lets a matched resource use a different path for subsequent rule matching while preserving the original resource for file reading and loaders. For example, as: '[resource-path].txt' lets later .txt rules also process example.source.js. (#15917)
// rspack.config.mjs
export default {
module: {
rules: [
{
test: /\.source\.js$/,
type: 'asset/source',
as: '[resource-path].txt',
},
{ test: /\.txt$/, use: './text-loader.js' },
],
},
};Here, example.source.js matches the later .txt rule as example.source.js.txt; text-loader.js still receives the contents of the original file.
Skip side-effect-free export * passthrough modules
Rspack can now bypass side-effect-free modules that only forward exports with export *, connecting directly to the underlying module.
Mark the package as side-effect-free in package.json:
{
"sideEffects": false
}// src/value.js
export const value = 42;
// src/passthrough.js
export * from './value.js';
// src/index.js
export * from './passthrough.js';With optimization.sideEffects enabled (the default in production), the export * connection from index.js can now go directly to value.js, skipping passthrough.js.
What's Changed
New Features 🎉
- feat(sri): support hashLoading: "lazy" in SubresourceIntegrityPlugin by @sd2k in #16374
- feat: add output.environment.topLevelAwait and await async ESM entries by @hai-x in #16386
- feat: support externals.byLayer by @stormslowly in #16307
- feat(css): Add opt-in runtime public paths for injected styles by @scttcper in #15705
- feat: add experimental rule.as by @intellild in #15917
- feat(tree-shaking): prune dynamic imports from unused exports by @LingyuCoder in #15449
- feat: skip side-effect-free
export *passthrough modules by @hai-x in #16472
Performance 🚀
- perf: use memchr SIMD scans and drop winnow by @intellild in #16424
- perf(sources): box the replacement name by @LingyuCoder in #15878
- perf: lazily create existing loader dependency sets by @chenjiahan in #16449
- perf: lazily materialize package.json metadata by @LingyuCoder in #16469
- perf(core): trim runtime spec sets on creation by @guru-irl in #16478
- perf(sources): share source map text with BytesStr by @SyMind in #16468
- perf(core): free the previous compilation's assets during a rebuild by @guru-irl in #16479
- perf(sources): compact noSources maps only when retained by @SyMind in #16536
- perf: reduce source map memory during asset generation and content hashing by @LingyuCoder in #16470
Bug Fixes 🐞
- fix(core): keep property access when inlining an export reached through a re-export by @flex-mookeun in #16310
- fix(core): keep the full hash stable across rebuilds without HMR by @guru-irl in #16280
- fix(runtime): avoid coercion collisions in chunk ID matchers by @intellild in #16423
- fix(devtool): map bootstrap and startup sources by @LingyuCoder in #16426
- fix: keep receiver exports for calls on unprovided members by @hai-x in #16418
- fix: restore side-effect imports after package metadata changes by @ahabhgk in #16435
- fix(cache): reuse completed builds for external and generated modules by @ahabhgk in #16429
- fix(core): fold chunk hashes into the full hash in chunk id order by @guru-irl in #16293
- fix: keep initializers of unused top-level using declarations by @hai-x in #16437
- fix(watcher): preserve concrete paths in native watcher events by @stormslowly in #16411
- fix(stats): report each runtime module's own size and chunks by @guru-irl in #16076
- fix(hmr): complete new entry chunk dependencies by @JSerFeng in #15955
- fix: isolate entry declarations from runtime tables by @ahabhgk in #16497
- fix: preserve module namespace key order for mixed exports by @LingyuCoder in #16491
- fix(watcher): separate filesystem accuracy from cache by @stormslowly in #16512
- fix(watcher): align rename events with watchpack by @stormslowly in #16460
- fix: skip cyclic star re-exports when resolving a binding by @LingyuCoder in #16496
- fix: preserve lone surrogates during constant evaluation by @LingyuCoder in #16494
- fix(watcher): pass SystemTime to mtime_accuracy by @hai-x in #16526
- fix(resolver): support UTF-8 BOM in tsconfig files by @stormslowly in #16518
- fix: evaluate
x in nsto true whenxis a re-exported namespace by @hai-x in #16509 - fix: preserve negative zero in exports and use JavaScript number strings in constant evaluation by @LingyuCoder in #16527
- fix(mf): keep the whole requiredVersion range in mf-manifest.json by @arnaud-zg in #16402
- fix(core): distinguish fatal module errors from loader diagnostics by @ahabhgk in #16538
- fix(css): scope counter styles and implicit grid lines by @intellild in #16520
- fix(hmr): invalidate cached chunks when version tags change by @JSerFeng in #16548
- fix(watcher): account for directory mtime accuracy by @stormslowly in #16531
- fix(mf): read provided shared fields directly in manifests by @ahabhgk in #16533
- fix(resolver): report circular tsconfig extends instead of crashing by @stormslowly in #16513
- fix(hmr): load async groups through their last chunk by @JSerFeng in #16328
- fix(resolver): reload PnP manifest from cached path by @stormslowly in #16543
Refactor 🔨
- refactor(binding): rely on napi-rs for module retention by @SyMind in #16431
- refactor: remove unused exports_definitions hook from ConcatenatedModule by @hai-x in #16434
- refactor(binding): implement module classes in JavaScript by @SyMind in #16436
Document 📖
- docs: clarify split chunks sizing and cache group examples by @chenjiahan in #16409
- docs: clarify split chunks counting and troubleshooting by @chenjiahan in #16412
- docs: explain entry dependencies and shared runtime by @chenjiahan in #16413
- docs: standardize Rspack runtime terminology by @chenjiahan in #16427
- docs: clarify Lightning CSS minimizer options and examples by @chenjiahan in #16417
- docs: add Nitro to community integrations by @chenjiahan in #16428
- docs: introduce rspack-chain for configuration customization by @chenjiahan in #16430
- docs: illustrate runtime chunk initialization by @chenjiahan in #16414
- docs: add compilation dependency tracking examples by @chenjiahan in #16415
- docs: add entrypoints manifest example by @chenjiahan in #16416
- docs: refresh Rspack and Rstack introduction by @chenjiahan in #16455
- docs: clarify stats asset metadata by @chenjiahan in #16461
- docs: redirect moved pages on Cloudflare Pages by @chenjiahan in #16465
- docs(website): simplify Rspress configuration by @SoonIter in #16522
- docs: expand community plugin list by @chenjiahan in #16524
- docs: expand community loader list by @chenjiahan in #16528
- docs: clarify chunk ID assignment when chunkIds is false by @LingyuCoder in #16523
- docs: use a WebMCP prompt in the Rspack 2.3 announcement by @SoonIter in #16553
Other Changes
- test(cache): validate persistent cache hits in config and normal cases by @ahabhgk in #16397
- test: exclude external re-export case from cache reuse checks by @SyMind in #16425
- ci: use trunk baseline for branch-based PR stacks by @ScriptedAlchemy in #16201
- chore(deps): update napi by @renovate[bot] in #16230
- chore(deps): update dependency tiny-emitter to v2.1.0 by @renovate[bot] in #16440
- test: exclude container tree shaking for configCases cache test by @ahabhgk in #16450
- chore(deps): upgrade SWC crates and browserslist-rs by @chenjiahan in #16458
- chore(deps): update dependency rsbuild-plugin-google-analytics to v1.1.0 by @renovate[bot] in #16438
- chore(deps): update dependency coffee-loader to v5 by @renovate[bot] in #16441
- chore(deps): update patch npm dependencies by @renovate[bot] in #16476
- chore(deps): update dependency mermaid to ^12.3.0 by @renovate[bot] in #16480
- chore: use Rspress built-in Shiki transformers by @chenjiahan in #16489
- chore(deps): update dependency playwright to v1.65.0 by @renovate[bot] in #16481
- chore(ci): use mini runner for ecosystem ci dispatcher by @stormslowly in #14471
- test(watcher): stabilize nested context removal case by @stormslowly in #16519
- chore(deps): update Rslib to 1.0.6 by @SoonIter in #16471
- chore(deps): update dependency sass-loader to ^17.1.0 by @renovate[bot] in #16498
- chore(deps): update rust crate tokio to 1.54.1 by @renovate[bot] in #16502
- chore(deps): update dependency jsdom to v31 by @renovate[bot] in #16504
- chore(deps): bump swc-next to 0.6.1 by @CPunisher in #16525
- chore: bump
swc_corefrom 84.0.1 to 84.0.2 by @CPunisher in #16547 - test(stats): cover shared issuers in child compilations by @stormslowly in #16456
- chore(deps): update dependency execa to v10 by @renovate[bot] in #16503
- test: wait for both watchers to finish the initial batch in rename cases by @LingyuCoder in #16530
- test(watcher): validate burst aggregation against event timing by @stormslowly in #16544
- test: stabilize cache restoration watch test by @ahabhgk in #16555
New Contributors
- @sd2k made their first contribution in #16374
- @scttcper made their first contribution in #15705
- @arnaud-zg made their first contribution in #16402
Full Changelog: v2.3.1...v2.3.2