perf(rspack): keep persistent caches warm across modes and stop full stats serialization per rebuild - #14569
Conversation
…ats serialization
Four fixes to the rspack persistent-cache and stats handling:
- Include the mode in the cache directory name. The cache version already
encoded the mode, and rspack invalidates a persistent store on version
mismatch, so development and production builds sharing one directory
wiped each other's cache on every run/build switch instead of keeping
both warm.
- Restore buildContext in the second createCacheStrategy call. The
reassignment after user/override configs load is the effective cache
strategy, and dropping buildContext there made the cache directory
collide across build contexts (e.g. custom METEOR_LOCAL_DIR setups).
- Apply the persistent cache to server production builds. The server
config only cached development, test, and native builds, so meteor
build recompiled the entire server bundle cold every time. Eager
server test builds remain excluded since their generated entry
changes on every run.
- Narrow RequireExternalsPlugin's stats.toJson to { all: false,
modules: true, cachedModules: true }. The plugin only reads module
names, but serialized the full stats object inside the done hook on
every compilation. cachedModules keeps unchanged modules listed on
incremental rebuilds so their requires are not wrongly removed.
Part of meteor#14568.
✅ Deploy Preview for v3-migration-docs canceled.
|
✅ Deploy Preview for v3-meteor-api-docs ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughRspack external-module statistics now include cached and orphan modules with a narrower payload. Persistent cache directories are scoped by mode and build context. Server builds use the persistent cache except for eager test builds. ChangesExternal module statistics
Persistent cache configuration
Estimated code review effort: 3 (Moderate) | ~20 minutes Possibly related issues
Possibly related PRs
Suggested labels: Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
In production, module concatenation absorbs the externals' importers
and the external modules themselves are flagged as orphans, so the
narrowed stats.toJson({ all: false, modules: true, cachedModules:
true }) returned no externals at all. RequireExternalsPlugin then
removed every mirrored require (meteor/*, Blaze .html) from the
generated meteor entry, breaking production runs at load time
(e2e: 'Cannot find package react-meteor-data', Blaze Template
undefined). Add orphanModules: true, which restores exact parity
with the full stats' top-level module list.
Verified with a standalone @rspack/core production build: cold and
warm (persistent cache) compiles, an external imported only from a
dynamic chunk, and the stale-require removal path all now match the
full-stats behavior exactly.
Part of meteor#14568.
|
The e2e failures on this PR were a real regression in the stats narrowing, now fixed in 00be428: in production, module concatenation absorbs the externals' importers and flags the external modules as orphans, so Fix: add CI should be meaningfully greener on the next run; the earlier flake-looking failures on the sibling PRs were unrelated (harness cascade where a failed app-create step leaves |
|
Minimal reproduction for the production stats-narrowing regression this PR guards against (standalone @rspack/core, no Meteor needed; exits non-zero on regression): https://github.com/vlasky/meteor-rspack-repro-stats-orphans |
|
@coderabbitai full review |
✅ Action performedFull review finished. |
nachocodoner
left a comment
There was a problem hiding this comment.
This is indeed a proper change that it will improve performance for large apps by:
- Keep separate Rspack caches warm across dev, production, client, server, and build contexts.
- Enable server production caching.
- Avoid serializing unnecessary compilation stats on rebuilds.
This will be included in the next Meteor 3.5.2.
Thanks for the fix
Low-risk subset of #14568 (items that are plain bugs or free wins; the larger architectural items in that issue - double compilation, double minification - are left for a follow-up with benchmarks).
Changes
1. Persistent cache directory now includes the mode
createCacheStrategyalready encoded the mode in the cache version (cache-developmentvscache-production) but not in the directory. rspack invalidates a persistent cache store on version mismatch, so development and production builds shared one directory and everymeteor run<->meteor buildswitch wiped the other mode's cache instead of keeping both warm. The directory is nownode_modules/.cache/rspack/<buildContext>-<side>-<mode>, so all four stores (client/server x development/production) coexist.2.
buildContextrestored in the secondcreateCacheStrategycallThe cache strategy is created twice (once before user/override configs are loaded, once after, with the fully resolved mode). The second call - the one that actually takes effect - dropped
buildContextfrom its options, so the effective cache directory collided across build contexts (e.g. customMETEOR_LOCAL_DIRsetups) and never matched the directory the first call used.3. Server production builds now get the persistent cache
The server config only applied the cache strategy for development, test, and native builds.
meteor build(andmeteor run --production) recompiled the entire server bundle cold every time. The condition is now "everything except eager test builds" (whose generated entry changes on every run, making a persistent cache useless).4.
RequireExternalsPluginno longer serializes full stats on every compilationThe plugin only needs module names, but called
stats.toJson({ modules: true }), which serializes the entire stats object (chunks, assets, reasons, module contents, ...) on every rebuild - a fixed cost that grows with app size, paid inside thedonehook. Narrowed to{ all: false, modules: true, cachedModules: true };cachedModules: truekeeps unchanged modules in the list on incremental rebuilds so their requires are not wrongly dropped.Verification
Tested with a Blaze test app (dev and prod runs, cold and warm):
meteor run: createsnode_modules/.cache/rspack/_build-client-developmentand_build-server-development; HTML import wiring throughRequireExternalsPluginintact after the stats narrowing (client-meteor.jsstill receives the.htmlimports).meteor run --production: creates_build-client-productionand_build-server-production- the server production store did not exist at all before change 3.@rspack/core's cache normalization to log every persistent-cache directory: exactly two compilers per run (client serve, server build), each receiving the expected directory.Part of #14568.
Summary by CodeRabbit
Performance
Build Reliability