Repository navigation
Conversation
|
Important Draft PR not reviewedDraft PRs are not automatically reviewed by default.
To automatically review draft PRs, update your CodeRabbit configuration: reviews:
auto_review:
drafts: true
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 |
🦋 Changeset detectedLatest commit: 37e941d The changes in this PR will be included in the next version bump. This PR includes changesets to release 24 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 |
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
|
Warning Review the following alerts detected in dependencies. According to your organization's Security Policy, it is recommended to resolve "Warn" alerts. Learn more about Socket for GitHub.
|
|
View your CI Pipeline Execution ↗ for commit 37e941d
☁️ Nx Cloud last updated this comment at |
🚀 Changeset Version Preview14 package(s) bumped directly, 10 bumped as dependents. 🟨 Minor bumps
🟩 Patch bumps
|
Bundle Size Benchmarks
The following scenarios have bundle-size changes compared with the baseline:
Current gzip tracks all emitted client JS chunks. Initial gzip tracks only the entry/import graph. Trend sparkline is historical current gzip ending with this PR measurement; lower is better. |
Headroom after this PR (338-route apps, median ms; real = final perf matrix at c4cb7e8; floor = every compiler output replayed, i.e. a zero-cost compiler, from the earlier 498ac9b run. The two come from different runs, so treat ±8% as noise):
Compiler-only work can still win at most ~0.2–0.3 s on Router and ~1 s on Start, for React and Solid alike. Solid's floor is 1.5–4× React's because of HMR: route, loader and server-fn edits are 15–84% faster than main. Shared-module edits are at or below main in every cell and don't grow with app size (large React Start −2.40 ms [−2.70, −2.10], Solid Start −2.15 [−2.40, −1.90], React Router −0.10 [−0.40, 0.20]; React Start 23.2/23.6/23.5 ms small→large vs main 23.4/24.1/25.6). Where the Start second goes: the last full profile was taken before the final perf pass (Yuku 216 ms, own core 455, Start planners ~85, libraries ~12). That pass cut per-module core time by 12–23% in-process and compile-all by ~6% end to end. It took tier-0 bindings from Dev startup
Build / compile-all
MemoryDev heap after GC (react-start medium) is 87 MB after BytesClient: Router is byte-identical; Start is −35…−47 B gzip (shorter server-fn ids). Rsbuild minimal is +1/+3 B gzip (Rspack renumbers module ids; raw −22). Server: Vite −12…−823 B raw. react-start.rsbuild.full is +432 raw / +132 gzip because the handler stays in its module, so Rspack loses scope hoisting. A cache group that merges the provider chunk into the router chunk recovers part of it, but is blocked by an Rspack panic (web-infra-dev/rspack#16289). Route files importing another route file's export. A route file that imports an exported component or helper from another route file ( Effect-free built-in constructors. A module-level Route CSS stays eager, as on main; fully lazy route CSS needs a per-route asset loader in router-core. Root routes stay unsplit: splitting their error/notFound components cost SSR CPU, and the manifest preloaded that chunk on every page anyway. |
Merging this PR will regress 2 benchmarks2 warnings, 1 note
Warning Please fix the performance issues or acknowledge them on CodSpeed. Performance Changes
Tip Investigate this regression by commenting Comparing Footnotes
|
What this rewrite unlocks. Before: each transform re-parsed the previous one's output, APIs were matched by name, removal was guessed. Now: one shared analysis per module, recognition by binding identity across re-exports, edits on original ranges with exact maps, and per-output placement by reachability. Effort: S = days, M = weeks, L = a quarter. Top picks
Also enabledCompiler APIs
Diagnostics / devtools
Routing
RSC
Bundlers
Maintenance: React/Solid/Vue share every planner, so features reach all three at once. |
Root routes are not split, as on main: their component, errorComponent and notFoundComponent stay in the root route module in every env and bundler. Splitting them added a lazy round trip to every not-found and error render on the server, and the manifest preloaded the chunk on every page anyway. The J2.7 goal pin goes back to a known-bug pin. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…s change throttle Vite's chokidar drops a second `change` of the same path within 50 ms of the previous one, and the compiler is now fast enough that an HMR spec's next edit landed inside that window (hmr "publishes a failed route refresh and accepts the next HMR update", "multiple HMR saves"): the edit never reached the bundler. The file editor spaces writes of one file by 100 ms. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…(file:line:col) like the Vite host The Rsbuild/webpack hosts ended their messages with `\n at file:line:col`, which the Rsbuild error overlay spec (and its readers) could not position; both now use the Vite host's `message (file:line:col)` form. The overlay spec's line parser reads that form too, with the same assertions. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…read; test the core's small modules `cleanOrphanedDeclarations` asked `isPureExpression` about a class declaration, which only knows class expressions, so such a class never left with its erased reader; it now asks `isPureClass`. Adds unit tests for `WarningLedger`, the string/identifier helpers, parse diagnostics and expression wrappers, export summaries and their digest, and the orphan cleanup's multi-declarator and lazy declaration paths. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…rd-slash ids (Windows) The consumer's resolve and transform hooks compared Vite's module ids (forward slashes on every platform) with the recorded inputs' native paths (backslashes on Windows), so no fixture module was ever recognised there: every route's file was null and no import edge was recorded. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…art on Vite and Rsbuild `startGeneratorConfig` builds the generator configuration of both Start plugins: the router options as the Start config parsed them (Rsbuild no longer parses them again), the framework's target, one plugin list, and Start's footer computed at every print. Start's Vite plugin printed the first result of a function-form `routeTreeFileFooter` for the whole session; it now gives the function's current lines like Rsbuild and a router app's own footer (start-dev-route-tree-footer test: the Vite row fails before). The Vite route tree plugin uses the shared `escapeRegExp`. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…te files' real paths The generator records each route file's real path when it reads it and publishes the registry under both the scanned and the real path (a symlinked file or root); a real path that is another scanned route file stays that file's. The registry view no longer resolves symlinks per registry, `changedRoutePaths` no longer resolves each changed path (it could not for a deleted file: the previous registry names its real path now), and the generator's per-root real-path mapping goes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Vite's pre-bundled dependencies were opaque twice over: the start-env prefetch skipped a resolved `node_modules/.vite/` id (`StartEnvConfig .isOpaque`) besides the raw facts' `opaque` rule. The Vite host now gives the session its one extra rule for the raw facts (`opaque`); such a module's summary is null, so its values are unknown to the prefetch as before. `isOpaque` goes from the planner config and the prefetch. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ons in the registry The registry only inserted or overwrote ids, so on Vite an edit that removed a createServerFn left its id registered: the dev lookup re-exported a missing wrapper (a TypeError instead of an unknown id). The registry now keeps, per environment, the server functions each defining module's last compile reported; every compile replaces its module's snapshot (with none too, an untouched module included), and the entries are the aggregate. Rsbuild's finishMake replay replaces its environment's snapshots in the same registry instead of keeping its own copy; a deleted file is forgotten through one session operation. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…t tree drops The route HMR runtime kept, per route id, the evaluations, split chunks and (React) the refresh-ignored exports of every route a dev session ever saw, also after the route was removed or renamed. When it has the router read its route tree again, it now forgets the ids the router held before and no longer holds; ids the router never held stay (a route module evaluates before the route tree module that adds it runs). React's ignored exports remember their route id and are retired with it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ive in the compiler's hosts applyViteInvalidation, liveModules and loadDerivedSource are new in this PR and only Start uses them besides the router host: they move to router-utils' hosts/vite.ts, so @tanstack/router-plugin/vite gains no public exports. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…rce length PlanFacts.publishedSummaryDigest was written and never read; publish() stays for its side effect. EmitPlan.sourceLength had only test readers, which now check the published plan's revision. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ort flag ModuleSummary.rawRevision and hasImportOrExport had only test readers and enter no digest; buildSummary loses its revision parameter. RawFacts' rawRevision and ModuleAnalysis.hasImportOrExport stay. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
No gate reads GateContext.env and no prefetch reads PrefetchContext.env or .config since the router planners merged and start-env stopped reading its config: the planner contract drops them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- EdgeRecord.output and the edge builder's output parameter: edges are keyed by output already; - Tier1.tail: its last reader went with erasedParts' range; - the 'region' root kind: no planner roots a region; - PlanContext.fallbacks: planners use fallbackAt; the toy planners do too. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…g type Start imports HmrStyle and RouterPlannerEnv came back with the one-planner merge and have no importer. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…s environment type StartRsbuildEnvironment was StartCompilerEnvironment field for field, a leftover of the one Start session. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
AppInfo.env/.mode (plugin callbacks read root), BuildResult.bundler, OriginalPosition.source, RsbuildPluginHost.dev and RunNodeResult.stderr. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The .mdx page's warning is located in the page's source (the late import-protection pass maps it through MDX's source map), as the next test already requires: the first test asserts it too instead of accepting a report without coordinates, and the comments stop calling that a pinned bug. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Comments from before the one-router-planner merge said "route planners" or "split planner"; pointers at reach.ts for rules that moved to placement/ now name it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…nvironment that resolved it `vite build --watch` of a Start app failed before any edit: `Could not load \0%23tanstack-start-server-fn-resolver`. The raw facts read a virtual module through every environment's loader in turn; in watch mode the client and SSR builds run at once, so the live client build's `this.load` of the SSR-only resolver registered a failed module. The core's `loadVirtual` now receives the environment asking for the facts (the one that resolved the id), and the Vite host loads through that environment's loader only. The Start build harness builds Vite apps in watch mode too (`watchEdits`). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Three gaps of `vite build --watch` once the first build succeeds: - the server environment built at the same time as the client, so its server-function resolver listed what the client had compiled so far (often none): Start's build loop now waits for the client's first watch build, as a one-shot build does; - every client rebuild emptied the server-function registry while the server environment rebuilt from it: a watch rebuild keeps it (each compile replaces its module's functions, a deleted file is forgotten); - no invalidation ran on a file event, so an unchanged importer reused a plan validated against stale raw facts (a module an edit marked server-only stayed in the client): `watchChange` runs the one invalidation operation in build mode too. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… chunk only The server `router` cache group merges the router's chunk with the server-function providers' to save production bytes; its `chunks` test ran on every dev rebuild (~1,600 calls, ~6 ms per server compilation). The dev server needs only the shared group (one instance per module). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…unchanged After every dev compilation `retain` re-identified every plan, raw-facts entry and import-protection record to drop state of files the compilation no longer depends on; with the same files as the last compilation (every plain edit) there is nothing to drop. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e first compilation only The `finishMake` passes looking for modules restored from Rspack's persistent cache (unjudged importers, unconfirmed edge modules) walked every module of every dev compilation. Rspack loads the cache's module graph only in a compiler's first compilation: the persistent cache's `before_build_module_graph` returns for `is_rebuild` compilations, and every compilation after the first is a rebuild (Rspack 2.0.0 to 2.2.9). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… thrown, on both bundlers Rsbuild watch builds already let the first build fail (a test relies on it) and described the rebuild; the Vite watch builds now do the same, and `StartBuild.firstBuild` holds what the first build reported, so a test can check that it succeeded. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…build wants them Like the router plugin's Vite host: a build without `build.sourcemap` reads no map, and import protection locates violations through the input map and the raw files, not through Start's output map. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… again when its import changed meanwhile A module the cache restores must be compiled again when a module it imports changed what it is while no build ran (here: it became a server fn builder, so the handler built on it leaves the client). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…module Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…-less SWC code frame Rspack 2.1.6 (web-infra-dev/rspack#14921) prints SWC's code frame header as `[line:col]`, without the file, which the overlay shows on its `File:` line. Since 5ebce55 moved the e2e apps to Rspack 2.2.9, the server entry's line read as null. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Summary
Every TanStack build-time compiler now runs on one shared core built on Yuku. That covers route code splitting and route HMR (router-plugin), all of Start's transforms (server functions, environment separation,
<Hydrate>, RSC CSS, import protection) and the route generator. Babel,babel-dead-code-eliminationand the Prettier hot path are gone.On main, Babel took ~90% of compiler time. On 333- and 1,485-route React and Solid apps, builds are 2.1–4.8× faster and dev cold start is 2.1–5.0× faster. Start builds also end with 3–10× less heap.
Each module and environment gets one parse and one plan. Outputs no longer depend on transform or request order, and source maps are exact. The oracle's known-bug pins drop from 874 to 45 (36 of those keep main's behaviour on purpose), and 29 open issues are fixed.
Architecture
Full map:
packages/router-utils/src/compiler/README.md.?tsr-split=…,?tss-hydrate=…,?tss-serverfn-split,?tss-serverfn-handler) and facts (import edges, server-fn registry, diagnostics, dependencies).start-env → hydrate → rsc-css → router → import-edges. APIs are recognised by binding, through an abstract value domain. Cross-module summaries come from raw text, never from the bundler pipeline.OutputBuilderwrites VLQ maps directly and composes them with input maps.?tss-serverfn-handler, which loads on the first call. The defining module runs once.TSR_COMPILER_VERIFY=1, on in all tests). Every output is re-parsed and checked: no assignment to an import, glue imports resolve, each effect is emitted once, and extracted outputs make no eager env-module reads.invalidate(); no Yuku objects are retained. We own the hosts: a native Vite plugin, a Rspack/webpack loader, and Start Rsbuild loaders (withbuildInforeplay for the persistent cache). Start's Vite and Rsbuild hosts share one bundler-free Start session; hosts keep only bundler wiring. unplugin remains only for the generator and esbuild.Performance
Measured with
benchmarks/compiler-perfat774eba05a4against mainda2adec76d. Cells marked ² were re-measured ate80188ee7b. Both checkouts run in parallel on mirrored core sets, over 6 paired rounds; values are medians. Times are in ms and heap in MB. Large = 1,485 route files.³ On main, this HMR run aborted in 5 of 6 rounds and full-reloaded 13 edits. This PR had no failures and no reloads.
e80188ee7bvs npm main, 6 paired rounds):064d29003a, 129 apps, medians of per-app Δ): build −12.1%, dev ready −18.8%, first render −10.5%, peak RSS −1.7%.774eba05a4).e80188ee7b); kroma +3.8% (+64 MB,774eba05a4).b25984c166): +308 B raw on Vite*.full, +602 B raw / +78 B gzip on react-start.rsbuild.full (da12a6f6ba).da12a6f6ba; CodSpeed notes base and head ran on different runner types).All 11 cells, HMR, Vue, memory, bytes
Medium = 333 route files. Δ CIs are 95% t intervals of the paired log ratios.
¹ react-start plus a generated dependency graph and tanstack.com's
manualChunks. Dev SSR fails on both sides here because of a?urlwasm asset in the harness, so<Hydrate>HMR is not measured.<Hydrate>is −8…−46% on Vite and −30 / −38% on Rsbuild ². Shared-module edits show no significant slowdown.eedc638e42).18ef570edc, KB/cycle, PR vs main): react-start Vite −0.7 vs 11.2, react-router Vite 2.3 vs 6.3, react-start Rsbuild 20.9. The soak found five records that grew with deleted files; all are fixed and tested. The remaining growth is upstream (vite#23907, rsbuild#8736).fdc48254c8).eedc638e42): webpack build −38%, RSC build −74%.498ac9be17): 715 → 94 ms. The react-start build floor drops from 1,629 to 779 ms.b25984c166):*.fullscenarios are −35…−47 B gzip, thanks to shorter server-fn ids.*.fullscenario. react-start.rsbuild.full is +602 raw / +78 gzip (da12a6f6ba; was +696 / +326):__roota second concatenation root, so router modules shared with the route tree stay unhoisted;GET /never calls; main / eager handlers / this PR): Vite ~88 / ~145 / ~88 ms, Rsbuild ~57 / ~122 / ~57 ms.Testing
The oracle (
packages/compiler-test-utils/oracle) drives real bundlers, dev servers and browsers through public APIs only. Main's bugs are pinned as.fails.80d1890bed).fails)b25984c166: all 8 unit and integration targets pass (4,247/4,247). WithCOMPILER_TESTS_PINS=run, each pin fails for its documented reason.e80188ee7b: the Test job passes 881/881 Nx tasks. Compiler Platforms passes on all platforms except Linux arm64, which failed one router-utils unit test,pipeline.test.ts(f), an in-flight dependency-only edit.Beyond the oracle:
Every PR bug these found is fixed, with a regression test. The fuzz differences that remain are pre-existing on main or upstream.
Results
Corpus (
b25984c166vs npm main):390ca815c3.(/[;@babel/traversecopies, which break main's DCE.Leak check (139 builds per side,
5ff36a1816): 0 leaks here. Main leaks inmockmode; that case is pinned.Fuzzers:
Coverage: lines 91.1 → 91.5%, branch arms 79.2 → 80.2%. No bug found; 2 unused paths deleted.
Vite 6 / 7 (
5ff36a1816): the 13 router-plugin e2e projects pass on Vite 6.0.15, 6.4.5 and 7.3.7. Split Solid and Vue routes update in place, where main full-reloads.Remaining fail pins (45)
sideEffects, an exported component another route's chunk imports loads with that chunk..pageasjavascript/auto) importing a denied file is reported. Rspack rules select by resource.bundledDev, a factory that becomes a server-fn builder keeps its handler. This needs the full-bundle API.Behaviour changes
routeTree.gen.tsformatting changes once. The file is printed in yourquoteStyle/semicolons.enableRouteTreeFormattingnow defaults tofalse(trueuses Prettier, loaded lazily). Custom templates are inserted as written.serverFns.generateFunctionIdreceives the stable key (greetUser) asfunctionName, and default ids are shorter.Invalid server function ID). Main answered a 500TypeError.?tsr-split=export~Name), together with their augmentations. On one corpus app: −179 KB initial, +2.4 KB total.this(Handle route callbacks that reference this during code splitting #8688), and splits that never settle.onViolationreturningfalsegets the real module;fullPath:'/', not''.@vitejs/plugin-react: an edit that makes a split chunk throw while it loads reloads the page (split components are refresh boundaries, which plugin-react makes self-import, and Vite reloads failures in a circular import). The fixing edit applies in place.addHmris always on, and the server honours yourcodeSplittingOptions.deleteNodes(Rsbuild used to drop it).spa.enableddev serves the shell;server.compressis no longer forced;@rspack/core≥ 2.2.9 (fix: reset MultiCompiler done state on watch restart web-infra-dev/rspack#15865); peer ranges are unchanged.rsbuild build --watchpicks up route files created while watching.vite build --watchof a Start app builds and rebuilds against each edit (the server builds after the client's first build).autoCodeSplitting: truethrows;@babel/coreis no longer transitive, so declare it if a plugin needs it (e.g. React Compiler).codeSplittingOptions.compilerPlugins, StartcompilerTransforms,serverFnProviderModuleDirectivesandStartCompilerPlugin;react-start-rsc/plugin/rscCssTransform, replaced byrsc: { loadCssExpression, providerDirective };/compiler);format,inferFullPath,checkRouteFullPathUniquenessandwriteIfDifferent.onRouteTreeChangednow receives{ model };plugin.hmr.style(andHmrOptions): the style follows the bundler. On Vite, its only other value turned route HMR off.@tanstack/router-core/hmrand@tanstack/{react,solid,vue}-router/hmr.19 changesets. Minor bumps: router-utils, router-generator, router-plugin, router-core, start-plugin-core and react-start-rsc. Everything else gets a patch.
Follow-ups
createServerFn({ serializable: true }).__rootcache group: unblocked now that the Rspack panic (rspack#16289) is fixed..mapfill once Rspack can fill it natively (rspack#16348).tsr generatewrite different routeTree.gen.ts (Start footer added, then stripped) #8437 CLI half, server routes with a.tsextension gets the wrong boilerplate while creating the file. #4462, Vite HMR blank page when editing__root.tsx(Solid SSR) #6331 (solid-refresh#91), [@tanstack/react-start/plugin/rsbuild] tanstackStart() eclipses the client environment's output.assetPrefix, blocking downstream plugins #7827 andssr: falseroutes still bundle components in server output #6400.Upstream issues filed
✅ fixed · ✖ closed without a fix · ○ open
Yuku: 26 ✅ fixed, 1 ✖ closed. Four of the fixes (Duplicated render after
nevigate#288, Routes transitions don't use transitions? #289, How to resolve act(...) errors in components containing Link #291, Update peerDependency react-location to match higher versions #292) shipped in Yuku 0.25.0; the PR pins 0.26.0. fix: render errorElement when route loader is rejected #290 was closed because the fix is deferred to Yuku's upcoming transformer; we don't need it.All 27
✅ #202 purity comments · ✅ #203 codegen SIGBUS · ✅ #204 JSX refs for
_/$/Unicode · ✅ #229import X = ns.Y· ✅ #230 decorators afterexport· ✅ #231 JSXText entities · ✅ #232 false duplicate export · ✅ #237 empty JSX container comments · ✅ #244 WASM stale bytes · ✅ #247unwraptyping · ✅ #248copyAst()· ✅ #251export {} from· ✅ #252import()specifiers · ✅ #253 big-endian decoding · ✅ #254 JSX attribute mapping · ✅ #255 postfix++parens · ✅ #256for (init;;)no-in· ✅ #257 private method overloads · ✅ #258import type {}· ✅ #259super()in computed key · ✅ #260 JSX text after</>· ✅ #287(a?.b)!.c· ✅ #288 JSXText escaping · ✅ #289 stale JSXTextraw· ✖ #290stripkeeps type-only exports · ✅ #291 surrogate-pair spans · ✅ #292 Annex B functionsVite:
Rolldown:
this.load()returns null in bundled-dev HMRmoduleSideEffectsin watch modeMissingFactoryErrorRspack:
sourcesContententry is emitted as"", notnullsourcesContentfrom the module resource at map emissionRsbuild:
solid-refresh (all ○):
__root.tsx(Solid SSR) #6331)Others:
\ncounts as a line breaktypeof xkeepsxencodeInto('')returns stale dataIssues
server.handlersstrip — server code and node-only imports ship in the client bundle #8514autoCodeSplitting: falsedoes not avoid it) #7754Split…when two @babel/traverse copies are installed #8715bundledDev: true#7535.andhandler/server/client, silently disabling transform after AST-roundtripping pre-plugins #7280autoCodeSplittingis enabled #6667server.compress: false, overriding user config #8544Other issues:
tsr generatewrite different routeTree.gen.ts (Start footer added, then stripped) #8437, partially addressed: Start's footer followsquoteStyle/semicolons, buttsr generatestill writes none.strictExecutionOrder: trueonssr.Supersedes #8805, #8504, #8630, #8721, #8780, #8773, #8756, #8755, #8732, #8686, #8682, #8681, #8061, #8541, #8493, #8481, #8459, #8455, #7892, #8515, #7281, #8269, #8628, #8797, #8662, #8296, #8215, #8454, #8276, #8675, #8540, #8523, #8524, #8680, #8684, #8642, #8749, #8801, #7338, #8656, #8798, #8818
Implementation obsolete (still needs a re-port after merge): #8804, #7693, #7766, #7872, #8291, #8293, #8277, #8799, #8800, #6748, #8256, #8057, #7925
How to review
The diff is +164k/−75k lines in 2,000 files. The
compiler-tests/baselinebranch accounts for +102k/−42k of it, and most of the rest is tests and regenerated route trees. Product code (packages/*/src) is +31k/−23k in 211 files.router-utils/src/compiler/README.md, then readidentity→source/analysis→units/mutation→rewrite→reach→plan→emit→values/summary/facts→cache/pipeline→verify. Keeptests/helpers.tsandtests/placement.test.tsopen alongside.router-plugin/ARCHITECTURE-CODE-SPLITTING.md, thensrc/planners/.start-plugin-core/src/planners/(start-env,hydrate,rsc-css,edges), withsrc/compiler/,src/server-fns/andsrc/import-protection/.router-plugin/src/hosts/.src/vite/compiler-plugin.ts.src/rsbuild/(readCOMPILER_ARCHITECTURE.mdfirst).router-generator(AGENTS.md,analyze/,model/,print/).router-core/src/hmr.tsand{react,solid,vue}-router/src/hmr.ts.start-client-core/src/createServerFn.ts.README.md,SPEC.mdandKNOWN-BUGS.md.To reproduce the measurements, see:
packages/compiler-test-utils/oracle/README.mdbenchmarks/compiler-perf/README.md(run.mjs,compare.mjs,soak-analyze.mjs)pnpm benchmark:bundle-size:runscripts/benchmarks/bundle-size/server.mjsThis PR was written with AI assistance: Claude Code agents working under a human architect. Their work was checked against the oracle, e2e, perf and bytes gates above.
🤖 Generated with Claude Code