@rangojs/router 0.0.0-experimental.0f44aca1
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 +5 -0
- package/README.md +899 -0
- package/dist/bin/rango.js +1601 -0
- package/dist/vite/index.js +5214 -0
- package/package.json +176 -0
- package/skills/breadcrumbs/SKILL.md +250 -0
- package/skills/cache-guide/SKILL.md +262 -0
- package/skills/caching/SKILL.md +220 -0
- package/skills/composability/SKILL.md +172 -0
- package/skills/debug-manifest/SKILL.md +112 -0
- package/skills/document-cache/SKILL.md +182 -0
- package/skills/fonts/SKILL.md +167 -0
- package/skills/hooks/SKILL.md +704 -0
- package/skills/host-router/SKILL.md +218 -0
- package/skills/intercept/SKILL.md +313 -0
- package/skills/layout/SKILL.md +310 -0
- package/skills/links/SKILL.md +239 -0
- package/skills/loader/SKILL.md +596 -0
- package/skills/middleware/SKILL.md +339 -0
- package/skills/mime-routes/SKILL.md +128 -0
- package/skills/parallel/SKILL.md +305 -0
- package/skills/prerender/SKILL.md +643 -0
- package/skills/rango/SKILL.md +118 -0
- package/skills/response-routes/SKILL.md +411 -0
- package/skills/route/SKILL.md +385 -0
- package/skills/router-setup/SKILL.md +439 -0
- package/skills/tailwind/SKILL.md +129 -0
- package/skills/theme/SKILL.md +79 -0
- package/skills/typesafety/SKILL.md +623 -0
- package/skills/use-cache/SKILL.md +324 -0
- package/src/__internal.ts +273 -0
- package/src/bin/rango.ts +321 -0
- package/src/browser/action-coordinator.ts +97 -0
- package/src/browser/action-response-classifier.ts +99 -0
- package/src/browser/event-controller.ts +899 -0
- package/src/browser/history-state.ts +80 -0
- package/src/browser/index.ts +18 -0
- package/src/browser/intercept-utils.ts +52 -0
- package/src/browser/link-interceptor.ts +141 -0
- package/src/browser/logging.ts +55 -0
- package/src/browser/merge-segment-loaders.ts +134 -0
- package/src/browser/navigation-bridge.ts +645 -0
- package/src/browser/navigation-client.ts +215 -0
- package/src/browser/navigation-store.ts +806 -0
- package/src/browser/navigation-transaction.ts +295 -0
- package/src/browser/network-error-handler.ts +61 -0
- package/src/browser/partial-update.ts +550 -0
- package/src/browser/prefetch/cache.ts +146 -0
- package/src/browser/prefetch/fetch.ts +135 -0
- package/src/browser/prefetch/observer.ts +65 -0
- package/src/browser/prefetch/policy.ts +42 -0
- package/src/browser/prefetch/queue.ts +88 -0
- package/src/browser/rango-state.ts +112 -0
- package/src/browser/react/Link.tsx +360 -0
- package/src/browser/react/NavigationProvider.tsx +386 -0
- package/src/browser/react/ScrollRestoration.tsx +94 -0
- package/src/browser/react/context.ts +59 -0
- package/src/browser/react/filter-segment-order.ts +11 -0
- package/src/browser/react/index.ts +52 -0
- package/src/browser/react/location-state-shared.ts +162 -0
- package/src/browser/react/location-state.ts +107 -0
- package/src/browser/react/mount-context.ts +37 -0
- 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 +218 -0
- package/src/browser/react/use-client-cache.ts +58 -0
- package/src/browser/react/use-handle.ts +162 -0
- package/src/browser/react/use-href.tsx +40 -0
- package/src/browser/react/use-link-status.ts +135 -0
- package/src/browser/react/use-mount.ts +31 -0
- package/src/browser/react/use-navigation.ts +99 -0
- package/src/browser/react/use-params.ts +65 -0
- package/src/browser/react/use-pathname.ts +47 -0
- package/src/browser/react/use-router.ts +63 -0
- package/src/browser/react/use-search-params.ts +56 -0
- package/src/browser/react/use-segments.ts +171 -0
- package/src/browser/response-adapter.ts +73 -0
- package/src/browser/rsc-router.tsx +431 -0
- package/src/browser/scroll-restoration.ts +400 -0
- package/src/browser/segment-reconciler.ts +216 -0
- package/src/browser/segment-structure-assert.ts +83 -0
- package/src/browser/server-action-bridge.ts +667 -0
- package/src/browser/shallow.ts +40 -0
- package/src/browser/types.ts +538 -0
- package/src/browser/validate-redirect-origin.ts +29 -0
- package/src/build/generate-manifest.ts +438 -0
- package/src/build/generate-route-types.ts +36 -0
- package/src/build/index.ts +35 -0
- package/src/build/route-trie.ts +265 -0
- 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 +411 -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 +469 -0
- package/src/build/route-types/scan-filter.ts +78 -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 +338 -0
- package/src/cache/cache-scope.ts +382 -0
- package/src/cache/cf/cf-cache-store.ts +540 -0
- package/src/cache/cf/index.ts +25 -0
- package/src/cache/document-cache.ts +369 -0
- package/src/cache/handle-capture.ts +81 -0
- package/src/cache/handle-snapshot.ts +41 -0
- package/src/cache/index.ts +43 -0
- package/src/cache/memory-segment-store.ts +328 -0
- 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 +98 -0
- package/src/cache/types.ts +342 -0
- package/src/client.rsc.tsx +85 -0
- package/src/client.tsx +601 -0
- package/src/component-utils.ts +76 -0
- package/src/components/DefaultDocument.tsx +27 -0
- package/src/context-var.ts +86 -0
- package/src/debug.ts +243 -0
- package/src/default-error-boundary.tsx +88 -0
- package/src/deps/browser.ts +8 -0
- package/src/deps/html-stream-client.ts +2 -0
- package/src/deps/html-stream-server.ts +2 -0
- package/src/deps/rsc.ts +10 -0
- package/src/deps/ssr.ts +2 -0
- package/src/errors.ts +365 -0
- package/src/handle.ts +135 -0
- package/src/handles/MetaTags.tsx +246 -0
- package/src/handles/breadcrumbs.ts +66 -0
- package/src/handles/index.ts +7 -0
- package/src/handles/meta.ts +264 -0
- package/src/host/cookie-handler.ts +165 -0
- package/src/host/errors.ts +97 -0
- package/src/host/index.ts +53 -0
- package/src/host/pattern-matcher.ts +214 -0
- package/src/host/router.ts +352 -0
- package/src/host/testing.ts +79 -0
- package/src/host/types.ts +146 -0
- package/src/host/utils.ts +25 -0
- package/src/href-client.ts +222 -0
- package/src/index.rsc.ts +233 -0
- package/src/index.ts +277 -0
- package/src/internal-debug.ts +11 -0
- package/src/loader.rsc.ts +89 -0
- package/src/loader.ts +64 -0
- package/src/network-error-thrower.tsx +23 -0
- package/src/outlet-context.ts +15 -0
- package/src/outlet-provider.tsx +45 -0
- package/src/prerender/param-hash.ts +37 -0
- package/src/prerender/store.ts +185 -0
- package/src/prerender.ts +463 -0
- package/src/reverse.ts +330 -0
- package/src/root-error-boundary.tsx +289 -0
- package/src/route-content-wrapper.tsx +196 -0
- package/src/route-definition/dsl-helpers.ts +934 -0
- package/src/route-definition/helper-factories.ts +200 -0
- package/src/route-definition/helpers-types.ts +430 -0
- package/src/route-definition/index.ts +52 -0
- package/src/route-definition/redirect.ts +93 -0
- package/src/route-definition.ts +1 -0
- package/src/route-map-builder.ts +275 -0
- package/src/route-name.ts +53 -0
- package/src/route-types.ts +259 -0
- package/src/router/content-negotiation.ts +116 -0
- package/src/router/debug-manifest.ts +72 -0
- package/src/router/error-handling.ts +287 -0
- package/src/router/find-match.ts +158 -0
- package/src/router/handler-context.ts +451 -0
- package/src/router/intercept-resolution.ts +395 -0
- package/src/router/lazy-includes.ts +234 -0
- package/src/router/loader-resolution.ts +420 -0
- package/src/router/logging.ts +248 -0
- package/src/router/manifest.ts +267 -0
- package/src/router/match-api.ts +620 -0
- package/src/router/match-context.ts +266 -0
- package/src/router/match-handlers.ts +440 -0
- package/src/router/match-middleware/background-revalidation.ts +223 -0
- package/src/router/match-middleware/cache-lookup.ts +634 -0
- package/src/router/match-middleware/cache-store.ts +295 -0
- package/src/router/match-middleware/index.ts +81 -0
- package/src/router/match-middleware/intercept-resolution.ts +306 -0
- package/src/router/match-middleware/segment-resolution.ts +192 -0
- package/src/router/match-pipelines.ts +179 -0
- package/src/router/match-result.ts +219 -0
- package/src/router/metrics.ts +282 -0
- package/src/router/middleware-cookies.ts +55 -0
- package/src/router/middleware-types.ts +222 -0
- package/src/router/middleware.ts +748 -0
- package/src/router/pattern-matching.ts +563 -0
- package/src/router/prerender-match.ts +402 -0
- package/src/router/preview-match.ts +170 -0
- package/src/router/revalidation.ts +289 -0
- package/src/router/router-context.ts +316 -0
- package/src/router/router-interfaces.ts +452 -0
- package/src/router/router-options.ts +592 -0
- package/src/router/router-registry.ts +24 -0
- package/src/router/segment-resolution/fresh.ts +570 -0
- package/src/router/segment-resolution/helpers.ts +263 -0
- package/src/router/segment-resolution/loader-cache.ts +198 -0
- package/src/router/segment-resolution/revalidation.ts +1239 -0
- package/src/router/segment-resolution/static-store.ts +67 -0
- package/src/router/segment-resolution.ts +21 -0
- package/src/router/segment-wrappers.ts +289 -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 +239 -0
- package/src/router/types.ts +170 -0
- package/src/router.ts +1002 -0
- package/src/rsc/handler-context.ts +45 -0
- package/src/rsc/handler.ts +1089 -0
- package/src/rsc/helpers.ts +198 -0
- package/src/rsc/index.ts +36 -0
- package/src/rsc/loader-fetch.ts +209 -0
- package/src/rsc/manifest-init.ts +86 -0
- package/src/rsc/nonce.ts +32 -0
- package/src/rsc/origin-guard.ts +141 -0
- package/src/rsc/progressive-enhancement.ts +379 -0
- package/src/rsc/response-error.ts +37 -0
- package/src/rsc/response-route-handler.ts +347 -0
- package/src/rsc/rsc-rendering.ts +235 -0
- package/src/rsc/runtime-warnings.ts +42 -0
- package/src/rsc/server-action.ts +348 -0
- package/src/rsc/ssr-setup.ts +128 -0
- package/src/rsc/types.ts +263 -0
- package/src/search-params.ts +230 -0
- package/src/segment-system.tsx +454 -0
- package/src/server/context.ts +591 -0
- package/src/server/cookie-store.ts +190 -0
- package/src/server/fetchable-loader-store.ts +37 -0
- package/src/server/handle-store.ts +308 -0
- package/src/server/loader-registry.ts +133 -0
- package/src/server/request-context.ts +914 -0
- package/src/server/root-layout.tsx +10 -0
- package/src/server/tsconfig.json +14 -0
- package/src/server.ts +51 -0
- package/src/ssr/index.tsx +365 -0
- package/src/static-handler.ts +114 -0
- package/src/theme/ThemeProvider.tsx +297 -0
- package/src/theme/ThemeScript.tsx +61 -0
- package/src/theme/constants.ts +62 -0
- package/src/theme/index.ts +48 -0
- package/src/theme/theme-context.ts +44 -0
- package/src/theme/theme-script.ts +155 -0
- package/src/theme/types.ts +182 -0
- package/src/theme/use-theme.ts +44 -0
- 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 +687 -0
- package/src/types/index.ts +88 -0
- package/src/types/loader-types.ts +183 -0
- package/src/types/route-config.ts +170 -0
- package/src/types/route-entry.ts +102 -0
- package/src/types/segments.ts +148 -0
- package/src/types.ts +1 -0
- package/src/urls/include-helper.ts +197 -0
- package/src/urls/index.ts +53 -0
- package/src/urls/path-helper-types.ts +339 -0
- package/src/urls/path-helper.ts +329 -0
- package/src/urls/pattern-types.ts +95 -0
- package/src/urls/response-types.ts +106 -0
- package/src/urls/type-extraction.ts +372 -0
- package/src/urls/urls-function.ts +98 -0
- package/src/urls.ts +1 -0
- package/src/use-loader.tsx +354 -0
- package/src/vite/discovery/bundle-postprocess.ts +184 -0
- package/src/vite/discovery/discover-routers.ts +344 -0
- package/src/vite/discovery/prerender-collection.ts +385 -0
- package/src/vite/discovery/route-types-writer.ts +258 -0
- package/src/vite/discovery/self-gen-tracking.ts +47 -0
- package/src/vite/discovery/state.ts +110 -0
- package/src/vite/discovery/virtual-module-codegen.ts +203 -0
- package/src/vite/index.ts +16 -0
- package/src/vite/plugin-types.ts +131 -0
- package/src/vite/plugins/cjs-to-esm.ts +93 -0
- package/src/vite/plugins/client-ref-dedup.ts +115 -0
- package/src/vite/plugins/client-ref-hashing.ts +105 -0
- package/src/vite/plugins/expose-action-id.ts +365 -0
- package/src/vite/plugins/expose-id-utils.ts +287 -0
- package/src/vite/plugins/expose-ids/export-analysis.ts +296 -0
- package/src/vite/plugins/expose-ids/handler-transform.ts +179 -0
- package/src/vite/plugins/expose-ids/loader-transform.ts +74 -0
- package/src/vite/plugins/expose-ids/router-transform.ts +110 -0
- package/src/vite/plugins/expose-ids/types.ts +45 -0
- package/src/vite/plugins/expose-internal-ids.ts +569 -0
- package/src/vite/plugins/refresh-cmd.ts +65 -0
- package/src/vite/plugins/use-cache-transform.ts +323 -0
- package/src/vite/plugins/version-injector.ts +83 -0
- package/src/vite/plugins/version-plugin.ts +254 -0
- package/src/vite/plugins/version.d.ts +12 -0
- package/src/vite/plugins/virtual-entries.ts +123 -0
- package/src/vite/plugins/virtual-stub-plugin.ts +29 -0
- package/src/vite/rango.ts +510 -0
- package/src/vite/router-discovery.ts +785 -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 +121 -0
- package/src/vite/utils/prerender-utils.ts +189 -0
- package/src/vite/utils/shared-utils.ts +169 -0
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Default virtual entry file contents for rsc-router.
|
|
3
|
+
* These are used when users don't provide their own entry files.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export const VIRTUAL_ENTRY_BROWSER: string = `
|
|
7
|
+
import {
|
|
8
|
+
createFromReadableStream,
|
|
9
|
+
createFromFetch,
|
|
10
|
+
setServerCallback,
|
|
11
|
+
encodeReply,
|
|
12
|
+
createTemporaryReferenceSet,
|
|
13
|
+
} from "@rangojs/router/internal/deps/browser";
|
|
14
|
+
import { createElement, StrictMode } from "react";
|
|
15
|
+
import { hydrateRoot } from "react-dom/client";
|
|
16
|
+
import { rscStream } from "@rangojs/router/internal/deps/html-stream-client";
|
|
17
|
+
import { initBrowserApp, RSCRouter } from "@rangojs/router/browser";
|
|
18
|
+
|
|
19
|
+
async function initializeApp() {
|
|
20
|
+
const deps = {
|
|
21
|
+
createFromFetch,
|
|
22
|
+
createFromReadableStream,
|
|
23
|
+
encodeReply,
|
|
24
|
+
setServerCallback,
|
|
25
|
+
createTemporaryReferenceSet,
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
await initBrowserApp({ rscStream, deps });
|
|
29
|
+
|
|
30
|
+
hydrateRoot(
|
|
31
|
+
document,
|
|
32
|
+
createElement(StrictMode, null, createElement(RSCRouter))
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
initializeApp().catch(console.error);
|
|
37
|
+
`.trim();
|
|
38
|
+
|
|
39
|
+
export const VIRTUAL_ENTRY_SSR: string = `
|
|
40
|
+
import { createFromReadableStream } from "@rangojs/router/internal/deps/ssr";
|
|
41
|
+
import { renderToReadableStream } from "react-dom/server.edge";
|
|
42
|
+
import { injectRSCPayload } from "@rangojs/router/internal/deps/html-stream-server";
|
|
43
|
+
import { createSSRHandler } from "@rangojs/router/ssr";
|
|
44
|
+
|
|
45
|
+
export const renderHTML = createSSRHandler({
|
|
46
|
+
createFromReadableStream,
|
|
47
|
+
renderToReadableStream,
|
|
48
|
+
injectRSCPayload,
|
|
49
|
+
loadBootstrapScriptContent: () =>
|
|
50
|
+
import.meta.viteRsc.loadBootstrapScriptContent("index"),
|
|
51
|
+
});
|
|
52
|
+
`.trim();
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Generate the RSC entry content with the specified router path
|
|
56
|
+
*/
|
|
57
|
+
export function getVirtualEntryRSC(routerPath: string): string {
|
|
58
|
+
return `
|
|
59
|
+
import {
|
|
60
|
+
renderToReadableStream,
|
|
61
|
+
decodeReply,
|
|
62
|
+
createTemporaryReferenceSet,
|
|
63
|
+
loadServerAction,
|
|
64
|
+
decodeAction,
|
|
65
|
+
decodeFormState,
|
|
66
|
+
} from "@rangojs/router/internal/deps/rsc";
|
|
67
|
+
import { router } from "${routerPath}";
|
|
68
|
+
import { createRSCHandler } from "@rangojs/router/internal/rsc-handler";
|
|
69
|
+
import { VERSION } from "@rangojs/router:version";
|
|
70
|
+
|
|
71
|
+
// Import loader manifest to ensure all fetchable loaders are registered at startup
|
|
72
|
+
// This is critical for serverless/multi-process deployments where the loader module
|
|
73
|
+
// might not be imported before a GET request arrives
|
|
74
|
+
import "virtual:rsc-router/loader-manifest";
|
|
75
|
+
|
|
76
|
+
// Import pre-generated route manifest so href() works immediately on cold start.
|
|
77
|
+
// In build mode, this contains the full route map generated at build time.
|
|
78
|
+
// In dev mode, this is a no-op (manifest is populated in-memory by the discovery plugin).
|
|
79
|
+
import "virtual:rsc-router/routes-manifest";
|
|
80
|
+
|
|
81
|
+
// Lazily create the handler on first request so that ESM live bindings
|
|
82
|
+
// have resolved by the time we read \`router\`. During HMR the module may
|
|
83
|
+
// re-evaluate before router.tsx finishes, leaving the import undefined.
|
|
84
|
+
let _handler;
|
|
85
|
+
export default function handler(request, env) {
|
|
86
|
+
if (!_handler) {
|
|
87
|
+
_handler = createRSCHandler({
|
|
88
|
+
router,
|
|
89
|
+
version: VERSION,
|
|
90
|
+
deps: {
|
|
91
|
+
renderToReadableStream,
|
|
92
|
+
decodeReply,
|
|
93
|
+
createTemporaryReferenceSet,
|
|
94
|
+
loadServerAction,
|
|
95
|
+
decodeAction,
|
|
96
|
+
decodeFormState,
|
|
97
|
+
},
|
|
98
|
+
loadSSRModule: () =>
|
|
99
|
+
import.meta.viteRsc.loadModule("ssr", "index"),
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
return _handler(request, env);
|
|
103
|
+
}
|
|
104
|
+
`.trim();
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Virtual module IDs
|
|
109
|
+
*/
|
|
110
|
+
export const VIRTUAL_IDS = {
|
|
111
|
+
browser: "virtual:rsc-router/entry.browser.js",
|
|
112
|
+
ssr: "virtual:rsc-router/entry.ssr.js",
|
|
113
|
+
rsc: "virtual:rsc-router/entry.rsc.js",
|
|
114
|
+
version: "@rangojs/router:version",
|
|
115
|
+
} as const;
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Virtual module content for version.
|
|
119
|
+
* Exports VERSION - a timestamp that changes on server restart (dev) or at build time (production).
|
|
120
|
+
*/
|
|
121
|
+
export function getVirtualVersionContent(version: string): string {
|
|
122
|
+
return `export const VERSION = ${JSON.stringify(version)};`;
|
|
123
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { Plugin } from "vite";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Stub plugin that resolves and provides empty exports for virtual modules
|
|
5
|
+
* that the RSC entry may import but aren't needed for route discovery.
|
|
6
|
+
* @internal
|
|
7
|
+
*/
|
|
8
|
+
export function createVirtualStubPlugin(): Plugin {
|
|
9
|
+
const STUB_PREFIXES = [
|
|
10
|
+
"virtual:rsc-router/",
|
|
11
|
+
"virtual:entry-",
|
|
12
|
+
"virtual:vite-rsc/",
|
|
13
|
+
];
|
|
14
|
+
return {
|
|
15
|
+
name: "@rangojs/router:virtual-stubs",
|
|
16
|
+
resolveId(id) {
|
|
17
|
+
if (STUB_PREFIXES.some((p) => id.startsWith(p))) {
|
|
18
|
+
return "\0stub:" + id;
|
|
19
|
+
}
|
|
20
|
+
return null;
|
|
21
|
+
},
|
|
22
|
+
load(id) {
|
|
23
|
+
if (id.startsWith("\0stub:")) {
|
|
24
|
+
return "export default {}";
|
|
25
|
+
}
|
|
26
|
+
return null;
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
}
|
|
@@ -0,0 +1,510 @@
|
|
|
1
|
+
import type { PluginOption } from "vite";
|
|
2
|
+
import { readFileSync } from "node:fs";
|
|
3
|
+
import { resolve } from "node:path";
|
|
4
|
+
import { exposeActionId } from "./plugins/expose-action-id.js";
|
|
5
|
+
import {
|
|
6
|
+
exposeInternalIds,
|
|
7
|
+
exposeRouterId,
|
|
8
|
+
} from "./plugins/expose-internal-ids.js";
|
|
9
|
+
import { useCacheTransform } from "./plugins/use-cache-transform.js";
|
|
10
|
+
import { clientRefDedup } from "./plugins/client-ref-dedup.js";
|
|
11
|
+
import { VIRTUAL_IDS } from "./plugins/virtual-entries.js";
|
|
12
|
+
import {
|
|
13
|
+
getExcludeDeps,
|
|
14
|
+
getPackageAliases,
|
|
15
|
+
} from "./utils/package-resolution.js";
|
|
16
|
+
import {
|
|
17
|
+
createScanFilter,
|
|
18
|
+
findRouterFiles,
|
|
19
|
+
} from "../build/generate-route-types.js";
|
|
20
|
+
import { createVersionPlugin } from "./plugins/version-plugin.js";
|
|
21
|
+
import {
|
|
22
|
+
sharedEsbuildOptions,
|
|
23
|
+
createVirtualEntriesPlugin,
|
|
24
|
+
onwarn,
|
|
25
|
+
getManualChunks,
|
|
26
|
+
} from "./utils/shared-utils.js";
|
|
27
|
+
import type {
|
|
28
|
+
RangoOptions,
|
|
29
|
+
RangoNodeOptions,
|
|
30
|
+
RscPluginOptions,
|
|
31
|
+
} from "./plugin-types.js";
|
|
32
|
+
import { printBanner, rangoVersion } from "./utils/banner.js";
|
|
33
|
+
import { createVersionInjectorPlugin } from "./plugins/version-injector.js";
|
|
34
|
+
import { createCjsToEsmPlugin } from "./plugins/cjs-to-esm.js";
|
|
35
|
+
import { createRouterDiscoveryPlugin } from "./router-discovery.js";
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Vite plugin for @rangojs/router.
|
|
39
|
+
*
|
|
40
|
+
* Includes @vitejs/plugin-rsc and all necessary transforms for the router
|
|
41
|
+
* to function correctly with React Server Components.
|
|
42
|
+
*
|
|
43
|
+
* @example Node.js (default)
|
|
44
|
+
* ```ts
|
|
45
|
+
* export default defineConfig({
|
|
46
|
+
* plugins: [react(), rango({ router: './src/router.tsx' })],
|
|
47
|
+
* });
|
|
48
|
+
* ```
|
|
49
|
+
*
|
|
50
|
+
* @example Cloudflare Workers
|
|
51
|
+
* ```ts
|
|
52
|
+
* export default defineConfig({
|
|
53
|
+
* plugins: [
|
|
54
|
+
* react(),
|
|
55
|
+
* rango({ preset: 'cloudflare' }),
|
|
56
|
+
* cloudflare({ viteEnvironment: { name: 'rsc' } }),
|
|
57
|
+
* ],
|
|
58
|
+
* });
|
|
59
|
+
* ```
|
|
60
|
+
*/
|
|
61
|
+
export async function rango(options?: RangoOptions): Promise<PluginOption[]> {
|
|
62
|
+
const resolvedOptions: RangoOptions = options ?? { preset: "node" };
|
|
63
|
+
const preset = resolvedOptions.preset ?? "node";
|
|
64
|
+
const showBanner = resolvedOptions.banner ?? true;
|
|
65
|
+
|
|
66
|
+
const plugins: PluginOption[] = [];
|
|
67
|
+
|
|
68
|
+
// Get package resolution info (workspace vs npm install)
|
|
69
|
+
const rangoAliases = getPackageAliases();
|
|
70
|
+
const excludeDeps = getExcludeDeps();
|
|
71
|
+
|
|
72
|
+
// Track RSC entry path for version injection
|
|
73
|
+
let rscEntryPath: string | null = null;
|
|
74
|
+
|
|
75
|
+
// Mutable ref for router path (node preset only).
|
|
76
|
+
// Set immediately when user-specified, or populated by the auto-discover
|
|
77
|
+
// config() hook using Vite's resolved root.
|
|
78
|
+
const routerRef: { path: string | undefined } = { path: undefined };
|
|
79
|
+
|
|
80
|
+
// Build-time prerendering is enabled for both presets.
|
|
81
|
+
// Collection runs in-process via the RSC dev environment runner during discoverRouters().
|
|
82
|
+
const prerenderEnabled = true;
|
|
83
|
+
|
|
84
|
+
if (preset === "cloudflare") {
|
|
85
|
+
// Cloudflare preset: configure entries for cloudflare worker setup
|
|
86
|
+
// Router is not needed here - worker.rsc.tsx imports it directly
|
|
87
|
+
|
|
88
|
+
// Dynamically import @vitejs/plugin-rsc
|
|
89
|
+
const { default: rsc } = await import("@vitejs/plugin-rsc");
|
|
90
|
+
|
|
91
|
+
// Only client and ssr entries - rsc entry is handled by cloudflare plugin
|
|
92
|
+
// Always use virtual modules for cloudflare preset
|
|
93
|
+
const finalEntries: { client: string; ssr: string } = {
|
|
94
|
+
client: VIRTUAL_IDS.browser,
|
|
95
|
+
ssr: VIRTUAL_IDS.ssr,
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
plugins.push({
|
|
99
|
+
name: "@rangojs/router:cloudflare-integration",
|
|
100
|
+
enforce: "pre",
|
|
101
|
+
|
|
102
|
+
config() {
|
|
103
|
+
// Configure environments for cloudflare deployment
|
|
104
|
+
return {
|
|
105
|
+
// Exclude rsc-router modules from optimization to prevent module duplication
|
|
106
|
+
// This ensures the same Context instance is used by both browser entry and RSC proxy modules
|
|
107
|
+
optimizeDeps: {
|
|
108
|
+
exclude: excludeDeps,
|
|
109
|
+
esbuildOptions: sharedEsbuildOptions,
|
|
110
|
+
},
|
|
111
|
+
resolve: {
|
|
112
|
+
alias: rangoAliases,
|
|
113
|
+
},
|
|
114
|
+
build: {
|
|
115
|
+
rollupOptions: { onwarn },
|
|
116
|
+
},
|
|
117
|
+
environments: {
|
|
118
|
+
client: {
|
|
119
|
+
build: {
|
|
120
|
+
rollupOptions: {
|
|
121
|
+
output: {
|
|
122
|
+
manualChunks: getManualChunks,
|
|
123
|
+
},
|
|
124
|
+
},
|
|
125
|
+
},
|
|
126
|
+
// Pre-bundle rsc-html-stream to prevent discovery during first request
|
|
127
|
+
// Exclude rsc-router modules to ensure same Context instance
|
|
128
|
+
optimizeDeps: {
|
|
129
|
+
include: ["rsc-html-stream/client"],
|
|
130
|
+
exclude: excludeDeps,
|
|
131
|
+
esbuildOptions: sharedEsbuildOptions,
|
|
132
|
+
},
|
|
133
|
+
},
|
|
134
|
+
ssr: {
|
|
135
|
+
// Build SSR inside RSC directory so wrangler can deploy self-contained dist/rsc
|
|
136
|
+
build: {
|
|
137
|
+
outDir: "./dist/rsc/ssr",
|
|
138
|
+
},
|
|
139
|
+
resolve: {
|
|
140
|
+
// Ensure single React instance in SSR child environment
|
|
141
|
+
dedupe: ["react", "react-dom"],
|
|
142
|
+
},
|
|
143
|
+
// Pre-bundle SSR entry and React for proper module linking with childEnvironments
|
|
144
|
+
// All deps must be listed to avoid late discovery triggering ERR_OUTDATED_OPTIMIZED_DEP
|
|
145
|
+
optimizeDeps: {
|
|
146
|
+
entries: [finalEntries.ssr],
|
|
147
|
+
include: [
|
|
148
|
+
"react",
|
|
149
|
+
"react-dom",
|
|
150
|
+
"react-dom/server.edge",
|
|
151
|
+
"react-dom/static.edge",
|
|
152
|
+
"react/jsx-runtime",
|
|
153
|
+
"react/jsx-dev-runtime",
|
|
154
|
+
"rsc-html-stream/server",
|
|
155
|
+
"@vitejs/plugin-rsc/vendor/react-server-dom/client.edge",
|
|
156
|
+
],
|
|
157
|
+
exclude: excludeDeps,
|
|
158
|
+
esbuildOptions: sharedEsbuildOptions,
|
|
159
|
+
},
|
|
160
|
+
},
|
|
161
|
+
rsc: {
|
|
162
|
+
// RSC environment needs exclude list and esbuild options
|
|
163
|
+
// Exclude rsc-router modules to prevent createContext in RSC environment
|
|
164
|
+
optimizeDeps: {
|
|
165
|
+
// Pre-bundle all RSC deps to prevent late discovery triggering ERR_OUTDATED_OPTIMIZED_DEP
|
|
166
|
+
include: [
|
|
167
|
+
"react",
|
|
168
|
+
"react/jsx-runtime",
|
|
169
|
+
"react/jsx-dev-runtime",
|
|
170
|
+
"@vitejs/plugin-rsc/vendor/react-server-dom/server.edge",
|
|
171
|
+
],
|
|
172
|
+
exclude: excludeDeps,
|
|
173
|
+
esbuildOptions: sharedEsbuildOptions,
|
|
174
|
+
},
|
|
175
|
+
},
|
|
176
|
+
},
|
|
177
|
+
};
|
|
178
|
+
},
|
|
179
|
+
|
|
180
|
+
configResolved(config) {
|
|
181
|
+
if (showBanner) {
|
|
182
|
+
const mode =
|
|
183
|
+
config.command === "serve"
|
|
184
|
+
? process.argv.includes("preview")
|
|
185
|
+
? "preview"
|
|
186
|
+
: "dev"
|
|
187
|
+
: "build";
|
|
188
|
+
printBanner(mode, "cloudflare", rangoVersion);
|
|
189
|
+
}
|
|
190
|
+
},
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
plugins.push(createVirtualEntriesPlugin(finalEntries));
|
|
194
|
+
|
|
195
|
+
// Add RSC plugin with cloudflare-specific options
|
|
196
|
+
// Note: loadModuleDevProxy should NOT be used with childEnvironments
|
|
197
|
+
// since SSR runs in workerd alongside RSC
|
|
198
|
+
plugins.push(
|
|
199
|
+
rsc({
|
|
200
|
+
entries: finalEntries,
|
|
201
|
+
serverHandler: false,
|
|
202
|
+
}) as PluginOption,
|
|
203
|
+
);
|
|
204
|
+
|
|
205
|
+
// Deduplicate client references from third-party packages in dev mode.
|
|
206
|
+
// Prevents module duplication when server components import "use client"
|
|
207
|
+
// packages that are also imported directly by client components.
|
|
208
|
+
plugins.push(clientRefDedup());
|
|
209
|
+
} else {
|
|
210
|
+
// Node preset: full RSC plugin integration
|
|
211
|
+
const nodeOptions = resolvedOptions as RangoNodeOptions;
|
|
212
|
+
|
|
213
|
+
routerRef.path = nodeOptions.router;
|
|
214
|
+
|
|
215
|
+
// Auto-discover router using Vite's resolved root (not process.cwd())
|
|
216
|
+
if (!routerRef.path) {
|
|
217
|
+
plugins.push({
|
|
218
|
+
name: "@rangojs/router:auto-discover",
|
|
219
|
+
config(userConfig) {
|
|
220
|
+
if (routerRef.path) return;
|
|
221
|
+
const root = userConfig.root
|
|
222
|
+
? resolve(process.cwd(), userConfig.root)
|
|
223
|
+
: process.cwd();
|
|
224
|
+
const filter = createScanFilter(root, {
|
|
225
|
+
include: resolvedOptions.include,
|
|
226
|
+
exclude: resolvedOptions.exclude,
|
|
227
|
+
});
|
|
228
|
+
const candidates = findRouterFiles(root, filter);
|
|
229
|
+
if (candidates.length === 1) {
|
|
230
|
+
const abs = candidates[0];
|
|
231
|
+
routerRef.path = (
|
|
232
|
+
abs.startsWith(root) ? "./" + abs.slice(root.length + 1) : abs
|
|
233
|
+
).replaceAll("\\", "/");
|
|
234
|
+
} else if (candidates.length > 1) {
|
|
235
|
+
const list = candidates
|
|
236
|
+
.map(
|
|
237
|
+
(f) =>
|
|
238
|
+
" - " + (f.startsWith(root) ? f.slice(root.length + 1) : f),
|
|
239
|
+
)
|
|
240
|
+
.join("\n");
|
|
241
|
+
throw new Error(
|
|
242
|
+
`[rsc-router] Multiple routers found. Specify \`router\` to choose one:\n${list}`,
|
|
243
|
+
);
|
|
244
|
+
}
|
|
245
|
+
// 0 found: routerRef.path stays undefined, warn at startup via discovery plugin
|
|
246
|
+
},
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
const rscOption = nodeOptions.rsc ?? true;
|
|
251
|
+
|
|
252
|
+
// Add RSC plugin by default (can be disabled with rsc: false)
|
|
253
|
+
if (rscOption !== false) {
|
|
254
|
+
// Dynamically import @vitejs/plugin-rsc
|
|
255
|
+
const { default: rsc } = await import("@vitejs/plugin-rsc");
|
|
256
|
+
|
|
257
|
+
// Resolve entry paths: use explicit config or virtual modules
|
|
258
|
+
const userEntries =
|
|
259
|
+
typeof rscOption === "boolean" ? {} : rscOption.entries || {};
|
|
260
|
+
const finalEntries = {
|
|
261
|
+
client: userEntries.client ?? VIRTUAL_IDS.browser,
|
|
262
|
+
ssr: userEntries.ssr ?? VIRTUAL_IDS.ssr,
|
|
263
|
+
rsc: userEntries.rsc ?? VIRTUAL_IDS.rsc,
|
|
264
|
+
};
|
|
265
|
+
|
|
266
|
+
// Track RSC entry for version injection (only if custom entry provided)
|
|
267
|
+
rscEntryPath = userEntries.rsc ?? null;
|
|
268
|
+
|
|
269
|
+
// Create wrapper plugin that checks for duplicates
|
|
270
|
+
let hasWarnedDuplicate = false;
|
|
271
|
+
|
|
272
|
+
plugins.push({
|
|
273
|
+
name: "@rangojs/router:rsc-integration",
|
|
274
|
+
enforce: "pre",
|
|
275
|
+
|
|
276
|
+
config() {
|
|
277
|
+
// Configure environments for RSC
|
|
278
|
+
// When using virtual entries, we need to explicitly configure optimizeDeps
|
|
279
|
+
// so Vite pre-bundles React before processing the virtual modules.
|
|
280
|
+
// Without this, the dep optimizer may run multiple times with different hashes,
|
|
281
|
+
// causing React instance mismatches.
|
|
282
|
+
const useVirtualClient = finalEntries.client === VIRTUAL_IDS.browser;
|
|
283
|
+
const useVirtualSSR = finalEntries.ssr === VIRTUAL_IDS.ssr;
|
|
284
|
+
const useVirtualRSC = finalEntries.rsc === VIRTUAL_IDS.rsc;
|
|
285
|
+
|
|
286
|
+
return {
|
|
287
|
+
// Exclude rsc-router modules from optimization to prevent module duplication
|
|
288
|
+
// This ensures the same Context instance is used by both browser entry and RSC proxy modules
|
|
289
|
+
optimizeDeps: {
|
|
290
|
+
exclude: excludeDeps,
|
|
291
|
+
esbuildOptions: sharedEsbuildOptions,
|
|
292
|
+
},
|
|
293
|
+
build: {
|
|
294
|
+
rollupOptions: { onwarn },
|
|
295
|
+
},
|
|
296
|
+
resolve: {
|
|
297
|
+
alias: rangoAliases,
|
|
298
|
+
},
|
|
299
|
+
environments: {
|
|
300
|
+
client: {
|
|
301
|
+
build: {
|
|
302
|
+
rollupOptions: {
|
|
303
|
+
output: {
|
|
304
|
+
manualChunks: getManualChunks,
|
|
305
|
+
},
|
|
306
|
+
},
|
|
307
|
+
},
|
|
308
|
+
// Always exclude rsc-router modules, conditionally add virtual entry
|
|
309
|
+
optimizeDeps: {
|
|
310
|
+
// Pre-bundle React and rsc-html-stream to prevent late discovery
|
|
311
|
+
// triggering ERR_OUTDATED_OPTIMIZED_DEP on cold starts
|
|
312
|
+
include: [
|
|
313
|
+
"react",
|
|
314
|
+
"react-dom",
|
|
315
|
+
"react/jsx-runtime",
|
|
316
|
+
"react/jsx-dev-runtime",
|
|
317
|
+
"rsc-html-stream/client",
|
|
318
|
+
],
|
|
319
|
+
exclude: excludeDeps,
|
|
320
|
+
esbuildOptions: sharedEsbuildOptions,
|
|
321
|
+
...(useVirtualClient && {
|
|
322
|
+
// Tell Vite to scan the virtual entry for dependencies
|
|
323
|
+
entries: [VIRTUAL_IDS.browser],
|
|
324
|
+
}),
|
|
325
|
+
},
|
|
326
|
+
},
|
|
327
|
+
...(useVirtualSSR && {
|
|
328
|
+
ssr: {
|
|
329
|
+
optimizeDeps: {
|
|
330
|
+
entries: [VIRTUAL_IDS.ssr],
|
|
331
|
+
// Pre-bundle all SSR deps to prevent late discovery triggering ERR_OUTDATED_OPTIMIZED_DEP
|
|
332
|
+
include: [
|
|
333
|
+
"react",
|
|
334
|
+
"react-dom",
|
|
335
|
+
"react-dom/server.edge",
|
|
336
|
+
"react-dom/static.edge",
|
|
337
|
+
"react/jsx-runtime",
|
|
338
|
+
"react/jsx-dev-runtime",
|
|
339
|
+
"@vitejs/plugin-rsc/vendor/react-server-dom/client.edge",
|
|
340
|
+
],
|
|
341
|
+
exclude: excludeDeps,
|
|
342
|
+
esbuildOptions: sharedEsbuildOptions,
|
|
343
|
+
},
|
|
344
|
+
},
|
|
345
|
+
}),
|
|
346
|
+
...(useVirtualRSC && {
|
|
347
|
+
rsc: {
|
|
348
|
+
optimizeDeps: {
|
|
349
|
+
entries: [VIRTUAL_IDS.rsc],
|
|
350
|
+
// Pre-bundle all RSC deps to prevent late discovery triggering ERR_OUTDATED_OPTIMIZED_DEP
|
|
351
|
+
include: [
|
|
352
|
+
"react",
|
|
353
|
+
"react/jsx-runtime",
|
|
354
|
+
"react/jsx-dev-runtime",
|
|
355
|
+
"@vitejs/plugin-rsc/vendor/react-server-dom/server.edge",
|
|
356
|
+
],
|
|
357
|
+
esbuildOptions: sharedEsbuildOptions,
|
|
358
|
+
},
|
|
359
|
+
},
|
|
360
|
+
}),
|
|
361
|
+
},
|
|
362
|
+
};
|
|
363
|
+
},
|
|
364
|
+
|
|
365
|
+
configResolved(config) {
|
|
366
|
+
if (showBanner) {
|
|
367
|
+
const mode =
|
|
368
|
+
config.command === "serve"
|
|
369
|
+
? process.argv.includes("preview")
|
|
370
|
+
? "preview"
|
|
371
|
+
: "dev"
|
|
372
|
+
: "build";
|
|
373
|
+
printBanner(mode, "node", rangoVersion);
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
// Count how many RSC base plugins there are (rsc:minimal is the main one)
|
|
377
|
+
const rscMinimalCount = config.plugins.filter(
|
|
378
|
+
(p) => p.name === "rsc:minimal",
|
|
379
|
+
).length;
|
|
380
|
+
|
|
381
|
+
if (rscMinimalCount > 1 && !hasWarnedDuplicate) {
|
|
382
|
+
hasWarnedDuplicate = true;
|
|
383
|
+
console.warn(
|
|
384
|
+
"[rsc-router] Duplicate @vitejs/plugin-rsc detected. " +
|
|
385
|
+
"Remove rsc() from your config or use rango({ rsc: false }) for manual configuration.",
|
|
386
|
+
);
|
|
387
|
+
}
|
|
388
|
+
},
|
|
389
|
+
});
|
|
390
|
+
|
|
391
|
+
// Add virtual entries plugin (RSC entry generated lazily from routerRef)
|
|
392
|
+
plugins.push(createVirtualEntriesPlugin(finalEntries, routerRef));
|
|
393
|
+
|
|
394
|
+
// Add the RSC plugin directly
|
|
395
|
+
// Cast to PluginOption to handle type differences between bundled vite types
|
|
396
|
+
plugins.push(
|
|
397
|
+
rsc({
|
|
398
|
+
entries: finalEntries,
|
|
399
|
+
}) as PluginOption,
|
|
400
|
+
);
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
// Deduplicate client references from third-party packages in dev mode.
|
|
404
|
+
// Prevents module duplication when server components import "use client"
|
|
405
|
+
// packages that are also imported directly by client components.
|
|
406
|
+
plugins.push(clientRefDedup());
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
// Fix HMR for "use client" components.
|
|
410
|
+
//
|
|
411
|
+
// @vitejs/plugin-rsc's hotUpdate returns undefined for "use client" files
|
|
412
|
+
// in the RSC environment. Vite then tries to propagate through the RSC
|
|
413
|
+
// module graph, but the proxy module has no import.meta.hot.accept()
|
|
414
|
+
// boundary, causing a full page reload. The client env would handle it
|
|
415
|
+
// fine via React Refresh, but the RSC env's full-reload arrives first.
|
|
416
|
+
//
|
|
417
|
+
// Fix: in the RSC env, return [] for "use client" files to signal
|
|
418
|
+
// "handled, nothing to propagate". The client env is left alone so
|
|
419
|
+
// React Refresh processes the update normally.
|
|
420
|
+
plugins.push({
|
|
421
|
+
name: "@rangojs/router:client-component-hmr",
|
|
422
|
+
hotUpdate(ctx) {
|
|
423
|
+
const envName = this.environment?.name;
|
|
424
|
+
if (envName !== "rsc" && envName !== "ssr") return;
|
|
425
|
+
|
|
426
|
+
// Check if the changed file is a "use client" module
|
|
427
|
+
const file = ctx.file;
|
|
428
|
+
if (
|
|
429
|
+
!file.endsWith(".tsx") &&
|
|
430
|
+
!file.endsWith(".ts") &&
|
|
431
|
+
!file.endsWith(".jsx") &&
|
|
432
|
+
!file.endsWith(".js")
|
|
433
|
+
)
|
|
434
|
+
return;
|
|
435
|
+
|
|
436
|
+
try {
|
|
437
|
+
const source = readFileSync(file, "utf-8");
|
|
438
|
+
const trimmed = source.trimStart();
|
|
439
|
+
if (
|
|
440
|
+
trimmed.startsWith('"use client"') ||
|
|
441
|
+
trimmed.startsWith("'use client'")
|
|
442
|
+
) {
|
|
443
|
+
// Consume the update in RSC/SSR envs. The proxy module was already
|
|
444
|
+
// re-transformed by the RSC plugin's hotUpdate. Without this, Vite
|
|
445
|
+
// tries to propagate through the RSC/SSR module graph where the proxy
|
|
446
|
+
// has no import.meta.hot.accept() boundary, triggering a full reload.
|
|
447
|
+
// The actual component update is handled by React Refresh in the
|
|
448
|
+
// client environment.
|
|
449
|
+
return [];
|
|
450
|
+
}
|
|
451
|
+
} catch {
|
|
452
|
+
// File deleted/moved during HMR, let default handling proceed
|
|
453
|
+
}
|
|
454
|
+
},
|
|
455
|
+
});
|
|
456
|
+
|
|
457
|
+
plugins.push(exposeActionId());
|
|
458
|
+
|
|
459
|
+
// "use cache" directive transform (enforce: "post"):
|
|
460
|
+
// Wraps exports with registerCachedFunction() for function-level caching.
|
|
461
|
+
plugins.push(useCacheTransform());
|
|
462
|
+
|
|
463
|
+
// Consolidated plugin for create* ID injection (enforce: "post"):
|
|
464
|
+
// loaders, handles, location state, and prerender handlers.
|
|
465
|
+
plugins.push(exposeInternalIds());
|
|
466
|
+
|
|
467
|
+
// Router ID injection runs at normal priority (no enforce) to avoid
|
|
468
|
+
// changing Vite's dep optimization timing.
|
|
469
|
+
plugins.push(exposeRouterId());
|
|
470
|
+
|
|
471
|
+
// Add version virtual module plugin for cache invalidation
|
|
472
|
+
plugins.push(createVersionPlugin());
|
|
473
|
+
|
|
474
|
+
// Entry path for discovery: user-specified value (if any) or undefined.
|
|
475
|
+
// Auto-discovered path is passed separately via routerRef.
|
|
476
|
+
// Cloudflare preset: deferred to configResolved (read from resolved Vite env config).
|
|
477
|
+
const discoveryEntryPath =
|
|
478
|
+
preset !== "cloudflare" ? routerRef.path : undefined;
|
|
479
|
+
// Ref for deferred auto-discovery (node preset only, undefined for cloudflare)
|
|
480
|
+
const discoveryRouterRef = preset !== "cloudflare" ? routerRef : undefined;
|
|
481
|
+
|
|
482
|
+
// Version injector: auto-injects VERSION and routes-manifest into custom entry.rsc files.
|
|
483
|
+
// Only applies when there's an explicit rscEntryPath or for cloudflare preset (resolved
|
|
484
|
+
// lazily in configResolved). For node preset without a custom entry, the router file
|
|
485
|
+
// must NOT be transformed — injecting routes-manifest there creates a circular dependency.
|
|
486
|
+
const injectorEntryPath =
|
|
487
|
+
rscEntryPath ?? (preset === "cloudflare" ? undefined : null);
|
|
488
|
+
if (injectorEntryPath !== null) {
|
|
489
|
+
plugins.push(createVersionInjectorPlugin(injectorEntryPath));
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
// Transform CJS vendor files to ESM for browser compatibility
|
|
493
|
+
// optimizeDeps.include doesn't work because the file is loaded after initial optimization
|
|
494
|
+
plugins.push(createCjsToEsmPlugin());
|
|
495
|
+
|
|
496
|
+
// Router discovery plugin for build-time manifest generation.
|
|
497
|
+
// For cloudflare, the entry is resolved lazily in configResolved from the RSC environment.
|
|
498
|
+
// For node, discoveryRouterRef provides the auto-discovered path when not user-specified.
|
|
499
|
+
plugins.push(
|
|
500
|
+
createRouterDiscoveryPlugin(discoveryEntryPath, {
|
|
501
|
+
routerPathRef: discoveryRouterRef,
|
|
502
|
+
enableBuildPrerender: prerenderEnabled,
|
|
503
|
+
staticRouteTypesGeneration: resolvedOptions.staticRouteTypesGeneration,
|
|
504
|
+
include: resolvedOptions.include,
|
|
505
|
+
exclude: resolvedOptions.exclude,
|
|
506
|
+
}),
|
|
507
|
+
);
|
|
508
|
+
|
|
509
|
+
return plugins;
|
|
510
|
+
}
|