Repository navigation
fix(start-plugin-core): restore Rsbuild import-protection mocks from persistent cache - #8798
mattcosta7 wants to merge 6 commits into
Conversation
…persistent cache Rspack's persistent cache restores modules without rerunning loaders, so the import-protection loader never rewrote the virtual mock modules that restored importers reference, and warm builds and dev restarts failed with Module not found while dropping their violations. Regenerate a requested mock from its file name, which fully encodes its contents, before Rspack resolves it.
🦋 Changeset detectedLatest commit: 54ebe15 The changes in this PR will be included in the next version bump. This PR includes changesets to release 5 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
No actionable comments were generated in the recent review.
|
| Layer / File(s) | Summary |
|---|---|
Query-based mock-module transport packages/start-plugin-core/src/rsbuild/mock-module.ts, packages/start-plugin-core/src/rsbuild/mock-loader.ts, packages/start-plugin-core/src/rsbuild/mock.ts, packages/start-plugin-core/vite.config.ts |
Mock IDs now use query parameters and optional encoded payloads. mock-loader selects the silent, runtime, or edge mock source. The build entries include the new loader and mock resource. |
Import-protection integration and diagnostics packages/start-plugin-core/src/rsbuild/import-protection-loader.ts, packages/start-plugin-core/src/rsbuild/import-protection.ts, packages/start-plugin-core/tests/rsbuild/import-protection.test.ts, packages/start-plugin-core/src/rsbuild/INTERNALS-import-protection.md |
The import-protection loader emits mock IDs instead of ensuring virtual modules through shared state. Rsbuild registers mock-loader and excludes its resource from the import-protection rule. Diagnostic resource lookup maps mock requests to their embedded resource paths. Tests and internals documentation reflect the updated setup. |
Persistent-cache regression coverage e2e/react-start/import-protection/tests/import-protection.spec.ts, .changeset/rsbuild-import-protection-persistent-cache.md |
The E2E test builds twice with a shared cache and checks warnings, importer reuse, violation locations, traces, and getRequest() snippets. A patch changeset records the issue. |
Priority:
Estimated code review effort: 3 (Moderate) | ~20 minutes
Change: Bug fix
Sequence Diagram(s)
sequenceDiagram
participant transformImportProtection
participant Rspack
participant mock-loader
participant getModuleResource
transformImportProtection->>Rspack: Emit query-specific mock module ID
Rspack->>mock-loader: Load matching mock.js request
mock-loader->>Rspack: Return selected mock module source
Rspack->>getModuleResource: Pass mock resource for diagnostic lookup
getModuleResource->>Rspack: Return normalized embedded resource path
Possibly related PRs
- TanStack/router#8801: Both changes affect Rsbuild import-protection graph handling, including mock-module resource mapping and diagnostic trace construction.
Suggested labels: package: start-plugin-core, documentation
Suggested reviewers: schiller-manuel, symind, beaussan
Merge Risk: 
Minimal · up to 54ebe
-
No actionable issue was established that should prevent merging after normal checks.
Pre-merge checks: 
4 · 
1
-
Failed checks: 1 warning Passed checks: 4 passed-
Full details: Description check
-
Explanation
The description follows the required template. It explains the persistent-cache failure, the mock-loader solution, tests, validation results, checklist completion, changeset status, and AI assistance disclosure.
-
Full details: Docstring Coverage
-
Explanation
Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentation-only edits and deletions within surviving functions are included; unchanged diff context and fully deleted functions are excluded. Analyzed 6 functions across 8 files. (2 skipped: 2 unsupported.)
Resolution
Write docstrings for the functions missing them to satisfy the coverage threshold.
-
Finishing Touches
-
🧪 Generate unit tests (beta)
-
- Create a new PR
-
- Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
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 @coderabbitai help to get the list of available commands.
… from their request An importer Rspack restores from its persistent cache (performance.buildCache) in a new process requests edge modules nothing registered: the warm build failed with "Can't resolve .../edge.<key>.mjs" for every edge module. The importer's request now carries the module's content (?tss-ip=<base64url>, checked against the key that digests it); a normalModuleFactory beforeResolve tap defines unknown edge modules and the runtime from it before they resolve. The rewrite of every known edge module at thisCompilation is gone. Tests: Rsbuild cold+warm builds with buildCache in error and mock mode and with an onViolation veto; Rsbuild dev edits that add a .server import, add or remove a server-only marker of an unchanged importer's dependency (upstream #8798, #8801 scenarios). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…build restored modules A module Rspack restores from its persistent cache is not compiled, so the edge index that gives trace steps their specifier and position knew nothing of it: a warm build's violation traces lost those steps' locations. Each compiled module's Rspack buildInfo record now carries its indexed edges, replayed at finishMake for a module the index does not know (replayed by its canonical resource, the compile's id). Ports upstream #8798's e2e test (cold vs warm Rsbuild build with performance.buildCache: no errors, identical warnings). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
I think a dedicated The import-protection post-loader still checks the compiled code and rewrites denied imports, but the requests now point to a real, package-owned This makes each mock independently resolvable and rebuildable even when its importer comes from persistent cache. It removes the The regression test in this PR passes with this approach. I also strengthened it to check that the warm build actually reuses an importer containing mock requests, and that two distinct specifier diagnostics retain their usage locations and traces. All 88 Rsbuild import-protection E2E tests pass locally, along with the core unit/type/lint and package checks. The 18 bundle scenarios show no gzip growth. These checks were run on macOS; I haven't run Windows E2E or measured a build-time speedup. |
…ock-loader fix(start-plugin-core): build Rsbuild import-protection mocks with a dedicated loader
Thanks, I pulled those into this branch and i'll update the related prs to avoid the old impl here! |
|
@mattcosta7 Maybe we can mark this PR as ready for review. |
🎯 Changes
With
performance.buildCacheenabled, Rspack restores modules from its persistent cache without rerunning their loaders. Rsbuild import protection wrote its mock modules (node_modules/.virtual/import-protection/<env>/mock-*.mjs) throughVirtualModulesPluginas a side effect of the import-protection loader, so importers restored from cache pointed at mocks that were never written. In theimport-protectionfixture the warm build failed:and client violations dropped from 11 to 8. A warm
rsbuild devrestart failed the same way.Mocks are now ordinary modules with their own loader (implementation by @SyMind):
mock.jsentry, with the mock kind (silent/runtime/edge), environment and base64url payload in the query.mock-loadergenerates each mock's source from its query using the existing shared mock generators. The mock entry is excluded from the post-loader.VirtualModulesPlugin, the shared write/ready/pending state, and the earlierbeforeResolverestore hook. A JSbeforeResolvetap runs on every resolve and cost ~8% of thebasicproduction build.Tests
persistent cache restores import-protection mocks and violations(Rsbuild-only,e2e/react-start/import-protection) runs a cold build and then a warm build with a persistent cache. It requires:@tanstack/react-start/serverkeep their importer location, trace and snippetIt fails without the fix. Unit test updated for the mock-loader rule (including Windows separators).
Validation
@tanstack/start-plugin-core:test:unit(872),test:types,test:eslint,test:buildimport-protectione2e, all toolchains: Rsbuild 88 passed; Vite SSR and bundled-dev 87 passed + 1 skippedhmr28/28;server-functionsRsbuild SSR 53/53 and Rsbuild persistent cache 3/3;basice2e, all variantsmain(5 alternating runs):import-protection1,439 → 1,426 ms,basic2,825 → 2,838 ms (noise)Written with AI coding assistants.
✅ Checklist
🚀 Release Impact
Summary by CodeRabbit