fix: add next shim js variants#482
Conversation
commit: |
|
/bigbonk review |
There was a problem hiding this comment.
Good diagnosis and solid fix. Moving .js variant handling from resolve.alias (in the shim map) instead of resolveId is the right approach — optimizeDeps pre-bundling uses alias resolution before plugins' resolveId hooks run, so the old resolveId-based .js stripping never kicked in for dep scanning. The removal of ssr.noExternal: ["nuqs"] from the fixture is a nice UX win — users shouldn't need that workaround.
A few notes below. The main concern is the fragility of the new test assertion.
Stale comment (not in diff): The resolveId filter comment at line ~1455-1457 still references "next/router.js" as an example of what the filter matches, but .js variant handling has been moved out of resolveId. That handler no longer does anything with .js suffixes. Worth updating the comment to avoid confusion (minor, non-blocking).
| const optimizedAdapter = readFileSync( | ||
| path.join(fixtureRoot, "node_modules", ".vite", "deps", "nuqs_adapters_next_app.js"), | ||
| "utf8", | ||
| ); | ||
|
|
||
| expect(optimizedAdapter).toContain("packages/vinext/dist/shims/navigation.js"); |
There was a problem hiding this comment.
This assertion reads a Vite-internal pre-bundled file and checks for a monorepo-specific path substring. Two fragility concerns:
- Dep filename:
nuqs_adapters_next_app.jsis derived from Vite's dep flattening heuristic. If Vite changes the naming scheme (or nuqs restructures its exports), this path breaks. - Path substring:
"packages/vinext/dist/shims/navigation.js"is specific to the monorepo workspace layout where vinext is a linked workspace package. If vinext is installed from npm (or the monorepo structure changes), the absolute path embedded in the pre-bundled file will differ.
The negative assertion on line 239 (not.toContain("node_modules/.pnpm/next@")) is actually the more important and more robust check — it proves real Next.js was excluded from the pre-bundle. Consider either:
- Making the positive assertion use a regex like
/shims\/navigation\.js/(matches regardless of absolute path prefix) - Or dropping line 238 entirely and relying on the negative assertion, which is the core invariant
| "next/headers": path.join(shimsDir, "headers"), | ||
| "next/headers.js": path.join(shimsDir, "headers"), | ||
| "next/font/google": path.join(shimsDir, "font-google"), | ||
| "next/font/google.js": path.join(shimsDir, "font-google"), |
There was a problem hiding this comment.
Minor: next/font/google.js and next/font/local.js don't actually exist as files in the next package (font resolution uses package.json exports maps, not file-backed .js files). Including them is harmless and defensive, but the comment on line 956 says "file-backed in next/package.json" which doesn't apply to these two. Non-blocking — just noting the inaccuracy.
| // Build the shim alias map. Exact `.js` variants are included for the | ||
| // public Next entrypoints that are file-backed in `next/package.json`. | ||
| // Some libraries (for example `nuqs`) import `next/navigation.js` | ||
| // directly; aliasing the `.js` form ensures optimizeDeps pre-bundles | ||
| // vinext's shim instead of real Next. |
There was a problem hiding this comment.
Nice — the updated comment is much clearer about the why (optimizeDeps pre-bundling) rather than just the what.
|
Review posted successfully. Here's a summary of the feedback I left on PR #482: Overall: The fix is correct. Moving Comments posted:
|
|
Updated |
|
/bigbonk re-review |
There was a problem hiding this comment.
Good fix. Moving .js variant handling from resolveId into the alias map is the correct approach since optimizeDeps pre-bundling resolves aliases before plugin hooks run. The removal of the ssr.noExternal: ["nuqs"] workaround confirms the fix works at the right layer.
A few minor notes below — none are blocking.
Stale resolveId filter comment (not in diff, so can't inline): Lines 1453-1455 still reference "next/router.js" as an example of what the filter matches, but .js variant handling has been moved out of resolveId. The handler no longer processes .js suffixes. Consider updating to:
// Hook filter: only invoke JS for next/* imports and virtual:vinext-* modules.
// Matches "next/navigation", "virtual:vinext-rsc-entry",
// and \0-prefixed re-imports from @vitejs/plugin-rsc.
| // Build the shim alias map. Exact `.js` variants are included for the | ||
| // public Next entrypoints that are file-backed in `next/package.json`. |
There was a problem hiding this comment.
Nit: the comment says "file-backed in next/package.json" but that's not accurate for all entries. next/config.js and next/amp.js don't exist on disk (no top-level .js files). next/font/google and next/font/local resolve through a directory index.js, not google.js/local.js.
The .js aliases for entries that don't have a real .js file are harmless (defensive), but the comment could be simpler:
| // Build the shim alias map. Exact `.js` variants are included for the | |
| // public Next entrypoints that are file-backed in `next/package.json`. | |
| // Build the shim alias map. Exact `.js` variants are included because | |
| // some libraries (for example `nuqs`) import `next/navigation.js` |
|
|
||
| const optimizedAdapter = readFileSync(path.join(depsDir, optimizedAdapterFile!), "utf8"); | ||
|
|
||
| expect(optimizedAdapter).toMatch(/shims\/navigation\.js/); |
There was a problem hiding this comment.
Good use of regex instead of a full path substring — this is resilient to different install layouts (monorepo workspace link vs npm install). Together with the negative assertion on line 244 this covers the invariant well.
|
Review submitted successfully. Here's a summary of the feedback: Verdict: Approved The fix is correct. Comments posted:
|
|
Thanks, I was going to do this today so you've saved me some time! |
It looks like
resolveIddoes not work foroptimizeDeps