@rangojs/router 0.0.0-experimental.10 → 0.0.0-experimental.100
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +9 -0
- package/README.md +1037 -4
- package/dist/bin/rango.js +1619 -157
- package/dist/vite/index.js +5762 -2301
- package/dist/vite/plugins/cloudflare-protocol-loader-hook.mjs +76 -0
- package/package.json +71 -63
- package/skills/breadcrumbs/SKILL.md +252 -0
- package/skills/cache-guide/SKILL.md +294 -0
- package/skills/caching/SKILL.md +93 -23
- package/skills/composability/SKILL.md +172 -0
- package/skills/debug-manifest/SKILL.md +12 -8
- package/skills/document-cache/SKILL.md +18 -16
- package/skills/fonts/SKILL.md +6 -4
- package/skills/handler-use/SKILL.md +364 -0
- package/skills/hooks/SKILL.md +367 -71
- package/skills/host-router/SKILL.md +218 -0
- package/skills/i18n/SKILL.md +276 -0
- package/skills/intercept/SKILL.md +176 -8
- package/skills/layout/SKILL.md +124 -3
- package/skills/links/SKILL.md +304 -25
- package/skills/loader/SKILL.md +474 -47
- package/skills/middleware/SKILL.md +207 -37
- package/skills/migrate-nextjs/SKILL.md +562 -0
- package/skills/migrate-react-router/SKILL.md +769 -0
- package/skills/mime-routes/SKILL.md +15 -11
- package/skills/parallel/SKILL.md +272 -1
- package/skills/prerender/SKILL.md +467 -65
- package/skills/rango/SKILL.md +89 -21
- package/skills/response-routes/SKILL.md +152 -91
- package/skills/route/SKILL.md +305 -14
- package/skills/router-setup/SKILL.md +210 -32
- package/skills/server-actions/SKILL.md +739 -0
- package/skills/streams-and-websockets/SKILL.md +283 -0
- package/skills/theme/SKILL.md +9 -8
- package/skills/typesafety/SKILL.md +333 -86
- package/skills/use-cache/SKILL.md +324 -0
- package/skills/view-transitions/SKILL.md +212 -0
- package/src/__internal.ts +102 -4
- package/src/bin/rango.ts +312 -15
- package/src/browser/action-coordinator.ts +97 -0
- package/src/browser/action-response-classifier.ts +99 -0
- package/src/browser/app-shell.ts +52 -0
- package/src/browser/app-version.ts +14 -0
- package/src/browser/event-controller.ts +136 -68
- package/src/browser/history-state.ts +80 -0
- package/src/browser/intercept-utils.ts +52 -0
- package/src/browser/link-interceptor.ts +24 -4
- package/src/browser/logging.ts +55 -0
- package/src/browser/merge-segment-loaders.ts +20 -12
- package/src/browser/navigation-bridge.ts +374 -561
- package/src/browser/navigation-client.ts +228 -70
- package/src/browser/navigation-store.ts +97 -55
- package/src/browser/navigation-transaction.ts +297 -0
- package/src/browser/network-error-handler.ts +61 -0
- package/src/browser/partial-update.ts +376 -315
- package/src/browser/prefetch/cache.ts +314 -0
- package/src/browser/prefetch/fetch.ts +282 -0
- package/src/browser/prefetch/observer.ts +65 -0
- package/src/browser/prefetch/policy.ts +48 -0
- package/src/browser/prefetch/queue.ts +191 -0
- package/src/browser/prefetch/resource-ready.ts +77 -0
- package/src/browser/rango-state.ts +152 -0
- package/src/browser/react/Link.tsx +255 -71
- package/src/browser/react/NavigationProvider.tsx +152 -24
- package/src/browser/react/context.ts +11 -0
- package/src/browser/react/filter-segment-order.ts +55 -0
- package/src/browser/react/index.ts +15 -12
- package/src/browser/react/location-state-shared.ts +95 -53
- package/src/browser/react/location-state.ts +60 -15
- package/src/browser/react/mount-context.ts +6 -1
- package/src/browser/react/nonce-context.ts +23 -0
- package/src/browser/react/shallow-equal.ts +27 -0
- package/src/browser/react/use-action.ts +29 -51
- package/src/browser/react/use-client-cache.ts +5 -3
- package/src/browser/react/use-handle.ts +30 -120
- package/src/browser/react/use-link-status.ts +6 -5
- package/src/browser/react/use-navigation.ts +44 -65
- package/src/browser/react/use-params.ts +78 -0
- package/src/browser/react/use-pathname.ts +47 -0
- package/src/browser/react/use-reverse.ts +99 -0
- package/src/browser/react/use-router.ts +83 -0
- package/src/browser/react/use-search-params.ts +56 -0
- package/src/browser/react/use-segments.ts +85 -99
- package/src/browser/response-adapter.ts +73 -0
- package/src/browser/rsc-router.tsx +246 -64
- package/src/browser/scroll-restoration.ts +127 -52
- package/src/browser/segment-reconciler.ts +243 -0
- package/src/browser/segment-structure-assert.ts +16 -0
- package/src/browser/server-action-bridge.ts +510 -603
- package/src/browser/shallow.ts +6 -1
- package/src/browser/types.ts +158 -48
- package/src/browser/validate-redirect-origin.ts +29 -0
- package/src/build/generate-manifest.ts +84 -23
- package/src/build/generate-route-types.ts +39 -828
- package/src/build/index.ts +4 -5
- package/src/build/route-trie.ts +85 -32
- package/src/build/route-types/ast-helpers.ts +25 -0
- package/src/build/route-types/ast-route-extraction.ts +98 -0
- package/src/build/route-types/codegen.ts +102 -0
- package/src/build/route-types/include-resolution.ts +418 -0
- package/src/build/route-types/param-extraction.ts +48 -0
- package/src/build/route-types/per-module-writer.ts +128 -0
- package/src/build/route-types/router-processing.ts +618 -0
- package/src/build/route-types/scan-filter.ts +85 -0
- package/src/build/runtime-discovery.ts +231 -0
- package/src/cache/background-task.ts +34 -0
- package/src/cache/cache-key-utils.ts +44 -0
- package/src/cache/cache-policy.ts +125 -0
- package/src/cache/cache-runtime.ts +342 -0
- package/src/cache/cache-scope.ts +167 -307
- package/src/cache/cf/cf-cache-store.ts +573 -21
- package/src/cache/cf/index.ts +13 -3
- package/src/cache/document-cache.ts +116 -77
- package/src/cache/handle-capture.ts +81 -0
- package/src/cache/handle-snapshot.ts +41 -0
- package/src/cache/index.ts +1 -15
- package/src/cache/memory-segment-store.ts +191 -13
- package/src/cache/profile-registry.ts +73 -0
- package/src/cache/read-through-swr.ts +134 -0
- package/src/cache/segment-codec.ts +256 -0
- package/src/cache/taint.ts +153 -0
- package/src/cache/types.ts +72 -122
- package/src/client.rsc.tsx +6 -1
- package/src/client.tsx +118 -302
- package/src/component-utils.ts +4 -4
- package/src/components/DefaultDocument.tsx +5 -1
- package/src/context-var.ts +156 -0
- package/src/debug.ts +19 -9
- package/src/errors.ts +77 -7
- package/src/handle.ts +55 -10
- package/src/handles/MetaTags.tsx +73 -20
- package/src/handles/breadcrumbs.ts +66 -0
- package/src/handles/index.ts +1 -0
- package/src/handles/meta.ts +30 -13
- package/src/host/cookie-handler.ts +21 -15
- package/src/host/errors.ts +8 -8
- package/src/host/index.ts +4 -7
- package/src/host/pattern-matcher.ts +27 -27
- package/src/host/router.ts +61 -39
- package/src/host/testing.ts +8 -8
- package/src/host/types.ts +15 -7
- package/src/host/utils.ts +1 -1
- package/src/href-client.ts +65 -45
- package/src/index.rsc.ts +138 -21
- package/src/index.ts +206 -51
- package/src/internal-debug.ts +11 -0
- package/src/loader.rsc.ts +25 -143
- package/src/loader.ts +27 -10
- package/src/network-error-thrower.tsx +3 -1
- package/src/outlet-context.ts +1 -1
- package/src/outlet-provider.tsx +45 -0
- package/src/prerender/param-hash.ts +4 -2
- package/src/prerender/store.ts +159 -13
- package/src/prerender.ts +397 -29
- package/src/response-utils.ts +28 -0
- package/src/reverse.ts +231 -121
- package/src/root-error-boundary.tsx +41 -29
- package/src/route-content-wrapper.tsx +7 -4
- package/src/route-definition/dsl-helpers.ts +1134 -0
- package/src/route-definition/helper-factories.ts +200 -0
- package/src/route-definition/helpers-types.ts +483 -0
- package/src/route-definition/index.ts +55 -0
- package/src/route-definition/redirect.ts +101 -0
- package/src/route-definition/resolve-handler-use.ts +155 -0
- package/src/route-definition.ts +1 -1431
- package/src/route-map-builder.ts +162 -123
- package/src/route-name.ts +53 -0
- package/src/route-types.ts +66 -9
- package/src/router/content-negotiation.ts +215 -0
- package/src/router/debug-manifest.ts +72 -0
- package/src/router/error-handling.ts +9 -9
- package/src/router/find-match.ts +160 -0
- package/src/router/handler-context.ts +418 -86
- package/src/router/intercept-resolution.ts +35 -20
- package/src/router/lazy-includes.ts +237 -0
- package/src/router/loader-resolution.ts +359 -128
- package/src/router/logging.ts +251 -0
- package/src/router/manifest.ts +98 -32
- package/src/router/match-api.ts +196 -261
- package/src/router/match-context.ts +4 -2
- package/src/router/match-handlers.ts +441 -0
- package/src/router/match-middleware/background-revalidation.ts +108 -93
- package/src/router/match-middleware/cache-lookup.ts +415 -86
- package/src/router/match-middleware/cache-store.ts +91 -29
- package/src/router/match-middleware/intercept-resolution.ts +48 -21
- package/src/router/match-middleware/segment-resolution.ts +73 -9
- package/src/router/match-pipelines.ts +10 -45
- package/src/router/match-result.ts +154 -35
- package/src/router/metrics.ts +240 -15
- package/src/router/middleware-cookies.ts +55 -0
- package/src/router/middleware-types.ts +209 -0
- package/src/router/middleware.ts +373 -371
- package/src/router/navigation-snapshot.ts +182 -0
- package/src/router/pattern-matching.ts +292 -52
- package/src/router/prerender-match.ts +502 -0
- package/src/router/preview-match.ts +98 -0
- package/src/router/request-classification.ts +310 -0
- package/src/router/revalidation.ts +152 -39
- package/src/router/route-snapshot.ts +245 -0
- package/src/router/router-context.ts +41 -21
- package/src/router/router-interfaces.ts +484 -0
- package/src/router/router-options.ts +618 -0
- package/src/router/router-registry.ts +24 -0
- package/src/router/segment-resolution/fresh.ts +756 -0
- package/src/router/segment-resolution/helpers.ts +268 -0
- package/src/router/segment-resolution/loader-cache.ts +199 -0
- package/src/router/segment-resolution/revalidation.ts +1407 -0
- package/src/router/segment-resolution/static-store.ts +67 -0
- package/src/router/segment-resolution.ts +21 -1315
- package/src/router/segment-wrappers.ts +291 -0
- package/src/router/substitute-pattern-params.ts +56 -0
- package/src/router/telemetry-otel.ts +299 -0
- package/src/router/telemetry.ts +300 -0
- package/src/router/timeout.ts +148 -0
- package/src/router/trie-matching.ts +111 -39
- package/src/router/types.ts +17 -9
- package/src/router/url-params.ts +49 -0
- package/src/router.ts +642 -2011
- package/src/rsc/handler-context.ts +45 -0
- package/src/rsc/handler.ts +864 -1114
- package/src/rsc/helpers.ts +181 -19
- package/src/rsc/index.ts +0 -20
- package/src/rsc/loader-fetch.ts +229 -0
- package/src/rsc/manifest-init.ts +90 -0
- package/src/rsc/nonce.ts +14 -0
- package/src/rsc/origin-guard.ts +141 -0
- package/src/rsc/progressive-enhancement.ts +395 -0
- package/src/rsc/response-error.ts +37 -0
- package/src/rsc/response-route-handler.ts +360 -0
- package/src/rsc/rsc-rendering.ts +256 -0
- package/src/rsc/runtime-warnings.ts +42 -0
- package/src/rsc/server-action.ts +360 -0
- package/src/rsc/ssr-setup.ts +128 -0
- package/src/rsc/types.ts +52 -11
- package/src/search-params.ts +230 -0
- package/src/segment-content-promise.ts +67 -0
- package/src/segment-loader-promise.ts +122 -0
- package/src/segment-system.tsx +187 -38
- package/src/server/context.ts +333 -59
- package/src/server/cookie-store.ts +190 -0
- package/src/server/fetchable-loader-store.ts +37 -0
- package/src/server/handle-store.ts +113 -15
- package/src/server/loader-registry.ts +24 -64
- package/src/server/request-context.ts +603 -109
- package/src/server.ts +35 -155
- package/src/ssr/index.tsx +107 -30
- package/src/static-handler.ts +126 -0
- package/src/theme/ThemeProvider.tsx +21 -15
- package/src/theme/ThemeScript.tsx +5 -5
- package/src/theme/constants.ts +5 -2
- package/src/theme/index.ts +4 -14
- package/src/theme/theme-context.ts +4 -30
- package/src/theme/theme-script.ts +21 -18
- package/src/types/boundaries.ts +158 -0
- package/src/types/cache-types.ts +198 -0
- package/src/types/error-types.ts +192 -0
- package/src/types/global-namespace.ts +100 -0
- package/src/types/handler-context.ts +764 -0
- package/src/types/index.ts +88 -0
- package/src/types/loader-types.ts +209 -0
- package/src/types/request-scope.ts +126 -0
- package/src/types/route-config.ts +170 -0
- package/src/types/route-entry.ts +120 -0
- package/src/types/segments.ts +167 -0
- package/src/types.ts +1 -1757
- package/src/urls/include-helper.ts +207 -0
- package/src/urls/index.ts +53 -0
- package/src/urls/path-helper-types.ts +372 -0
- package/src/urls/path-helper.ts +364 -0
- package/src/urls/pattern-types.ts +107 -0
- package/src/urls/response-types.ts +108 -0
- package/src/urls/type-extraction.ts +372 -0
- package/src/urls/urls-function.ts +98 -0
- package/src/urls.ts +1 -1282
- package/src/use-loader.tsx +161 -81
- package/src/vite/debug.ts +184 -0
- package/src/vite/discovery/bundle-postprocess.ts +181 -0
- package/src/vite/discovery/discover-routers.ts +376 -0
- package/src/vite/discovery/gate-state.ts +171 -0
- package/src/vite/discovery/prerender-collection.ts +486 -0
- package/src/vite/discovery/route-types-writer.ts +258 -0
- package/src/vite/discovery/self-gen-tracking.ts +73 -0
- package/src/vite/discovery/state.ts +117 -0
- package/src/vite/discovery/virtual-module-codegen.ts +203 -0
- package/src/vite/index.ts +15 -2063
- package/src/vite/plugin-types.ts +103 -0
- package/src/vite/plugins/cjs-to-esm.ts +98 -0
- package/src/vite/plugins/client-ref-dedup.ts +131 -0
- package/src/vite/plugins/client-ref-hashing.ts +117 -0
- package/src/vite/plugins/cloudflare-protocol-loader-hook.d.mts +23 -0
- package/src/vite/plugins/cloudflare-protocol-loader-hook.mjs +76 -0
- package/src/vite/plugins/cloudflare-protocol-stub.ts +214 -0
- package/src/vite/{expose-action-id.ts → plugins/expose-action-id.ts} +107 -64
- package/src/vite/plugins/expose-id-utils.ts +299 -0
- package/src/vite/plugins/expose-ids/export-analysis.ts +296 -0
- package/src/vite/plugins/expose-ids/handler-transform.ts +209 -0
- package/src/vite/plugins/expose-ids/loader-transform.ts +74 -0
- package/src/vite/plugins/expose-ids/router-transform.ts +127 -0
- package/src/vite/plugins/expose-ids/types.ts +45 -0
- package/src/vite/plugins/expose-internal-ids.ts +816 -0
- package/src/vite/plugins/performance-tracks.ts +96 -0
- package/src/vite/plugins/refresh-cmd.ts +127 -0
- package/src/vite/plugins/use-cache-transform.ts +336 -0
- package/src/vite/plugins/version-injector.ts +109 -0
- package/src/vite/plugins/version-plugin.ts +266 -0
- package/src/vite/{virtual-entries.ts → plugins/virtual-entries.ts} +23 -14
- package/src/vite/plugins/virtual-stub-plugin.ts +29 -0
- package/src/vite/rango.ts +497 -0
- package/src/vite/router-discovery.ts +1423 -0
- package/src/vite/utils/ast-handler-extract.ts +517 -0
- package/src/vite/utils/banner.ts +36 -0
- package/src/vite/utils/bundle-analysis.ts +137 -0
- package/src/vite/utils/manifest-utils.ts +70 -0
- package/src/vite/utils/package-resolution.ts +161 -0
- package/src/vite/utils/prerender-utils.ts +222 -0
- package/src/vite/utils/shared-utils.ts +170 -0
- package/CLAUDE.md +0 -43
- package/src/browser/lru-cache.ts +0 -69
- package/src/browser/request-controller.ts +0 -164
- package/src/cache/memory-store.ts +0 -253
- package/src/href-context.ts +0 -33
- package/src/router.gen.ts +0 -6
- package/src/urls.gen.ts +0 -8
- package/src/vite/expose-handle-id.ts +0 -209
- package/src/vite/expose-loader-id.ts +0 -426
- package/src/vite/expose-location-state-id.ts +0 -177
- package/src/vite/expose-prerender-handler-id.ts +0 -429
- package/src/vite/package-resolution.ts +0 -125
- /package/src/vite/{version.d.ts → plugins/version.d.ts} +0 -0
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bundle Post-Processing
|
|
3
|
+
*
|
|
4
|
+
* Handles handler code eviction from prerender/static chunks and
|
|
5
|
+
* injection of collected prerender/static data into the RSC entry bundle.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { resolve } from "node:path";
|
|
9
|
+
import { readFileSync, writeFileSync, existsSync } from "node:fs";
|
|
10
|
+
import { evictHandlerCode } from "../utils/bundle-analysis.js";
|
|
11
|
+
import { copyStagedBuildAssets } from "../utils/prerender-utils.js";
|
|
12
|
+
import type { DiscoveryState } from "./state.js";
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Post-process the RSC bundle: evict handler code and inject
|
|
16
|
+
* prerender/static data as importable asset modules.
|
|
17
|
+
*/
|
|
18
|
+
export function postprocessBundle(state: DiscoveryState): void {
|
|
19
|
+
const hasPrerenderData =
|
|
20
|
+
state.prerenderManifestEntries &&
|
|
21
|
+
Object.keys(state.prerenderManifestEntries).length > 0;
|
|
22
|
+
const hasStaticData =
|
|
23
|
+
state.staticManifestEntries &&
|
|
24
|
+
Object.keys(state.staticManifestEntries).length > 0;
|
|
25
|
+
if (!hasPrerenderData && !hasStaticData) return;
|
|
26
|
+
|
|
27
|
+
// Find RSC entry (recorded in generateBundle, fallback to dist/rsc/index.js)
|
|
28
|
+
const rscEntryPath = resolve(
|
|
29
|
+
state.projectRoot,
|
|
30
|
+
"dist/rsc",
|
|
31
|
+
state.rscEntryFileName ?? "index.js",
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
// 1. Evict handler code from whichever chunks contain handler exports.
|
|
35
|
+
// handlerChunkInfoMap/staticHandlerChunkInfoMap are populated by generateBundle
|
|
36
|
+
// after the production RSC build. In Vite 6 multi-environment builds, the
|
|
37
|
+
// RSC build runs twice (analysis + production). The maps are cleared at the
|
|
38
|
+
// start of each generateBundle pass so only production data is used here.
|
|
39
|
+
const evictionTargets: Array<{
|
|
40
|
+
infos: Iterable<import("./state.js").ChunkInfo>;
|
|
41
|
+
fnName: string;
|
|
42
|
+
brand: string;
|
|
43
|
+
label: string;
|
|
44
|
+
}> = [
|
|
45
|
+
{
|
|
46
|
+
infos: state.handlerChunkInfoMap.values(),
|
|
47
|
+
fnName: "Prerender",
|
|
48
|
+
brand: "prerenderHandler",
|
|
49
|
+
label: "handler code from RSC bundle",
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
infos: state.staticHandlerChunkInfoMap.values(),
|
|
53
|
+
fnName: "Static",
|
|
54
|
+
brand: "staticHandler",
|
|
55
|
+
label: "static handler code",
|
|
56
|
+
},
|
|
57
|
+
];
|
|
58
|
+
|
|
59
|
+
for (const target of evictionTargets) {
|
|
60
|
+
for (const info of target.infos) {
|
|
61
|
+
const chunkPath = resolve(state.projectRoot, "dist/rsc", info.fileName);
|
|
62
|
+
try {
|
|
63
|
+
const code = readFileSync(chunkPath, "utf-8");
|
|
64
|
+
const result = evictHandlerCode(
|
|
65
|
+
code,
|
|
66
|
+
info.exports,
|
|
67
|
+
target.fnName,
|
|
68
|
+
target.brand,
|
|
69
|
+
);
|
|
70
|
+
if (result) {
|
|
71
|
+
writeFileSync(chunkPath, result.code);
|
|
72
|
+
const savedKB = (result.savedBytes / 1024).toFixed(1);
|
|
73
|
+
console.log(
|
|
74
|
+
`[rsc-router] Evicted ${target.label} (${savedKB} KB saved): ${info.fileName}`,
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
} catch (replaceErr: any) {
|
|
78
|
+
console.warn(
|
|
79
|
+
`[rsc-router] Failed to evict ${target.label}: ${replaceErr.message}`,
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
state.handlerChunkInfoMap.clear();
|
|
85
|
+
state.staticHandlerChunkInfoMap.clear();
|
|
86
|
+
|
|
87
|
+
// 2. Write prerender data as separate importable asset modules
|
|
88
|
+
// and inject a lazy manifest loader into the RSC entry.
|
|
89
|
+
if (hasPrerenderData && existsSync(rscEntryPath)) {
|
|
90
|
+
const rscCode = readFileSync(rscEntryPath, "utf-8");
|
|
91
|
+
// Check for the specific injection marker to avoid double-injection.
|
|
92
|
+
if (!rscCode.includes("__prerender-manifest.js")) {
|
|
93
|
+
try {
|
|
94
|
+
let totalBytes = copyStagedBuildAssets(
|
|
95
|
+
state.projectRoot,
|
|
96
|
+
Object.values(state.prerenderManifestEntries!),
|
|
97
|
+
);
|
|
98
|
+
|
|
99
|
+
const manifestMap: Record<string, string> = {};
|
|
100
|
+
for (const [key, assetFileName] of Object.entries(
|
|
101
|
+
state.prerenderManifestEntries!,
|
|
102
|
+
)) {
|
|
103
|
+
manifestMap[key] = `./assets/${assetFileName}`;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const manifestCode = [
|
|
107
|
+
`const m=JSON.parse('${JSON.stringify(manifestMap).replace(/'/g, "\\'")}');`,
|
|
108
|
+
`export function loadPrerenderAsset(s){return import(s)}`,
|
|
109
|
+
`export default m;`,
|
|
110
|
+
"",
|
|
111
|
+
].join("\n");
|
|
112
|
+
const manifestPath = resolve(
|
|
113
|
+
state.projectRoot,
|
|
114
|
+
"dist/rsc/__prerender-manifest.js",
|
|
115
|
+
);
|
|
116
|
+
writeFileSync(manifestPath, manifestCode);
|
|
117
|
+
totalBytes += Buffer.byteLength(manifestCode);
|
|
118
|
+
|
|
119
|
+
const injection = `globalThis.__loadPrerenderManifestModule = () => import("./__prerender-manifest.js");\n`;
|
|
120
|
+
writeFileSync(rscEntryPath, injection + rscCode);
|
|
121
|
+
|
|
122
|
+
const totalKB = (totalBytes / 1024).toFixed(1);
|
|
123
|
+
console.log(
|
|
124
|
+
`[rsc-router] Wrote prerender assets (${totalKB} KB total, ${Object.keys(state.prerenderManifestEntries!).length} entries)`,
|
|
125
|
+
);
|
|
126
|
+
} catch (err: any) {
|
|
127
|
+
throw new Error(
|
|
128
|
+
`[rsc-router] Failed to write prerender assets: ${err.message}`,
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// 3. Write static handler data as separate importable asset modules
|
|
135
|
+
// and inject a __STATIC_MANIFEST import into the RSC entry.
|
|
136
|
+
if (hasStaticData && existsSync(rscEntryPath)) {
|
|
137
|
+
const rscCode = readFileSync(rscEntryPath, "utf-8");
|
|
138
|
+
if (!rscCode.includes("__static-manifest.js")) {
|
|
139
|
+
try {
|
|
140
|
+
const manifestEntries: string[] = [];
|
|
141
|
+
let totalBytes = copyStagedBuildAssets(
|
|
142
|
+
state.projectRoot,
|
|
143
|
+
Object.values(state.staticManifestEntries!),
|
|
144
|
+
);
|
|
145
|
+
|
|
146
|
+
for (const [handlerId, assetFileName] of Object.entries(
|
|
147
|
+
state.staticManifestEntries!,
|
|
148
|
+
)) {
|
|
149
|
+
manifestEntries.push(
|
|
150
|
+
`${JSON.stringify(handlerId)}:()=>import("./assets/${assetFileName}")`,
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// Set the global inside the manifest module so it is assigned
|
|
155
|
+
// during module evaluation (before dependent modules like
|
|
156
|
+
// segment-resolution.ts run their top-level initializers).
|
|
157
|
+
const manifestCode = `const m={${manifestEntries.join(",")}};globalThis.__STATIC_MANIFEST=m;export default m;\n`;
|
|
158
|
+
const manifestPath = resolve(
|
|
159
|
+
state.projectRoot,
|
|
160
|
+
"dist/rsc/__static-manifest.js",
|
|
161
|
+
);
|
|
162
|
+
writeFileSync(manifestPath, manifestCode);
|
|
163
|
+
totalBytes += Buffer.byteLength(manifestCode);
|
|
164
|
+
|
|
165
|
+
// The import ensures the manifest module is evaluated early.
|
|
166
|
+
// The global is already set inside the module itself.
|
|
167
|
+
const injection = `import "./__static-manifest.js";\n`;
|
|
168
|
+
writeFileSync(rscEntryPath, injection + rscCode);
|
|
169
|
+
|
|
170
|
+
const totalKB = (totalBytes / 1024).toFixed(1);
|
|
171
|
+
console.log(
|
|
172
|
+
`[rsc-router] Wrote static assets (${totalKB} KB total, ${Object.keys(state.staticManifestEntries!).length} entries)`,
|
|
173
|
+
);
|
|
174
|
+
} catch (err: any) {
|
|
175
|
+
throw new Error(
|
|
176
|
+
`[rsc-router] Failed to write static assets: ${err.message}`,
|
|
177
|
+
);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
@@ -0,0 +1,376 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Router Discovery
|
|
3
|
+
*
|
|
4
|
+
* Core discovery logic: imports the user's entry file via the RSC
|
|
5
|
+
* environment's module runner, generates manifests for each discovered
|
|
6
|
+
* router, and builds route tries for O(path_length) matching.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import {
|
|
10
|
+
buildCombinedRouteMapForRouterFile,
|
|
11
|
+
formatNestedRouterConflictError,
|
|
12
|
+
findNestedRouterConflict,
|
|
13
|
+
} from "../../build/generate-route-types.js";
|
|
14
|
+
import {
|
|
15
|
+
flattenLeafEntries,
|
|
16
|
+
buildRouteToStaticPrefix,
|
|
17
|
+
} from "../utils/manifest-utils.js";
|
|
18
|
+
import type { DiscoveryState, PrecomputedEntry } from "./state.js";
|
|
19
|
+
import {
|
|
20
|
+
expandPrerenderRoutes,
|
|
21
|
+
renderStaticHandlers,
|
|
22
|
+
} from "./prerender-collection.js";
|
|
23
|
+
import { createRangoDebugger, timed, NS } from "../debug.js";
|
|
24
|
+
|
|
25
|
+
const debug = createRangoDebugger(NS.discovery);
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Import the user's entry via RSC runner, generate manifests for each
|
|
29
|
+
* discovered router, build route tries, and optionally run prerender
|
|
30
|
+
* expansion and static handler rendering (build mode only).
|
|
31
|
+
*
|
|
32
|
+
* Returns the imported `@rangojs/router/server` module so the caller
|
|
33
|
+
* can access the RouterRegistry and manifest setters.
|
|
34
|
+
*/
|
|
35
|
+
export async function discoverRouters(
|
|
36
|
+
state: DiscoveryState,
|
|
37
|
+
rscEnv: any,
|
|
38
|
+
): Promise<any> {
|
|
39
|
+
if (!state.resolvedEntryPath) return;
|
|
40
|
+
|
|
41
|
+
// Import the entry file via RSC environment.
|
|
42
|
+
// For node preset: this is the router file (createRouter() registers in RouterRegistry).
|
|
43
|
+
// For cloudflare preset: this is the worker entry (which imports the router).
|
|
44
|
+
await timed(debug, "inner: import entry", () =>
|
|
45
|
+
rscEnv.runner.import(state.resolvedEntryPath),
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
// Import the router package to access the registry
|
|
49
|
+
const serverMod = await timed(
|
|
50
|
+
debug,
|
|
51
|
+
"inner: import @rangojs/router/server",
|
|
52
|
+
() => rscEnv.runner.import("@rangojs/router/server"),
|
|
53
|
+
);
|
|
54
|
+
let registry: Map<string, any> = serverMod.RouterRegistry;
|
|
55
|
+
|
|
56
|
+
if (!registry || registry.size === 0) {
|
|
57
|
+
// No RSC routers found directly. Check for host routers with lazy handlers
|
|
58
|
+
// that need to be resolved to trigger sub-app createRouter() calls.
|
|
59
|
+
try {
|
|
60
|
+
const hostRegistry: Map<string, any> | undefined =
|
|
61
|
+
serverMod.HostRouterRegistry;
|
|
62
|
+
|
|
63
|
+
if (hostRegistry && hostRegistry.size > 0) {
|
|
64
|
+
console.log(
|
|
65
|
+
`[rsc-router] Found ${hostRegistry.size} host router(s), resolving lazy handlers...`,
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
for (const [, entry] of hostRegistry) {
|
|
69
|
+
for (const route of entry.routes) {
|
|
70
|
+
if (typeof route.handler === "function") {
|
|
71
|
+
try {
|
|
72
|
+
await route.handler();
|
|
73
|
+
} catch {
|
|
74
|
+
// Lazy handler may fail in temp server context, that's OK
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
if (entry.fallback && typeof entry.fallback.handler === "function") {
|
|
79
|
+
try {
|
|
80
|
+
await entry.fallback.handler();
|
|
81
|
+
} catch {
|
|
82
|
+
// Fallback handler may fail in temp server context
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Re-read RouterRegistry - sub-app createRouter() calls should have populated it
|
|
88
|
+
const freshServerMod = await rscEnv.runner.import(
|
|
89
|
+
"@rangojs/router/server",
|
|
90
|
+
);
|
|
91
|
+
const freshRegistry: Map<string, any> = freshServerMod.RouterRegistry;
|
|
92
|
+
|
|
93
|
+
if (freshRegistry && freshRegistry.size > 0) {
|
|
94
|
+
// Update references so the manifest generation below uses the fresh data
|
|
95
|
+
Object.assign(serverMod, freshServerMod);
|
|
96
|
+
registry = freshRegistry;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
} catch {
|
|
100
|
+
// Host-router discovery is best-effort; skip if unavailable
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// If still no routers after host router resolution, fail
|
|
104
|
+
if (!registry || registry.size === 0) {
|
|
105
|
+
throw new Error(
|
|
106
|
+
`[rsc-router] No routers found in registry after importing ${state.resolvedEntryPath}`,
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Import build utilities for manifest generation
|
|
112
|
+
const buildMod = await timed(
|
|
113
|
+
debug,
|
|
114
|
+
"inner: import @rangojs/router/build",
|
|
115
|
+
() => rscEnv.runner.import("@rangojs/router/build"),
|
|
116
|
+
);
|
|
117
|
+
const generateManifestFull = buildMod.generateManifestFull;
|
|
118
|
+
|
|
119
|
+
debug?.("inner: found %d router(s) in registry", registry.size);
|
|
120
|
+
|
|
121
|
+
const nestedRouterConflict = findNestedRouterConflict(
|
|
122
|
+
[...registry.values()]
|
|
123
|
+
.map((router) => router.__sourceFile)
|
|
124
|
+
.filter(
|
|
125
|
+
(sourceFile): sourceFile is string => typeof sourceFile === "string",
|
|
126
|
+
),
|
|
127
|
+
);
|
|
128
|
+
if (nestedRouterConflict) {
|
|
129
|
+
throw new Error(formatNestedRouterConflictError(nestedRouterConflict));
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Build into local variables first. Only commit to state after the
|
|
133
|
+
// full pass succeeds, so a failed re-discovery preserves the last
|
|
134
|
+
// known-good state instead of leaving it partially wiped.
|
|
135
|
+
const newMergedRouteManifest: Record<string, string> = {};
|
|
136
|
+
const newMergedPrecomputedEntries: PrecomputedEntry[] = [];
|
|
137
|
+
const newPerRouterManifests: typeof state.perRouterManifests = [];
|
|
138
|
+
const newPerRouterManifestDataMap = new Map<string, any>();
|
|
139
|
+
const newPerRouterPrecomputedMap = new Map<string, PrecomputedEntry[]>();
|
|
140
|
+
const newPerRouterTrieMap = new Map<string, any>();
|
|
141
|
+
let mergedRouteAncestry: Record<string, string[]> = {};
|
|
142
|
+
let mergedRouteTrailingSlash: Record<string, string> = {};
|
|
143
|
+
|
|
144
|
+
let routerMountIndex = 0;
|
|
145
|
+
// Collect all manifests for trie building (avoid re-running generateManifest)
|
|
146
|
+
const allManifests: Array<{ id: string; manifest: any }> = [];
|
|
147
|
+
|
|
148
|
+
const manifestGenStart = debug ? performance.now() : 0;
|
|
149
|
+
for (const [id, router] of registry) {
|
|
150
|
+
if (!router.urlpatterns || !generateManifestFull) {
|
|
151
|
+
continue;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
const manifest = generateManifestFull(
|
|
155
|
+
router.urlpatterns,
|
|
156
|
+
routerMountIndex,
|
|
157
|
+
router.__basename ? { urlPrefix: router.__basename } : undefined,
|
|
158
|
+
);
|
|
159
|
+
routerMountIndex++;
|
|
160
|
+
allManifests.push({ id, manifest });
|
|
161
|
+
const routeCount = Object.keys(manifest.routeManifest).length;
|
|
162
|
+
const staticRoutes = Object.values(manifest.routeManifest).filter(
|
|
163
|
+
(p: any) => !p.includes(":") && !p.includes("*"),
|
|
164
|
+
).length;
|
|
165
|
+
const dynamicRoutes = routeCount - staticRoutes;
|
|
166
|
+
|
|
167
|
+
// Merge into the combined manifest
|
|
168
|
+
Object.assign(newMergedRouteManifest, manifest.routeManifest);
|
|
169
|
+
|
|
170
|
+
// Compute factory-only prefixes: dot-prefixed groups in the runtime
|
|
171
|
+
// manifest that the static parser cannot see. These are routes created
|
|
172
|
+
// by factory functions (e.g. createDocsPatterns()) and should always be
|
|
173
|
+
// supplemented on file change since HMR won't re-discover them.
|
|
174
|
+
let factoryOnlyPrefixes: Set<string> | undefined;
|
|
175
|
+
if (router.__sourceFile) {
|
|
176
|
+
const staticParsed = buildCombinedRouteMapForRouterFile(
|
|
177
|
+
router.__sourceFile,
|
|
178
|
+
);
|
|
179
|
+
const staticNames = new Set(Object.keys(staticParsed.routes));
|
|
180
|
+
factoryOnlyPrefixes = new Set<string>();
|
|
181
|
+
for (const name of Object.keys(manifest.routeManifest)) {
|
|
182
|
+
if (staticNames.has(name)) continue;
|
|
183
|
+
const dotIdx = name.indexOf(".");
|
|
184
|
+
if (dotIdx <= 0) continue;
|
|
185
|
+
const prefix = name.substring(0, dotIdx + 1);
|
|
186
|
+
if ([...staticNames].some((n) => n.startsWith(prefix))) continue;
|
|
187
|
+
factoryOnlyPrefixes.add(prefix);
|
|
188
|
+
}
|
|
189
|
+
if (factoryOnlyPrefixes.size === 0) factoryOnlyPrefixes = undefined;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
newPerRouterManifests.push({
|
|
193
|
+
id,
|
|
194
|
+
routeManifest: manifest.routeManifest,
|
|
195
|
+
routeSearchSchemas: manifest.routeSearchSchemas,
|
|
196
|
+
sourceFile: router.__sourceFile,
|
|
197
|
+
factoryOnlyPrefixes,
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
// Merge ancestry (internal field, used only for trie building)
|
|
201
|
+
if (manifest._routeAncestry) {
|
|
202
|
+
Object.assign(mergedRouteAncestry, manifest._routeAncestry);
|
|
203
|
+
}
|
|
204
|
+
// Merge trailing slash config
|
|
205
|
+
if (manifest.routeTrailingSlash) {
|
|
206
|
+
Object.assign(mergedRouteTrailingSlash, manifest.routeTrailingSlash);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// Flatten prefix tree leaf nodes into precomputed entries.
|
|
210
|
+
// Leaf nodes (no children) can have their routes used directly by
|
|
211
|
+
// evaluateLazyEntry() without running the handler at runtime.
|
|
212
|
+
flattenLeafEntries(
|
|
213
|
+
manifest.prefixTree,
|
|
214
|
+
manifest.routeManifest,
|
|
215
|
+
newMergedPrecomputedEntries,
|
|
216
|
+
);
|
|
217
|
+
|
|
218
|
+
// Store per-router manifest and precomputed entries for isolated virtual modules.
|
|
219
|
+
newPerRouterManifestDataMap.set(id, manifest.routeManifest);
|
|
220
|
+
const routerPrecomputed: PrecomputedEntry[] = [];
|
|
221
|
+
flattenLeafEntries(
|
|
222
|
+
manifest.prefixTree,
|
|
223
|
+
manifest.routeManifest,
|
|
224
|
+
routerPrecomputed,
|
|
225
|
+
);
|
|
226
|
+
newPerRouterPrecomputedMap.set(id, routerPrecomputed);
|
|
227
|
+
|
|
228
|
+
console.log(
|
|
229
|
+
`[rsc-router] Router "${id}" -> ${routeCount} routes ` +
|
|
230
|
+
`(${staticRoutes} static, ${dynamicRoutes} dynamic)`,
|
|
231
|
+
);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// Warn if multiple routers use auto-generated IDs (router_0, router_1, ...).
|
|
235
|
+
// Auto-IDs are assigned by counter and depend on module evaluation order,
|
|
236
|
+
// which can differ between build time and runtime (especially with dynamic
|
|
237
|
+
// imports in host routers). This causes per-router data to be loaded into
|
|
238
|
+
// the wrong router at runtime.
|
|
239
|
+
if (registry.size > 1) {
|
|
240
|
+
const autoIds = [...registry.keys()].filter((id) =>
|
|
241
|
+
/^router_\d+$/.test(id),
|
|
242
|
+
);
|
|
243
|
+
if (autoIds.length > 1) {
|
|
244
|
+
console.warn(
|
|
245
|
+
`[rsc-router] WARNING: ${autoIds.length} routers use auto-generated IDs (${autoIds.join(", ")}). ` +
|
|
246
|
+
`In multi-router setups, each createRouter() must have an explicit \`id\` option ` +
|
|
247
|
+
`to ensure per-router manifest data is matched correctly at runtime. ` +
|
|
248
|
+
`Example: createRouter({ id: "site", ... })`,
|
|
249
|
+
);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
debug?.(
|
|
254
|
+
"inner: generated manifests for %d router(s) (%sms)",
|
|
255
|
+
allManifests.length,
|
|
256
|
+
(performance.now() - manifestGenStart).toFixed(1),
|
|
257
|
+
);
|
|
258
|
+
|
|
259
|
+
// Build route trie from merged manifest + ancestry
|
|
260
|
+
let newMergedRouteTrie: any = null;
|
|
261
|
+
const trieStart = debug ? performance.now() : 0;
|
|
262
|
+
if (Object.keys(newMergedRouteManifest).length > 0) {
|
|
263
|
+
const buildRouteTrie = buildMod.buildRouteTrie;
|
|
264
|
+
if (buildRouteTrie && mergedRouteAncestry) {
|
|
265
|
+
// Build routeToStaticPrefix from saved manifests
|
|
266
|
+
const routeToStaticPrefix: Record<string, string> = {};
|
|
267
|
+
for (const { manifest } of allManifests) {
|
|
268
|
+
// Root-level routes have empty static prefix
|
|
269
|
+
for (const name of Object.keys(manifest.routeManifest)) {
|
|
270
|
+
if (!(name in routeToStaticPrefix)) {
|
|
271
|
+
routeToStaticPrefix[name] = "";
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
buildRouteToStaticPrefix(manifest.prefixTree, routeToStaticPrefix);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// Collect prerender route names and response type routes from all manifests
|
|
278
|
+
const prerenderRouteNames = new Set<string>();
|
|
279
|
+
const passthroughRouteNames = new Set<string>();
|
|
280
|
+
const mergedResponseTypeRoutes: Record<string, string> = {};
|
|
281
|
+
for (const { manifest } of allManifests) {
|
|
282
|
+
if (manifest.prerenderRoutes) {
|
|
283
|
+
for (const name of manifest.prerenderRoutes) {
|
|
284
|
+
prerenderRouteNames.add(name);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
if (manifest.passthroughRoutes) {
|
|
288
|
+
for (const name of manifest.passthroughRoutes) {
|
|
289
|
+
passthroughRouteNames.add(name);
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
if (manifest.responseTypeRoutes) {
|
|
293
|
+
Object.assign(mergedResponseTypeRoutes, manifest.responseTypeRoutes);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
newMergedRouteTrie = buildRouteTrie(
|
|
298
|
+
newMergedRouteManifest,
|
|
299
|
+
mergedRouteAncestry,
|
|
300
|
+
routeToStaticPrefix,
|
|
301
|
+
Object.keys(mergedRouteTrailingSlash).length > 0
|
|
302
|
+
? mergedRouteTrailingSlash
|
|
303
|
+
: undefined,
|
|
304
|
+
prerenderRouteNames.size > 0 ? prerenderRouteNames : undefined,
|
|
305
|
+
passthroughRouteNames.size > 0 ? passthroughRouteNames : undefined,
|
|
306
|
+
Object.keys(mergedResponseTypeRoutes).length > 0
|
|
307
|
+
? mergedResponseTypeRoutes
|
|
308
|
+
: undefined,
|
|
309
|
+
);
|
|
310
|
+
|
|
311
|
+
// Build per-router tries for multi-router isolation.
|
|
312
|
+
for (const { id, manifest } of allManifests) {
|
|
313
|
+
if (
|
|
314
|
+
!manifest._routeAncestry ||
|
|
315
|
+
Object.keys(manifest._routeAncestry).length === 0
|
|
316
|
+
)
|
|
317
|
+
continue;
|
|
318
|
+
const perRouterStaticPrefix: Record<string, string> = {};
|
|
319
|
+
for (const name of Object.keys(manifest.routeManifest)) {
|
|
320
|
+
perRouterStaticPrefix[name] = "";
|
|
321
|
+
}
|
|
322
|
+
buildRouteToStaticPrefix(manifest.prefixTree, perRouterStaticPrefix);
|
|
323
|
+
|
|
324
|
+
const perRouterPrerenderNames = manifest.prerenderRoutes
|
|
325
|
+
? new Set<string>(manifest.prerenderRoutes)
|
|
326
|
+
: undefined;
|
|
327
|
+
const perRouterPassthroughNames = manifest.passthroughRoutes
|
|
328
|
+
? new Set<string>(manifest.passthroughRoutes)
|
|
329
|
+
: undefined;
|
|
330
|
+
|
|
331
|
+
const perRouterTrie = buildRouteTrie(
|
|
332
|
+
manifest.routeManifest,
|
|
333
|
+
manifest._routeAncestry,
|
|
334
|
+
perRouterStaticPrefix,
|
|
335
|
+
manifest.routeTrailingSlash &&
|
|
336
|
+
Object.keys(manifest.routeTrailingSlash).length > 0
|
|
337
|
+
? manifest.routeTrailingSlash
|
|
338
|
+
: undefined,
|
|
339
|
+
perRouterPrerenderNames && perRouterPrerenderNames.size > 0
|
|
340
|
+
? perRouterPrerenderNames
|
|
341
|
+
: undefined,
|
|
342
|
+
perRouterPassthroughNames && perRouterPassthroughNames.size > 0
|
|
343
|
+
? perRouterPassthroughNames
|
|
344
|
+
: undefined,
|
|
345
|
+
manifest.responseTypeRoutes &&
|
|
346
|
+
Object.keys(manifest.responseTypeRoutes).length > 0
|
|
347
|
+
? manifest.responseTypeRoutes
|
|
348
|
+
: undefined,
|
|
349
|
+
);
|
|
350
|
+
newPerRouterTrieMap.set(id, perRouterTrie);
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
debug?.(
|
|
356
|
+
"inner: trie build done (%sms)",
|
|
357
|
+
(performance.now() - trieStart).toFixed(1),
|
|
358
|
+
);
|
|
359
|
+
|
|
360
|
+
// Commit all local state to the shared discovery state atomically.
|
|
361
|
+
// This ensures a failed re-discovery (e.g. from a transient module
|
|
362
|
+
// evaluation error) preserves the last known-good state.
|
|
363
|
+
state.mergedRouteManifest = newMergedRouteManifest;
|
|
364
|
+
state.mergedPrecomputedEntries = newMergedPrecomputedEntries;
|
|
365
|
+
state.perRouterManifests = newPerRouterManifests;
|
|
366
|
+
state.perRouterManifestDataMap = newPerRouterManifestDataMap;
|
|
367
|
+
state.perRouterPrecomputedMap = newPerRouterPrecomputedMap;
|
|
368
|
+
state.perRouterTrieMap = newPerRouterTrieMap;
|
|
369
|
+
state.mergedRouteTrie = newMergedRouteTrie;
|
|
370
|
+
|
|
371
|
+
// Expand prerender routes and render static handlers (build mode only)
|
|
372
|
+
await expandPrerenderRoutes(state, rscEnv, registry, allManifests);
|
|
373
|
+
await renderStaticHandlers(state, rscEnv, registry);
|
|
374
|
+
|
|
375
|
+
return serverMod;
|
|
376
|
+
}
|