Conversation
Adds `unwasm/plugin/rspack` alongside the existing rollup-compatible plugin, reusing the shared binding generation. Instead of unplugin's loader-based approach, `.wasm` requests are redirected during `normalModuleFactory.beforeResolve` to a generated module served through rspack's built-in `VirtualModulesPlugin`. This keeps the plugin in a single file (rspack loaders must be path strings) and avoids the native `webassembly/async` handler entirely, since rspack never sees a `.wasm` module. Rspack-specific adaptations: - `\0`-prefixed virtual ids are rewritten to plain schemes, as module identifiers cross into the native side. - `esmImport` registers a `module-import` external so `import()` is preserved, then emits the binaries and rewrites the specifiers to relative paths in `processAssets` (the `renderChunk` analogue). The shared `esm-integration-missing-import` assertion now matches on the error message as well as the code: rspack reports an `ESModulesLinkingError` without a `code` field. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Warning Review limit reached
Next review available in: 9 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (3)
📝 WalkthroughWalkthroughRspack support adds a dedicated wasm transformation plugin, package exports and optional peer metadata, documentation, a dependency-tracking loader, and shared test coverage using rspack. ChangesRspack integration
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant RspackCompiler
participant UnwasmRspackPlugin
participant VirtualModulesPlugin
participant WasmAssets
RspackCompiler->>UnwasmRspackPlugin: Resolve wasm request
UnwasmRspackPlugin->>WasmAssets: Read and register binary
UnwasmRspackPlugin->>VirtualModulesPlugin: Write generated binding
RspackCompiler->>UnwasmRspackPlugin: Process output assets
UnwasmRspackPlugin->>WasmAssets: Emit wasm and rewrite imports
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 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 |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/plugin/rspack.ts`:
- Around line 221-229: Update the WebAssembly parse-failure handling in
registerAsset to accept and thread opts, then replace the direct
compilation.warnings.push call with the existing warn() helper so opts.silent
suppresses the warning consistently with the ESM fallback path. Preserve the
existing warning message, cause, and moduleFallback behavior.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: e59ef159-8e6d-4688-af2b-d6f120fcd6b3
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (5)
README.mdbuild.config.tspackage.jsonsrc/plugin/rspack.tstest/plugin.test.ts
# Conflicts: # README.md
Follow-up fixes from review of the rspack plugin. - The parse cache was keyed on the binary's content hash alone, so a file imported both plainly and as `?module` in one build reused whichever interface was registered first. When the `?module` form won, the plain import generated `export const default = ...`. The requested mode is now part of the binding's identity. - Editing a `.wasm` never propagated in watch mode. Bindings are virtual modules, and rspack replays the already-rewritten request for cached dependencies, so `beforeResolve` never saw the binary again. Bindings are now refreshed on `watchRun`, and a small dependency-declaring loader ties each binding to its source binary so rspack actually invalidates it. - `resolveSync` throws instead of returning `false`, so the existing guard was dead code and unresolved imports surfaced as a plugin stack trace rather than rspack's own "Module not found". Requests carrying inline loader syntax are skipped for the same reason. - Emitted binaries were tracked per compiler and never pruned, so watch rebuilds kept emitting binaries for imports that no longer existed. They are now derived from what the output actually references. - `silent` did not suppress parse-failure warnings. Also renames the helpers module so its filename is valid on Windows, and adds rspack regression tests covering each of the above plus code splitting under rspack's default `asyncChunks`. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/plugin/rspack.ts`:
- Line 37: Update the dependency-loader path initialization around
DEPENDENCY_LOADER to avoid using import.meta.dirname on unsupported Node
runtimes, or declare the required Node version floor through the package
engines.node configuration. Ensure loading rspack-loader.cjs remains compatible
with all supported runtimes.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 1586ba4f-033c-46bf-8a6e-3dcc44fb1f57
📒 Files selected for processing (6)
build.config.tssrc/plugin/rspack-loader.cjssrc/plugin/rspack.tstest/fixture/missing-wasm.mjstest/fixture/mixed-module-import.mjstest/plugin.test.ts
| * Rspack resolves loaders by path, so this ships as a plain `.cjs` file next to | ||
| * the built plugin (see `build.config.ts`) rather than being bundled into it. | ||
| */ | ||
| const DEPENDENCY_LOADER = join(import.meta.dirname, "rspack-loader.cjs"); |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Check declared Node engines and any existing usage of import.meta.dirname
fd -t f 'package.json' -d 2 --exec sh -c 'echo "== {} =="; jq ".engines // empty" {}'
rg -nP 'import\.meta\.dirname' --type=tsRepository: unjs/unwasm
Length of output: 200
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== root package.json =="
cat -n package.json | sed -n '1,220p'
echo
echo "== examples/package.json =="
cat -n examples/package.json | sed -n '1,220p'
echo
echo "== references to Node version/support =="
rg -n --hidden --glob '!**/node_modules/**' --glob '!**/dist/**' -e 'engines\.node|node version|Node\.js|Nodejs|import\.meta\.dirname' .Repository: unjs/unwasm
Length of output: 3180
Add a Node engine floor import.meta.dirname requires Node 20.11+/21.2+, but package.json doesn’t declare an engines.node constraint. Add one or use a supported path resolver here to avoid load-time failures on older runtimes.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/plugin/rspack.ts` at line 37, Update the dependency-loader path
initialization around DEPENDENCY_LOADER to avoid using import.meta.dirname on
unsupported Node runtimes, or declare the required Node version floor through
the package engines.node configuration. Ensure loading rspack-loader.cjs remains
compatible with all supported runtimes.
Source: Linters/SAST tools
…ache Follow-up fixes from review of the rspack plugin: - Move the `esmImport` specifier rewrite from `PROCESS_ASSETS_STAGE_OPTIMIZE_INLINE` to `PROCESS_ASSETS_STAGE_OPTIMIZE`, ahead of minification and source map generation. The rewrite shortens the line it sits on, so running it after `DEV_TOOLING` left the emitted `.map` describing the longer `unwasm-external:` text and every mapping to the right of the import pointing at the wrong original column. Use `ReplaceSource` so the chunk's mappings survive the edit. - Prune bindings whose module has left the graph. They were kept for the compiler's lifetime, regenerated on every rebuild and holding their binary in the watch set. Skipped on failed builds, where the graph is incomplete. - Match JS output assets with a regex, so `.cjs` chunks and names carrying a query (`[name].js?[contenthash]`) are rewritten too. - Treat `?module&foo` and `?foo&module` as module requests, matching the Rollup plugin's `?module` handling. - Escape `EXTERNAL_PREFIX` when building its `RegExp`. Tests: regression guards for the source map and pruning fixes, both verified to fail without their fix. Watch test now rejects on build errors instead of timing out, and derives fixture hashes rather than hard-coding them. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds an rspack plugin alongside the existing rollup-compatible one, exported as
unwasm/plugin/rspack.Approach
All binding generation (
runtime/binding,runtime/utils,tools/parseWasm) is shared with the rollup plugin — only the bundler integration differs..wasmrequests are redirected duringnormalModuleFactory.hooks.beforeResolveto a generated module served through rspack's built-inexperiments.VirtualModulesPlugin. Since rspack never sees a.wasmmodule, the nativewebassembly/asynchandler (on by default in rspack v2) is bypassed, so notype: "javascript/auto"workaround is needed for the binary itself.Two rspack-specific adaptations:
\0-prefixed virtual ids become plainunwasm-external:/ a real helpers path, since module identifiers cross into the native (Rust) side.esmImportregisters amodule-importexternal to keepimport()intact, then rewrites specifiers to relative paths and emits the referenced binaries inprocessAssets— the analogue of the rolluprenderChunkpass.Generation happens at resolve time, which does not survive rebuilds on its own: rspack replays the already-rewritten request for cached dependencies. Bindings are therefore refreshed on
watchRun, and a small dependency-declaring loader (src/plugin/rspack-loader.cjs, shipped next to the bundled plugin) ties each binding to its source binary so rspack invalidates it when the.wasmchanges.Tests
test/plugin.test.tsruns the five shared scenarios against rspack (inline, esmImport incl. the Miniflare/Cloudflare eval, module, esm-integration, missing-import), plus rspack-specific tests for mixed?module/plain imports, unresolvable imports, code splitting under rspack's defaultasyncChunks, and watch-mode invalidation. 60 passing; lint and types clean.One shared assertion was loosened:
esm-integration-missing-importassertedcode === "MISSING_EXPORT", and rspack reportsESModulesLinkingErrorwith nocode, so it now matches the code or"was not found", plus a new check that the message namesbadImportName. rollup/rolldown/vite still satisfy it via the strict disjunct.@rspack/coreis added as a devDependency and an optional peer dependency; the plugin imports it asimport typeonly and reaches builtins viacompiler.rspackat runtime.Note on the
asyncChunks: falsein the test configAn earlier revision of this description claimed that setting was required because rspack's async chunk loader breaks Miniflare. That is true of the Miniflare test specifically, but it was not the whole story, and the wording implied the plugin was fine under async chunks without that having been verified.
It has now been verified. The failure originally observed with default
asyncChunkscame from the test's constantoutput.filename: "index.mjs"colliding with the separate runtime chunk thatlibrary.type: "modern-module"emits — not from the plugin. With[name].mjsthe build is clean and the output executes correctly, and there is now a regression test covering exactly that.Summary by CodeRabbit
.wasm) imports into generated JS bindings../plugin/rspackexport for consuming the rspack plugin.esmImportis enabled.?modulevs plain import behavior, chunking expectations, and watch-mode refresh behavior.