fix(docs): stop 500s on client-side navigation into /docs - #77
Merged
Conversation
…R bundle
Every client-side navigation into /docs returned 500 in production:
Error: Cannot find module 'react'
Require stack:
- /var/task/_ssr/rolldown-runtime-B4iAMlE-.mjs
The route loader's server function never resolved, so its `data` was
undefined and the route component threw "Cannot read properties of
undefined (reading 'path')". Direct hits on /docs/* were unaffected
because those pages are prerendered; only the `_serverFn` call made
during client-side navigation reached the crashing module.
`use-sync-external-store` is CJS-only and reaches the graph through
`@base-ui/react`, which `fumadocs-twoslash` started depending on in 3.3.
With pnpm the package is only visible through a nested `node_modules`,
so Vite's SSR pass cannot externalise it and inlines it instead —
leaving its internal `require("react")` as a runtime `__require("react")`
even though React is external. Nitro's second pass then bundles React
but cannot rewrite code that was already emitted, so the call survives
into `.vercel/output` and resolves against a `node_modules` that does
not exist on the Vercel function.
Declaring the package as a direct dependency hoists it to the root
`node_modules`, so Vite externalises it and Nitro links the require to
the bundled React copy. The built bundle now reads `require_react()`
instead of `__require("react")`.
This is a workaround for nitrojs/nitro#4171 (rolldown/rolldown#10643) and
can be dropped once nitrojs/nitro#4365 ships `experimental.cjsRequireRewrite`.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
`taze -r -w major` across the workspace: vitest 5, @vitest/coverage-v8 5,
pnpm 12.3.4, tsdown 0.23, @tanstack/intent 0.3.8, @testing-library/jest-dom 7,
jsdom 30, lucide-react 1, fumadocs-twoslash 4, fumadocs 16.15.7,
@types/node 26, and assorted patch bumps. Followed by `pnpm dedupe`, which
collapses @trpc/server onto a single 11.18.0 copy — permix was resolving an
older 11.17.0 through its optional peer, and the two instances made the
tRPC middleware types structurally incompatible in the
express-trpc-react example.
TypeScript stays on ^6.0.3. Under 7.0.2 the permix build fails:
rolldown-plugin-dts rejects TS 7 with the `tsc` generator and falls back to
`tsgo`, which cannot emit declarations for the solution-style tsconfig.json
("tsgo did not generate dts file for ..."). svelte-check, @sveltejs/kit and
tsconfck also still want TS 5/6. Revisit once tsdown supports project
references with tsgo.
drizzle-orm is left alone — the registry request timed out during the run,
and the workspace intentionally tracks 1.0.0-rc rather than the 0.45.x
"latest" tag.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Clicking Documentation from the landing page showed "Something went wrong! — Cannot read properties of undefined (reading 'path')".
What was happening
The
/docs/$loader's server function was returning 500 on every call, sodatacame back undefined and the route component threw ondata.path. The real error was in the Vercel function log:Direct hits on
/docs/*were fine — those pages are prerendered. Only client-side navigation, which calls_serverFn, reached the crashing module. That also explains why dev never showed it: Node resolvesreactfrom the repo's ownnode_modulesthere.Root cause
Bisected to 64586bf.
fumadocs-twoslash3.2 → 3.3 pulled in@base-ui/react, which imports the CJS-onlyuse-sync-external-store/shim/with-selector.Vite's SSR pass externalises
reactbut cannot externalise the shim — under pnpm it is only reachable through a nestednode_modules— so it inlines it, leaving its internalrequire("react")as a runtime__require("react"). Nitro's second pass then bundles React but cannot rewrite code that was already emitted, so the call survives into.vercel/outputand resolves against anode_modulesthat does not exist on the function.Upstream: nitrojs/nitro#4171, rolldown/rolldown#10643. The fix PR (nitrojs/nitro#4365,
experimental.cjsRequireRewrite) is still open, and the latest nitro beta does not carry it.The fix
Declaring
use-sync-external-storeas a direct dependency ofdocshoists it to the rootnode_modules, so Vite externalises it and Nitro links the require to the bundled React copy.Alternatives tested in clean worktrees, all still broken: pinning
viteback to 8.0.16,ssr.external(TanStack Start ignores it), and bumpingnitroto the latest beta.Also here
taze -r -w majoracross the workspace (vitest 5, pnpm 12.3.4, tsdown 0.23, fumadocs-twoslash 4, jsdom 30, lucide-react 1,@types/node26, …), pluspnpm dedupeto collapse@trpc/serveronto one copy.TypeScript deliberately stays on
^6.0.3: under 7.0.2rolldown-plugin-dtsrejects thetscgenerator and falls back totsgo, which cannot emit declarations for the solution-styletsconfig.json.svelte-check,@sveltejs/kitandtsconfckalso still want TS 5/6.Verification
__require("react"); the shim now readsvar React = require_react()vite preview: landing page → Documentation click renders/docs,_serverFnreturns 200 (same request that 500s in production today)@base-uicomponent that pulls in the shim — workscheck-types14/14,lint,format:check, tests 301/301Worth confirming on this PR's Vercel preview before merging, since the failure only reproduces in a real Vercel function.
🤖 Generated with Claude Code