@rangojs/router 0.0.0-experimental.eb0645d3 → 0.0.0-experimental.f1468e3c
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 +8 -0
- package/README.md +126 -16
- package/dist/bin/rango.js +319 -95
- package/dist/testing/vitest.js +82 -0
- package/dist/vite/index.js +2724 -1053
- package/package.json +68 -14
- package/skills/api-client/SKILL.md +211 -0
- package/skills/breadcrumbs/SKILL.md +64 -2
- package/skills/bundle-analysis/SKILL.md +159 -0
- package/skills/cache-guide/SKILL.md +224 -32
- package/skills/caching/SKILL.md +279 -17
- package/skills/composability/SKILL.md +27 -3
- package/skills/css/SKILL.md +76 -0
- package/skills/debug-manifest/SKILL.md +4 -2
- package/skills/document-cache/SKILL.md +78 -55
- package/skills/handler-use/SKILL.md +11 -9
- package/skills/hooks/SKILL.md +243 -29
- package/skills/host-router/SKILL.md +83 -23
- package/skills/i18n/SKILL.md +276 -0
- package/skills/intercept/SKILL.md +68 -19
- package/skills/layout/SKILL.md +13 -9
- package/skills/links/SKILL.md +190 -23
- package/skills/loader/SKILL.md +235 -9
- package/skills/middleware/SKILL.md +18 -10
- package/skills/migrate-nextjs/SKILL.md +43 -19
- package/skills/migrate-react-router/SKILL.md +8 -2
- package/skills/mime-routes/SKILL.md +28 -1
- package/skills/observability/SKILL.md +172 -0
- package/skills/parallel/SKILL.md +18 -7
- package/skills/prerender/SKILL.md +65 -60
- package/skills/rango/SKILL.md +251 -24
- package/skills/react-compiler/SKILL.md +168 -0
- package/skills/response-routes/SKILL.md +115 -48
- package/skills/route/SKILL.md +46 -5
- package/skills/router-setup/SKILL.md +30 -8
- package/skills/scripts/SKILL.md +179 -0
- package/skills/server-actions/SKILL.md +775 -0
- package/skills/tailwind/SKILL.md +27 -3
- package/skills/testing/SKILL.md +130 -0
- package/skills/testing/bindings.md +103 -0
- package/skills/testing/cache-prerender.md +127 -0
- package/skills/testing/client-components.md +124 -0
- package/skills/testing/e2e-parity.md +125 -0
- package/skills/testing/flight.md +91 -0
- package/skills/testing/handles.md +129 -0
- package/skills/testing/loader.md +128 -0
- package/skills/testing/middleware.md +99 -0
- package/skills/testing/render-handler.md +122 -0
- package/skills/testing/response-routes.md +95 -0
- package/skills/testing/reverse-and-types.md +84 -0
- package/skills/testing/server-actions.md +107 -0
- package/skills/testing/server-tree.md +128 -0
- package/skills/testing/setup.md +123 -0
- package/skills/typesafety/SKILL.md +322 -29
- package/skills/use-cache/SKILL.md +57 -14
- package/skills/view-transitions/SKILL.md +337 -0
- package/src/__augment-tests__/augment.ts +81 -0
- package/src/__augment-tests__/augmented.check.ts +116 -0
- package/src/__internal.ts +0 -65
- package/src/browser/action-coordinator.ts +53 -36
- package/src/browser/action-fence.ts +47 -0
- package/src/browser/app-shell.ts +39 -0
- package/src/browser/connection-warmup.ts +134 -0
- package/src/browser/cookie-name.ts +140 -0
- package/src/browser/event-controller.ts +192 -150
- package/src/browser/history-state.ts +21 -0
- package/src/browser/index.ts +3 -3
- package/src/browser/invalidate-client-cache.ts +52 -0
- package/src/browser/navigation-bridge.ts +94 -25
- package/src/browser/navigation-client.ts +121 -84
- package/src/browser/navigation-store-handle.ts +38 -0
- package/src/browser/navigation-store.ts +115 -67
- package/src/browser/navigation-transaction.ts +9 -59
- package/src/browser/network-error-handler.ts +34 -7
- package/src/browser/partial-update.ts +147 -128
- package/src/browser/prefetch/cache.ts +107 -56
- package/src/browser/prefetch/fetch.ts +204 -34
- package/src/browser/prefetch/queue.ts +6 -3
- package/src/browser/rango-state.ts +158 -76
- package/src/browser/react/Link.tsx +30 -7
- package/src/browser/react/NavigationProvider.tsx +283 -118
- package/src/browser/react/ScrollRestoration.tsx +10 -6
- package/src/browser/react/deferred-handle-resolution.ts +75 -0
- package/src/browser/react/filter-segment-order.ts +66 -7
- package/src/browser/react/index.ts +0 -48
- package/src/browser/react/location-state-shared.ts +178 -8
- package/src/browser/react/location-state.ts +39 -14
- package/src/browser/react/use-action.ts +6 -15
- package/src/browser/react/use-handle.ts +17 -14
- package/src/browser/react/use-href.tsx +8 -1
- package/src/browser/react/use-link-status.ts +33 -8
- package/src/browser/react/use-navigation.ts +10 -5
- package/src/browser/react/use-params.ts +11 -11
- package/src/browser/react/use-reverse.ts +106 -0
- package/src/browser/react/use-router.ts +25 -3
- package/src/browser/react/use-search-params.ts +0 -5
- package/src/browser/react/use-segments.ts +11 -21
- package/src/browser/response-adapter.ts +99 -8
- package/src/browser/rsc-router.tsx +91 -24
- package/src/browser/scroll-restoration.ts +30 -17
- package/src/browser/segment-structure-assert.ts +2 -2
- package/src/browser/server-action-bridge.ts +214 -55
- package/src/browser/types.ts +80 -9
- package/src/browser/validate-redirect-origin.ts +43 -16
- package/src/build/collect-fallback-refs.ts +107 -0
- package/src/build/generate-manifest.ts +60 -35
- package/src/build/generate-route-types.ts +2 -1
- package/src/build/index.ts +8 -2
- package/src/build/prefix-tree-utils.ts +123 -0
- package/src/build/route-trie.ts +117 -14
- package/src/build/route-types/ast-route-extraction.ts +15 -8
- package/src/build/route-types/codegen.ts +16 -5
- package/src/build/route-types/include-resolution.ts +117 -23
- package/src/build/route-types/param-extraction.ts +6 -3
- package/src/build/route-types/per-module-writer.ts +22 -6
- package/src/build/route-types/router-processing.ts +55 -28
- package/src/build/route-types/scan-filter.ts +1 -1
- package/src/build/route-types/source-scan.ts +216 -0
- package/src/build/runtime-discovery.ts +9 -20
- package/src/cache/cache-error.ts +104 -0
- package/src/cache/cache-key-utils.ts +29 -13
- package/src/cache/cache-policy.ts +108 -34
- package/src/cache/cache-runtime.ts +224 -41
- package/src/cache/cache-scope.ts +188 -82
- package/src/cache/cache-tag.ts +103 -0
- package/src/cache/cf/cf-base64.ts +33 -0
- package/src/cache/cf/cf-cache-constants.ts +127 -0
- package/src/cache/cf/cf-cache-store.ts +1989 -378
- package/src/cache/cf/cf-cache-types.ts +349 -0
- package/src/cache/cf/cf-kv-utils.ts +46 -0
- package/src/cache/cf/cf-tag-marker-memo.ts +105 -0
- package/src/cache/cf/index.ts +6 -16
- package/src/cache/document-cache.ts +89 -21
- package/src/cache/handle-snapshot.ts +70 -0
- package/src/cache/index.ts +10 -20
- package/src/cache/memory-segment-store.ts +136 -37
- package/src/cache/profile-registry.ts +46 -31
- package/src/cache/read-through-swr.ts +56 -12
- package/src/cache/segment-codec.ts +9 -17
- package/src/cache/tag-invalidation.ts +230 -0
- package/src/cache/types.ts +37 -100
- package/src/client.rsc.tsx +44 -21
- package/src/client.tsx +36 -61
- package/src/cloudflare/index.ts +11 -0
- package/src/cloudflare/tracing.ts +109 -0
- package/src/component-utils.ts +19 -0
- package/src/components/DefaultDocument.tsx +8 -2
- package/src/context-var.ts +18 -6
- package/src/decode-loader-results.ts +52 -0
- package/src/defer.ts +196 -0
- package/src/deps/ssr.ts +0 -1
- package/src/encode-kv.ts +49 -0
- package/src/errors.ts +30 -4
- package/src/escape-script.ts +52 -0
- package/src/handle.ts +31 -23
- package/src/handles/MetaTags.tsx +62 -19
- package/src/handles/Scripts.tsx +183 -0
- package/src/handles/breadcrumbs.ts +37 -8
- package/src/handles/is-thenable.ts +19 -0
- package/src/handles/meta.ts +51 -40
- package/src/handles/script.ts +244 -0
- package/src/host/cookie-handler.ts +9 -60
- package/src/host/errors.ts +0 -24
- package/src/host/index.ts +8 -2
- package/src/host/pattern-matcher.ts +23 -52
- package/src/host/router.ts +107 -99
- package/src/host/testing.ts +40 -27
- package/src/host/types.ts +37 -4
- package/src/host/utils.ts +1 -1
- package/src/href-client.ts +137 -22
- package/src/index.rsc.ts +96 -12
- package/src/index.ts +94 -14
- package/src/internal-debug.ts +11 -10
- package/src/loader-store.ts +500 -0
- package/src/loader.rsc.ts +20 -13
- package/src/loader.ts +12 -11
- package/src/missing-id-error.ts +68 -0
- package/src/outlet-context.ts +1 -1
- package/src/outlet-provider.tsx +1 -5
- package/src/prerender/param-hash.ts +16 -16
- package/src/prerender/store.ts +32 -37
- package/src/prerender.ts +61 -6
- package/src/redirect-origin.ts +100 -0
- package/src/regex-escape.ts +8 -0
- package/src/render-error-thrower.tsx +20 -0
- package/src/response-utils.ts +34 -0
- package/src/reverse.ts +65 -40
- package/src/root-error-boundary.tsx +1 -19
- package/src/route-content-wrapper.tsx +19 -77
- package/src/route-definition/dsl-helpers.ts +304 -309
- package/src/route-definition/helper-factories.ts +28 -140
- package/src/route-definition/helpers-types.ts +82 -55
- package/src/route-definition/index.ts +1 -2
- package/src/route-definition/redirect.ts +44 -11
- package/src/route-definition/resolve-handler-use.ts +12 -1
- package/src/route-definition/use-item-types.ts +29 -0
- package/src/route-map-builder.ts +0 -16
- package/src/route-types.ts +19 -46
- package/src/router/basename.ts +14 -0
- package/src/router/content-negotiation.ts +73 -25
- package/src/router/error-handling.ts +45 -18
- package/src/router/find-match.ts +44 -23
- package/src/router/handler-context.ts +27 -43
- package/src/router/instrument.ts +350 -0
- package/src/router/intercept-resolution.ts +39 -20
- package/src/router/lazy-includes.ts +10 -47
- package/src/router/loader-resolution.ts +155 -72
- package/src/router/logging.ts +0 -6
- package/src/router/manifest.ts +18 -29
- package/src/router/match-api.ts +9 -24
- package/src/router/match-context.ts +0 -22
- package/src/router/match-handlers.ts +58 -58
- package/src/router/match-middleware/background-revalidation.ts +40 -24
- package/src/router/match-middleware/cache-lookup.ts +159 -285
- package/src/router/match-middleware/cache-store.ts +64 -52
- package/src/router/match-middleware/intercept-resolution.ts +0 -22
- package/src/router/match-middleware/segment-resolution.ts +0 -22
- package/src/router/match-pipelines.ts +1 -42
- package/src/router/match-result.ts +44 -74
- package/src/router/metrics.ts +0 -34
- package/src/router/middleware-types.ts +7 -134
- package/src/router/middleware.ts +247 -166
- package/src/router/navigation-snapshot.ts +0 -51
- package/src/router/params-util.ts +23 -0
- package/src/router/pattern-matching.ts +85 -94
- package/src/router/prefetch-cache-ttl.ts +51 -0
- package/src/router/prerender-match.ts +104 -65
- package/src/router/preview-match.ts +3 -1
- package/src/router/request-classification.ts +28 -62
- package/src/router/revalidation.ts +123 -73
- package/src/router/route-snapshot.ts +0 -1
- package/src/router/router-context.ts +3 -28
- package/src/router/router-interfaces.ts +83 -35
- package/src/router/router-options.ts +136 -5
- package/src/router/router-registry.ts +2 -5
- package/src/router/segment-resolution/fresh.ts +97 -84
- package/src/router/segment-resolution/helpers.ts +86 -6
- package/src/router/segment-resolution/loader-cache.ts +76 -39
- package/src/router/segment-resolution/revalidation.ts +272 -320
- package/src/router/segment-resolution/static-store.ts +19 -5
- package/src/router/segment-resolution/streamed-handler-telemetry.ts +52 -0
- package/src/router/segment-resolution/view-transition-default.ts +56 -0
- package/src/router/segment-resolution.ts +5 -1
- package/src/router/segment-wrappers.ts +6 -5
- package/src/router/state-cookie-name.ts +33 -0
- package/src/router/substitute-pattern-params.ts +56 -0
- package/src/router/telemetry-otel.ts +161 -199
- package/src/router/telemetry.ts +96 -19
- package/src/router/timeout.ts +0 -20
- package/src/router/tracing.ts +206 -0
- package/src/router/trie-matching.ts +162 -64
- package/src/router/types.ts +9 -63
- package/src/router/url-params.ts +0 -5
- package/src/router.ts +110 -55
- package/src/rsc/handler-context.ts +3 -2
- package/src/rsc/handler.ts +264 -220
- package/src/rsc/helpers.ts +100 -6
- package/src/rsc/index.ts +2 -5
- package/src/rsc/json-route-result.ts +38 -0
- package/src/rsc/loader-fetch.ts +114 -38
- package/src/rsc/manifest-init.ts +28 -41
- package/src/rsc/origin-guard.ts +39 -25
- package/src/rsc/progressive-enhancement.ts +117 -11
- package/src/rsc/redirect-guard.ts +99 -0
- package/src/rsc/response-cache-serve.ts +238 -0
- package/src/rsc/response-error.ts +79 -12
- package/src/rsc/response-route-handler.ts +88 -188
- package/src/rsc/rsc-rendering.ts +98 -76
- package/src/rsc/runtime-warnings.ts +23 -10
- package/src/rsc/server-action.ts +281 -117
- package/src/rsc/ssr-setup.ts +16 -0
- package/src/rsc/transition-gate.ts +89 -0
- package/src/rsc/types.ts +23 -5
- package/src/runtime-env.ts +18 -0
- package/src/search-params.ts +35 -30
- package/src/segment-loader-promise.ts +31 -4
- package/src/segment-system.tsx +254 -143
- package/src/serialize.ts +243 -0
- package/src/server/context.ts +163 -51
- package/src/server/cookie-parse.ts +32 -0
- package/src/server/cookie-store.ts +80 -5
- package/src/server/handle-store.ts +21 -38
- package/src/server/loader-registry.ts +33 -42
- package/src/server/request-context.ts +287 -178
- package/src/ssr/index.tsx +21 -16
- package/src/static-handler.ts +10 -13
- package/src/testing/cache-status.ts +162 -0
- package/src/testing/collect-handle.ts +40 -0
- package/src/testing/dispatch.ts +701 -0
- package/src/testing/dom.entry.ts +22 -0
- package/src/testing/e2e/fixture.ts +188 -0
- package/src/testing/e2e/index.ts +128 -0
- package/src/testing/e2e/matchers.ts +35 -0
- package/src/testing/e2e/page-helpers.ts +272 -0
- package/src/testing/e2e/parity.ts +387 -0
- package/src/testing/e2e/server.ts +195 -0
- package/src/testing/flight-matchers.ts +97 -0
- package/src/testing/flight-normalize.ts +11 -0
- package/src/testing/flight-runtime.d.ts +57 -0
- package/src/testing/flight-tree.ts +682 -0
- package/src/testing/flight.entry.ts +52 -0
- package/src/testing/flight.ts +257 -0
- package/src/testing/generated-routes.ts +183 -0
- package/src/testing/index.ts +105 -0
- package/src/testing/internal/context.ts +371 -0
- package/src/testing/internal/flight-client-globals.ts +30 -0
- package/src/testing/internal/seed-vars.ts +54 -0
- package/src/testing/render-handler.ts +357 -0
- package/src/testing/render-route.tsx +581 -0
- package/src/testing/run-loader.ts +385 -0
- package/src/testing/run-middleware.ts +205 -0
- package/src/testing/run-transition-when.ts +164 -0
- package/src/testing/vitest-stubs/cloudflare-email.ts +9 -0
- package/src/testing/vitest-stubs/cloudflare-workers.ts +21 -0
- package/src/testing/vitest-stubs/plugin-rsc.ts +16 -0
- package/src/testing/vitest-stubs/version.ts +5 -0
- package/src/testing/vitest.ts +305 -0
- package/src/theme/ThemeProvider.tsx +20 -58
- package/src/theme/ThemeScript.tsx +7 -9
- package/src/theme/constants.ts +52 -13
- package/src/theme/index.ts +0 -7
- package/src/theme/theme-context.ts +1 -5
- package/src/theme/theme-script.ts +22 -21
- package/src/theme/use-theme.ts +0 -3
- package/src/types/boundaries.ts +0 -35
- package/src/types/cache-types.ts +13 -4
- package/src/types/error-types.ts +30 -90
- package/src/types/global-namespace.ts +54 -41
- package/src/types/handler-context.ts +110 -62
- package/src/types/index.ts +3 -10
- package/src/types/loader-types.ts +11 -9
- package/src/types/request-scope.ts +112 -0
- package/src/types/route-config.ts +6 -50
- package/src/types/route-entry.ts +0 -6
- package/src/types/segments.ts +135 -14
- package/src/urls/include-helper.ts +9 -56
- package/src/urls/index.ts +1 -11
- package/src/urls/path-helper-types.ts +29 -12
- package/src/urls/path-helper.ts +17 -106
- package/src/urls/pattern-types.ts +36 -19
- package/src/urls/response-types.ts +22 -29
- package/src/urls/type-extraction.ts +58 -139
- package/src/urls/urls-function.ts +1 -19
- package/src/use-loader.tsx +292 -107
- package/src/vite/debug.ts +185 -0
- package/src/vite/discovery/bundle-postprocess.ts +8 -7
- package/src/vite/discovery/discover-routers.ts +126 -85
- package/src/vite/discovery/discovery-errors.ts +194 -0
- package/src/vite/discovery/gate-state.ts +171 -0
- package/src/vite/discovery/prerender-collection.ts +96 -68
- package/src/vite/discovery/route-types-writer.ts +40 -84
- package/src/vite/discovery/self-gen-tracking.ts +27 -1
- package/src/vite/discovery/state.ts +44 -0
- package/src/vite/discovery/virtual-module-codegen.ts +14 -34
- package/src/vite/index.ts +2 -0
- package/src/vite/inject-client-debug.ts +36 -0
- package/src/vite/plugin-types.ts +126 -8
- package/src/vite/plugins/cjs-to-esm.ts +16 -19
- package/src/vite/plugins/client-ref-dedup.ts +16 -11
- package/src/vite/plugins/client-ref-hashing.ts +28 -15
- package/src/vite/plugins/cloudflare-protocol-stub.ts +1 -21
- package/src/vite/plugins/expose-action-id.ts +48 -95
- package/src/vite/plugins/expose-id-utils.ts +88 -55
- package/src/vite/plugins/expose-ids/export-analysis.ts +101 -34
- package/src/vite/plugins/expose-ids/handler-transform.ts +11 -90
- package/src/vite/plugins/expose-ids/loader-transform.ts +14 -24
- package/src/vite/plugins/expose-ids/router-transform.ts +118 -29
- package/src/vite/plugins/expose-internal-ids.ts +505 -486
- package/src/vite/plugins/performance-tracks.ts +26 -25
- package/src/vite/plugins/refresh-cmd.ts +1 -1
- package/src/vite/plugins/use-cache-transform.ts +73 -83
- package/src/vite/plugins/version-injector.ts +40 -29
- package/src/vite/plugins/version-plugin.ts +37 -40
- package/src/vite/plugins/virtual-entries.ts +39 -25
- package/src/vite/rango.ts +109 -118
- package/src/vite/router-discovery.ts +718 -119
- package/src/vite/utils/ast-handler-extract.ts +26 -35
- package/src/vite/utils/banner.ts +1 -1
- package/src/vite/utils/bundle-analysis.ts +10 -15
- package/src/vite/utils/client-chunks.ts +184 -0
- package/src/vite/utils/directive-prologue.ts +40 -0
- package/src/vite/utils/forward-user-plugins.ts +171 -0
- package/src/vite/utils/manifest-utils.ts +4 -59
- package/src/vite/utils/package-resolution.ts +20 -52
- package/src/vite/utils/prerender-utils.ts +54 -39
- package/src/vite/utils/shared-utils.ts +90 -41
- package/src/browser/action-response-classifier.ts +0 -99
- package/src/browser/react/use-client-cache.ts +0 -58
- package/src/browser/shallow.ts +0 -40
- package/src/handles/index.ts +0 -7
- package/src/network-error-thrower.tsx +0 -23
- package/src/router/middleware-cookies.ts +0 -55
|
@@ -1,8 +1,3 @@
|
|
|
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
1
|
export const VIRTUAL_ENTRY_BROWSER: string = `
|
|
7
2
|
import {
|
|
8
3
|
createFromReadableStream,
|
|
@@ -14,7 +9,7 @@ import {
|
|
|
14
9
|
import { createElement, StrictMode } from "react";
|
|
15
10
|
import { hydrateRoot } from "react-dom/client";
|
|
16
11
|
import { rscStream } from "@rangojs/router/internal/deps/html-stream-client";
|
|
17
|
-
import { initBrowserApp,
|
|
12
|
+
import { initBrowserApp, Rango } from "@rangojs/router/browser";
|
|
18
13
|
|
|
19
14
|
async function initializeApp() {
|
|
20
15
|
const deps = {
|
|
@@ -25,11 +20,16 @@ async function initializeApp() {
|
|
|
25
20
|
createTemporaryReferenceSet,
|
|
26
21
|
};
|
|
27
22
|
|
|
28
|
-
|
|
23
|
+
// initBrowserApp resolves the initial payload and returns the browser app
|
|
24
|
+
// context, including strictMode (default true) from createRouter. StrictMode
|
|
25
|
+
// is the default; createRouter({ strictMode: false }) ships the opt-out in the
|
|
26
|
+
// payload metadata. StrictMode emits no DOM, so toggling never changes markup.
|
|
27
|
+
const { strictMode } = await initBrowserApp({ rscStream, deps });
|
|
29
28
|
|
|
29
|
+
const app = createElement(Rango);
|
|
30
30
|
hydrateRoot(
|
|
31
31
|
document,
|
|
32
|
-
createElement(StrictMode, null,
|
|
32
|
+
strictMode === false ? app : createElement(StrictMode, null, app)
|
|
33
33
|
);
|
|
34
34
|
}
|
|
35
35
|
|
|
@@ -52,9 +52,31 @@ export const renderHTML = createSSRHandler({
|
|
|
52
52
|
`.trim();
|
|
53
53
|
|
|
54
54
|
/**
|
|
55
|
-
*
|
|
55
|
+
* Virtual modules an RSC entry must import at startup to register the data the
|
|
56
|
+
* request handler needs before the first request arrives:
|
|
57
|
+
*
|
|
58
|
+
* - routes-manifest: the pre-generated route map so href()/matching work on a
|
|
59
|
+
* cold start (full map in build, in-memory no-op in dev).
|
|
60
|
+
* - loader-manifest: setLoaderImports() for fetchable loaders. Critical for
|
|
61
|
+
* serverless/multi-process deployments and for fetchable loaders reachable
|
|
62
|
+
* only through a client component — without it those loaders are never
|
|
63
|
+
* registered for the _rsc_loader endpoint and fail in production.
|
|
64
|
+
*
|
|
65
|
+
* Single source of truth: both the generated virtual RSC entry below and the
|
|
66
|
+
* custom-entry injector (version-injector) consume this list, so a new
|
|
67
|
+
* bootstrap manifest cannot be added to one path and forgotten on the other.
|
|
68
|
+
* That exact drift (loader-manifest present here but missing from the injector)
|
|
69
|
+
* is what left fetchable loaders unresolved on custom worker entries.
|
|
56
70
|
*/
|
|
71
|
+
export const RSC_ENTRY_BOOTSTRAP_IMPORTS: readonly string[] = [
|
|
72
|
+
"virtual:rsc-router/routes-manifest",
|
|
73
|
+
"virtual:rsc-router/loader-manifest",
|
|
74
|
+
];
|
|
75
|
+
|
|
57
76
|
export function getVirtualEntryRSC(routerPath: string): string {
|
|
77
|
+
const bootstrapImports = RSC_ENTRY_BOOTSTRAP_IMPORTS.map(
|
|
78
|
+
(id) => `import "${id}";`,
|
|
79
|
+
).join("\n");
|
|
58
80
|
return `
|
|
59
81
|
import {
|
|
60
82
|
renderToReadableStream,
|
|
@@ -68,15 +90,9 @@ import { router } from "${routerPath}";
|
|
|
68
90
|
import { createRSCHandler } from "@rangojs/router/internal/rsc-handler";
|
|
69
91
|
import { VERSION } from "@rangojs/router:version";
|
|
70
92
|
|
|
71
|
-
//
|
|
72
|
-
//
|
|
73
|
-
|
|
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";
|
|
93
|
+
// Startup bootstrap imports (routes + loader manifests). See
|
|
94
|
+
// RSC_ENTRY_BOOTSTRAP_IMPORTS — the same list the custom-entry injector uses.
|
|
95
|
+
${bootstrapImports}
|
|
80
96
|
|
|
81
97
|
// Lazily create the handler on first request so that ESM live bindings
|
|
82
98
|
// have resolved by the time we read \`router\`. During HMR the module may
|
|
@@ -87,6 +103,11 @@ export default function handler(request, env) {
|
|
|
87
103
|
_handler = createRSCHandler({
|
|
88
104
|
router,
|
|
89
105
|
version: VERSION,
|
|
106
|
+
// Forward the router's CSP nonce provider. createRSCHandler reads the
|
|
107
|
+
// provider only from options.nonce; without this, createRouter({ nonce })
|
|
108
|
+
// is silently dropped on the Node preset (the Cloudflare path wires it via
|
|
109
|
+
// router.fetch). router.nonce is undefined when unconfigured, a safe no-op.
|
|
110
|
+
nonce: router.nonce,
|
|
90
111
|
deps: {
|
|
91
112
|
renderToReadableStream,
|
|
92
113
|
decodeReply,
|
|
@@ -104,9 +125,6 @@ export default function handler(request, env) {
|
|
|
104
125
|
`.trim();
|
|
105
126
|
}
|
|
106
127
|
|
|
107
|
-
/**
|
|
108
|
-
* Virtual module IDs
|
|
109
|
-
*/
|
|
110
128
|
export const VIRTUAL_IDS = {
|
|
111
129
|
browser: "virtual:rsc-router/entry.browser.js",
|
|
112
130
|
ssr: "virtual:rsc-router/entry.ssr.js",
|
|
@@ -114,10 +132,6 @@ export const VIRTUAL_IDS = {
|
|
|
114
132
|
version: "@rangojs/router:version",
|
|
115
133
|
} as const;
|
|
116
134
|
|
|
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
135
|
export function getVirtualVersionContent(version: string): string {
|
|
122
136
|
return `export const VERSION = ${JSON.stringify(version)};`;
|
|
123
137
|
}
|
package/src/vite/rango.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type PluginOption } from "vite";
|
|
2
2
|
import { readFileSync } from "node:fs";
|
|
3
3
|
import { resolve } from "node:path";
|
|
4
4
|
import { exposeActionId } from "./plugins/expose-action-id.js";
|
|
@@ -12,21 +12,37 @@ import { VIRTUAL_IDS } from "./plugins/virtual-entries.js";
|
|
|
12
12
|
import {
|
|
13
13
|
getExcludeDeps,
|
|
14
14
|
getPackageAliases,
|
|
15
|
+
getPublishedPackageName,
|
|
16
|
+
getVendorAliases,
|
|
15
17
|
} from "./utils/package-resolution.js";
|
|
16
18
|
import { findRouterFiles } from "../build/generate-route-types.js";
|
|
17
19
|
import { createVersionPlugin } from "./plugins/version-plugin.js";
|
|
18
20
|
import {
|
|
19
|
-
|
|
21
|
+
sharedRolldownOptions,
|
|
20
22
|
createVirtualEntriesPlugin,
|
|
21
23
|
onwarn,
|
|
22
24
|
getManualChunks,
|
|
23
25
|
} from "./utils/shared-utils.js";
|
|
26
|
+
import {
|
|
27
|
+
resolveClientChunks,
|
|
28
|
+
type ClientChunkContext,
|
|
29
|
+
} from "./utils/client-chunks.js";
|
|
24
30
|
import type { RangoOptions } from "./plugin-types.js";
|
|
25
31
|
import { printBanner, rangoVersion } from "./utils/banner.js";
|
|
26
32
|
import { createVersionInjectorPlugin } from "./plugins/version-injector.js";
|
|
27
33
|
import { createCjsToEsmPlugin } from "./plugins/cjs-to-esm.js";
|
|
28
34
|
import { createRouterDiscoveryPlugin } from "./router-discovery.js";
|
|
29
35
|
import { performanceTracksPlugin } from "./plugins/performance-tracks.js";
|
|
36
|
+
import { createRangoDebugger, NS } from "./debug.js";
|
|
37
|
+
|
|
38
|
+
const debugConfig = createRangoDebugger(NS.config);
|
|
39
|
+
|
|
40
|
+
// The leading-directive 'use client' sniff is shared with version-plugin's
|
|
41
|
+
// getClientModuleSignature so the two cannot drift. Imported for local use by the
|
|
42
|
+
// HMR transform below and re-exported because the E8 sniff test imports it from
|
|
43
|
+
// this module.
|
|
44
|
+
import { hasUseClientDirective } from "./utils/directive-prologue.js";
|
|
45
|
+
export { hasUseClientDirective };
|
|
30
46
|
|
|
31
47
|
/**
|
|
32
48
|
* Vite plugin for @rangojs/router.
|
|
@@ -53,25 +69,47 @@ import { performanceTracksPlugin } from "./plugins/performance-tracks.js";
|
|
|
53
69
|
* ```
|
|
54
70
|
*/
|
|
55
71
|
export async function rango(options?: RangoOptions): Promise<PluginOption[]> {
|
|
72
|
+
const rangoStart = performance.now();
|
|
56
73
|
const resolvedOptions: RangoOptions = options ?? { preset: "node" };
|
|
57
74
|
const preset = resolvedOptions.preset ?? "node";
|
|
58
75
|
const showBanner = resolvedOptions.banner ?? true;
|
|
76
|
+
const clientChunksOption = resolvedOptions.clientChunks ?? true;
|
|
77
|
+
const useBuiltInClientChunks = clientChunksOption === true;
|
|
78
|
+
const clientChunkCtx: ClientChunkContext | undefined = useBuiltInClientChunks
|
|
79
|
+
? { fallbackRefs: new Set<string>() }
|
|
80
|
+
: undefined;
|
|
81
|
+
const clientChunks = resolveClientChunks(clientChunksOption, clientChunkCtx);
|
|
82
|
+
debugConfig?.("rango(%s) setup start", preset);
|
|
59
83
|
|
|
60
84
|
const plugins: PluginOption[] = [];
|
|
61
85
|
|
|
62
|
-
// Get package resolution info (workspace vs npm install)
|
|
63
|
-
|
|
86
|
+
// Get package resolution info (workspace vs npm install).
|
|
87
|
+
// Vendor aliases redirect the bare plugin-rsc vendor specs (which plugin-rsc
|
|
88
|
+
// itself injects into optimizeDeps.include) to absolute paths resolved from
|
|
89
|
+
// this package — so strict-pnpm consumers don't hit "Failed to resolve
|
|
90
|
+
// dependency" warnings when those deps aren't hoisted to their app root.
|
|
91
|
+
const rangoAliases = { ...getPackageAliases(), ...getVendorAliases() };
|
|
64
92
|
const excludeDeps = [
|
|
65
93
|
...getExcludeDeps(),
|
|
66
|
-
//
|
|
67
|
-
//
|
|
68
|
-
// .
|
|
94
|
+
// plugin-rsc itself injects these into the client env's
|
|
95
|
+
// optimizeDeps.include, which overrides exclude for the dep's own
|
|
96
|
+
// pre-bundle entry. What exclude still controls is how *other*
|
|
97
|
+
// pre-bundled deps treat imports of these specs (external vs inlined)
|
|
98
|
+
// via esbuildCjsExternalPlugin. The cjs-to-esm transform in
|
|
99
|
+
// plugins/cjs-to-esm.ts is the fallback for strict-pnpm consumers,
|
|
100
|
+
// where client.browser's bare include fails to resolve and Vite ends up
|
|
101
|
+
// serving the raw CJS file at dev-serve time.
|
|
69
102
|
"@vitejs/plugin-rsc/browser",
|
|
70
|
-
// Keep the browser RSDW client out of Vite's dep optimizer so our
|
|
71
|
-
// cjs-to-esm transform can patch the real file.
|
|
72
103
|
"@vitejs/plugin-rsc/vendor/react-server-dom/client.browser",
|
|
73
104
|
];
|
|
74
105
|
|
|
106
|
+
// Vite supports a nested `A > B` syntax in optimizeDeps.include that resolves
|
|
107
|
+
// B from A's location. We anchor transitive deps (rsc-html-stream,
|
|
108
|
+
// @vitejs/plugin-rsc/vendor/*) to @rangojs/router so pnpm consumers — where
|
|
109
|
+
// these aren't visible at the app root — can still pre-bundle them.
|
|
110
|
+
const pkg = getPublishedPackageName();
|
|
111
|
+
const nested = (spec: string) => `${pkg} > ${spec}`;
|
|
112
|
+
|
|
75
113
|
// Mutable ref for router path (node preset only).
|
|
76
114
|
// Set immediately when user-specified, or populated by the auto-discover
|
|
77
115
|
// config() hook using Vite's resolved root.
|
|
@@ -82,14 +120,8 @@ export async function rango(options?: RangoOptions): Promise<PluginOption[]> {
|
|
|
82
120
|
const prerenderEnabled = true;
|
|
83
121
|
|
|
84
122
|
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
123
|
const { default: rsc } = await import("@vitejs/plugin-rsc");
|
|
90
124
|
|
|
91
|
-
// Only client and ssr entries - rsc entry is handled by cloudflare plugin
|
|
92
|
-
// Always use virtual modules for cloudflare preset
|
|
93
125
|
const finalEntries: { client: string; ssr: string } = {
|
|
94
126
|
client: VIRTUAL_IDS.browser,
|
|
95
127
|
ssr: VIRTUAL_IDS.ssr,
|
|
@@ -100,16 +132,21 @@ export async function rango(options?: RangoOptions): Promise<PluginOption[]> {
|
|
|
100
132
|
enforce: "pre",
|
|
101
133
|
|
|
102
134
|
config() {
|
|
103
|
-
// Configure environments for cloudflare deployment
|
|
104
135
|
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
136
|
optimizeDeps: {
|
|
108
137
|
exclude: excludeDeps,
|
|
109
|
-
|
|
138
|
+
rolldownOptions: sharedRolldownOptions,
|
|
110
139
|
},
|
|
111
140
|
resolve: {
|
|
112
141
|
alias: rangoAliases,
|
|
142
|
+
// Force a single React/React-DOM copy across all three RSC
|
|
143
|
+
// environments. RSC requires exactly one react/react-dom instance
|
|
144
|
+
// per environment runtime; consumer install topologies (pnpm
|
|
145
|
+
// strict layout, experimental React pins, third-party "use client"
|
|
146
|
+
// packages) can otherwise resolve duplicate copies, causing
|
|
147
|
+
// "Invalid hook call" / lost context. Child environments inherit
|
|
148
|
+
// this root dedupe, and Vite merges it with any consumer dedupe.
|
|
149
|
+
dedupe: ["react", "react-dom"],
|
|
113
150
|
},
|
|
114
151
|
build: {
|
|
115
152
|
rollupOptions: { onwarn },
|
|
@@ -118,30 +155,22 @@ export async function rango(options?: RangoOptions): Promise<PluginOption[]> {
|
|
|
118
155
|
client: {
|
|
119
156
|
build: {
|
|
120
157
|
rollupOptions: {
|
|
158
|
+
onwarn,
|
|
121
159
|
output: {
|
|
122
160
|
manualChunks: getManualChunks,
|
|
123
161
|
},
|
|
124
162
|
},
|
|
125
163
|
},
|
|
126
|
-
// Pre-bundle rsc-html-stream to prevent discovery during first request
|
|
127
|
-
// Exclude rsc-router modules to ensure same Context instance
|
|
128
164
|
optimizeDeps: {
|
|
129
|
-
include: ["rsc-html-stream/client"],
|
|
165
|
+
include: [nested("rsc-html-stream/client")],
|
|
130
166
|
exclude: excludeDeps,
|
|
131
|
-
|
|
167
|
+
rolldownOptions: sharedRolldownOptions,
|
|
132
168
|
},
|
|
133
169
|
},
|
|
134
170
|
ssr: {
|
|
135
|
-
// Build SSR inside RSC directory so wrangler can deploy self-contained dist/rsc
|
|
136
171
|
build: {
|
|
137
172
|
outDir: "./dist/rsc/ssr",
|
|
138
173
|
},
|
|
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
174
|
optimizeDeps: {
|
|
146
175
|
entries: [finalEntries.ssr],
|
|
147
176
|
include: [
|
|
@@ -151,26 +180,27 @@ export async function rango(options?: RangoOptions): Promise<PluginOption[]> {
|
|
|
151
180
|
"react-dom/static.edge",
|
|
152
181
|
"react/jsx-runtime",
|
|
153
182
|
"react/jsx-dev-runtime",
|
|
154
|
-
"rsc-html-stream/server",
|
|
155
|
-
|
|
183
|
+
nested("rsc-html-stream/server"),
|
|
184
|
+
nested(
|
|
185
|
+
"@vitejs/plugin-rsc/vendor/react-server-dom/client.edge",
|
|
186
|
+
),
|
|
156
187
|
],
|
|
157
188
|
exclude: excludeDeps,
|
|
158
|
-
|
|
189
|
+
rolldownOptions: sharedRolldownOptions,
|
|
159
190
|
},
|
|
160
191
|
},
|
|
161
192
|
rsc: {
|
|
162
|
-
// RSC environment needs exclude list and esbuild options
|
|
163
|
-
// Exclude rsc-router modules to prevent createContext in RSC environment
|
|
164
193
|
optimizeDeps: {
|
|
165
|
-
// Pre-bundle all RSC deps to prevent late discovery triggering ERR_OUTDATED_OPTIMIZED_DEP
|
|
166
194
|
include: [
|
|
167
195
|
"react",
|
|
168
196
|
"react/jsx-runtime",
|
|
169
197
|
"react/jsx-dev-runtime",
|
|
170
|
-
|
|
198
|
+
nested(
|
|
199
|
+
"@vitejs/plugin-rsc/vendor/react-server-dom/server.edge",
|
|
200
|
+
),
|
|
171
201
|
],
|
|
172
202
|
exclude: excludeDeps,
|
|
173
|
-
|
|
203
|
+
rolldownOptions: sharedRolldownOptions,
|
|
174
204
|
},
|
|
175
205
|
},
|
|
176
206
|
},
|
|
@@ -191,26 +221,16 @@ export async function rango(options?: RangoOptions): Promise<PluginOption[]> {
|
|
|
191
221
|
});
|
|
192
222
|
|
|
193
223
|
plugins.push(createVirtualEntriesPlugin(finalEntries));
|
|
194
|
-
|
|
195
|
-
// Dev-only: RSDW client patch for React Performance Tracks
|
|
196
224
|
plugins.push(performanceTracksPlugin());
|
|
197
|
-
|
|
198
|
-
// Add RSC plugin with cloudflare-specific options
|
|
199
|
-
// Note: loadModuleDevProxy should NOT be used with childEnvironments
|
|
200
|
-
// since SSR runs in workerd alongside RSC
|
|
201
225
|
plugins.push(
|
|
202
226
|
rsc({
|
|
203
227
|
entries: finalEntries,
|
|
204
228
|
serverHandler: false,
|
|
229
|
+
clientChunks,
|
|
205
230
|
}) as PluginOption,
|
|
206
231
|
);
|
|
207
|
-
|
|
208
|
-
// Deduplicate client references from third-party packages in dev mode.
|
|
209
|
-
// Prevents module duplication when server components import "use client"
|
|
210
|
-
// packages that are also imported directly by client components.
|
|
211
232
|
plugins.push(clientRefDedup());
|
|
212
233
|
} else {
|
|
213
|
-
// Auto-discover router using Vite's resolved root (not process.cwd())
|
|
214
234
|
plugins.push({
|
|
215
235
|
name: "@rangojs/router:auto-discover",
|
|
216
236
|
config(userConfig) {
|
|
@@ -231,20 +251,17 @@ export async function rango(options?: RangoOptions): Promise<PluginOption[]> {
|
|
|
231
251
|
" - " + (f.startsWith(root) ? f.slice(root.length + 1) : f),
|
|
232
252
|
)
|
|
233
253
|
.join("\n");
|
|
234
|
-
throw new Error(`[
|
|
254
|
+
throw new Error(`[rango] Multiple routers found:\n${list}`);
|
|
235
255
|
}
|
|
236
|
-
// 0 found: routerRef.path stays undefined, warn at startup via discovery plugin
|
|
237
256
|
},
|
|
238
257
|
});
|
|
239
258
|
|
|
240
|
-
// Always use virtual entries for client, ssr, and rsc
|
|
241
259
|
const finalEntries = {
|
|
242
260
|
client: VIRTUAL_IDS.browser,
|
|
243
261
|
ssr: VIRTUAL_IDS.ssr,
|
|
244
262
|
rsc: VIRTUAL_IDS.rsc,
|
|
245
263
|
};
|
|
246
264
|
|
|
247
|
-
// Dynamically import @vitejs/plugin-rsc
|
|
248
265
|
const { default: rsc } = await import("@vitejs/plugin-rsc");
|
|
249
266
|
|
|
250
267
|
let hasWarnedDuplicate = false;
|
|
@@ -257,18 +274,27 @@ export async function rango(options?: RangoOptions): Promise<PluginOption[]> {
|
|
|
257
274
|
return {
|
|
258
275
|
optimizeDeps: {
|
|
259
276
|
exclude: excludeDeps,
|
|
260
|
-
|
|
277
|
+
rolldownOptions: sharedRolldownOptions,
|
|
261
278
|
},
|
|
262
279
|
build: {
|
|
263
280
|
rollupOptions: { onwarn },
|
|
264
281
|
},
|
|
265
282
|
resolve: {
|
|
266
283
|
alias: rangoAliases,
|
|
284
|
+
// Force a single React/React-DOM copy across all three RSC
|
|
285
|
+
// environments. RSC requires exactly one react/react-dom instance
|
|
286
|
+
// per environment runtime; consumer install topologies (pnpm
|
|
287
|
+
// strict layout, experimental React pins, third-party "use client"
|
|
288
|
+
// packages) can otherwise resolve duplicate copies, causing
|
|
289
|
+
// "Invalid hook call" / lost context. Child environments inherit
|
|
290
|
+
// this root dedupe, and Vite merges it with any consumer dedupe.
|
|
291
|
+
dedupe: ["react", "react-dom"],
|
|
267
292
|
},
|
|
268
293
|
environments: {
|
|
269
294
|
client: {
|
|
270
295
|
build: {
|
|
271
296
|
rollupOptions: {
|
|
297
|
+
onwarn,
|
|
272
298
|
output: {
|
|
273
299
|
manualChunks: getManualChunks,
|
|
274
300
|
},
|
|
@@ -280,10 +306,10 @@ export async function rango(options?: RangoOptions): Promise<PluginOption[]> {
|
|
|
280
306
|
"react-dom",
|
|
281
307
|
"react/jsx-runtime",
|
|
282
308
|
"react/jsx-dev-runtime",
|
|
283
|
-
"rsc-html-stream/client",
|
|
309
|
+
nested("rsc-html-stream/client"),
|
|
284
310
|
],
|
|
285
311
|
exclude: excludeDeps,
|
|
286
|
-
|
|
312
|
+
rolldownOptions: sharedRolldownOptions,
|
|
287
313
|
entries: [VIRTUAL_IDS.browser],
|
|
288
314
|
},
|
|
289
315
|
},
|
|
@@ -297,10 +323,12 @@ export async function rango(options?: RangoOptions): Promise<PluginOption[]> {
|
|
|
297
323
|
"react-dom/static.edge",
|
|
298
324
|
"react/jsx-runtime",
|
|
299
325
|
"react/jsx-dev-runtime",
|
|
300
|
-
|
|
326
|
+
nested(
|
|
327
|
+
"@vitejs/plugin-rsc/vendor/react-server-dom/client.edge",
|
|
328
|
+
),
|
|
301
329
|
],
|
|
302
330
|
exclude: excludeDeps,
|
|
303
|
-
|
|
331
|
+
rolldownOptions: sharedRolldownOptions,
|
|
304
332
|
},
|
|
305
333
|
},
|
|
306
334
|
rsc: {
|
|
@@ -310,9 +338,17 @@ export async function rango(options?: RangoOptions): Promise<PluginOption[]> {
|
|
|
310
338
|
"react",
|
|
311
339
|
"react/jsx-runtime",
|
|
312
340
|
"react/jsx-dev-runtime",
|
|
313
|
-
|
|
341
|
+
nested(
|
|
342
|
+
"@vitejs/plugin-rsc/vendor/react-server-dom/server.edge",
|
|
343
|
+
),
|
|
314
344
|
],
|
|
315
|
-
|
|
345
|
+
// Vite 8 does not propagate the top-level optimizeDeps.exclude
|
|
346
|
+
// (set in config()) to non-client envs, so the rsc env must set
|
|
347
|
+
// it explicitly — mirroring the node ssr env and the cloudflare
|
|
348
|
+
// rsc env. Without it a strict-pnpm npm-installed app can try to
|
|
349
|
+
// pre-bundle the router's own subpath entries and fail.
|
|
350
|
+
exclude: excludeDeps,
|
|
351
|
+
rolldownOptions: sharedRolldownOptions,
|
|
316
352
|
},
|
|
317
353
|
},
|
|
318
354
|
},
|
|
@@ -337,42 +373,24 @@ export async function rango(options?: RangoOptions): Promise<PluginOption[]> {
|
|
|
337
373
|
if (rscMinimalCount > 1 && !hasWarnedDuplicate) {
|
|
338
374
|
hasWarnedDuplicate = true;
|
|
339
375
|
console.warn(
|
|
340
|
-
"[
|
|
376
|
+
"[rango] Duplicate @vitejs/plugin-rsc detected. " +
|
|
341
377
|
"Remove rsc() from your vite config — rango() includes it automatically.",
|
|
342
378
|
);
|
|
343
379
|
}
|
|
344
380
|
},
|
|
345
381
|
});
|
|
346
382
|
|
|
347
|
-
// Add virtual entries plugin (RSC entry generated lazily from routerRef)
|
|
348
383
|
plugins.push(createVirtualEntriesPlugin(finalEntries, routerRef));
|
|
349
|
-
|
|
350
|
-
// Dev-only: RSDW client patch for React Performance Tracks
|
|
351
384
|
plugins.push(performanceTracksPlugin());
|
|
352
|
-
|
|
353
385
|
plugins.push(
|
|
354
386
|
rsc({
|
|
355
387
|
entries: finalEntries,
|
|
388
|
+
clientChunks,
|
|
356
389
|
}) as PluginOption,
|
|
357
390
|
);
|
|
358
|
-
|
|
359
|
-
// Deduplicate client references from third-party packages in dev mode.
|
|
360
|
-
// Prevents module duplication when server components import "use client"
|
|
361
|
-
// packages that are also imported directly by client components.
|
|
362
391
|
plugins.push(clientRefDedup());
|
|
363
392
|
}
|
|
364
393
|
|
|
365
|
-
// Fix HMR for "use client" components.
|
|
366
|
-
//
|
|
367
|
-
// @vitejs/plugin-rsc's hotUpdate returns undefined for "use client" files
|
|
368
|
-
// in the RSC environment. Vite then tries to propagate through the RSC
|
|
369
|
-
// module graph, but the proxy module has no import.meta.hot.accept()
|
|
370
|
-
// boundary, causing a full page reload. The client env would handle it
|
|
371
|
-
// fine via React Refresh, but the RSC env's full-reload arrives first.
|
|
372
|
-
//
|
|
373
|
-
// Fix: in the RSC env, return [] for "use client" files to signal
|
|
374
|
-
// "handled, nothing to propagate". The client env is left alone so
|
|
375
|
-
// React Refresh processes the update normally.
|
|
376
394
|
plugins.push({
|
|
377
395
|
name: "@rangojs/router:client-component-hmr",
|
|
378
396
|
hotUpdate(ctx) {
|
|
@@ -391,72 +409,45 @@ export async function rango(options?: RangoOptions): Promise<PluginOption[]> {
|
|
|
391
409
|
|
|
392
410
|
try {
|
|
393
411
|
const source = readFileSync(file, "utf-8");
|
|
394
|
-
|
|
395
|
-
if (
|
|
396
|
-
trimmed.startsWith('"use client"') ||
|
|
397
|
-
trimmed.startsWith("'use client'")
|
|
398
|
-
) {
|
|
399
|
-
// Consume the update in RSC/SSR envs. The proxy module was already
|
|
400
|
-
// re-transformed by the RSC plugin's hotUpdate. Without this, Vite
|
|
401
|
-
// tries to propagate through the RSC/SSR module graph where the proxy
|
|
402
|
-
// has no import.meta.hot.accept() boundary, triggering a full reload.
|
|
403
|
-
// The actual component update is handled by React Refresh in the
|
|
404
|
-
// client environment.
|
|
412
|
+
if (hasUseClientDirective(source)) {
|
|
405
413
|
return [];
|
|
406
414
|
}
|
|
407
|
-
} catch {
|
|
408
|
-
// File deleted/moved during HMR, let default handling proceed
|
|
409
|
-
}
|
|
415
|
+
} catch {}
|
|
410
416
|
},
|
|
411
417
|
});
|
|
412
418
|
|
|
413
419
|
plugins.push(exposeActionId());
|
|
414
|
-
|
|
415
|
-
// "use cache" directive transform (enforce: "post"):
|
|
416
|
-
// Wraps exports with registerCachedFunction() for function-level caching.
|
|
417
420
|
plugins.push(useCacheTransform());
|
|
418
|
-
|
|
419
|
-
// Consolidated plugin for create* ID injection (enforce: "post"):
|
|
420
|
-
// loaders, handles, location state, and prerender handlers.
|
|
421
421
|
plugins.push(exposeInternalIds());
|
|
422
|
-
|
|
423
|
-
// Router ID injection runs at normal priority (no enforce) to avoid
|
|
424
|
-
// changing Vite's dep optimization timing.
|
|
425
422
|
plugins.push(exposeRouterId());
|
|
426
|
-
|
|
427
|
-
// Add version virtual module plugin for cache invalidation
|
|
428
423
|
plugins.push(createVersionPlugin());
|
|
429
424
|
|
|
430
|
-
// Entry path for discovery: user-specified value (if any) or undefined.
|
|
431
|
-
// Auto-discovered path is passed separately via routerRef.
|
|
432
|
-
// Cloudflare preset: deferred to configResolved (read from resolved Vite env config).
|
|
433
425
|
const discoveryEntryPath =
|
|
434
426
|
preset !== "cloudflare" ? routerRef.path : undefined;
|
|
435
|
-
// Ref for deferred auto-discovery (node preset only, undefined for cloudflare)
|
|
436
427
|
const discoveryRouterRef = preset !== "cloudflare" ? routerRef : undefined;
|
|
437
428
|
|
|
438
|
-
// Version injector: auto-injects VERSION and routes-manifest into the RSC entry.
|
|
439
|
-
// For cloudflare preset, the entry is resolved lazily in configResolved.
|
|
440
|
-
// For node preset, the virtual entry already includes these imports.
|
|
441
429
|
if (preset === "cloudflare") {
|
|
442
430
|
plugins.push(createVersionInjectorPlugin(undefined));
|
|
443
431
|
}
|
|
444
432
|
|
|
445
|
-
// Transform CJS vendor files to ESM for browser compatibility
|
|
446
|
-
// optimizeDeps.include doesn't work because the file is loaded after initial optimization
|
|
447
433
|
plugins.push(createCjsToEsmPlugin());
|
|
448
|
-
|
|
449
|
-
// Router discovery plugin for build-time manifest generation.
|
|
450
|
-
// For cloudflare, the entry is resolved lazily in configResolved from the RSC environment.
|
|
451
|
-
// For node, discoveryRouterRef provides the auto-discovered path when not user-specified.
|
|
452
434
|
plugins.push(
|
|
453
435
|
createRouterDiscoveryPlugin(discoveryEntryPath, {
|
|
454
436
|
routerPathRef: discoveryRouterRef,
|
|
455
437
|
enableBuildPrerender: prerenderEnabled,
|
|
456
438
|
buildEnv: options?.buildEnv,
|
|
457
439
|
preset,
|
|
440
|
+
prerenderOnError: options?.prerender?.onError,
|
|
441
|
+
discovery: options?.discovery,
|
|
442
|
+
clientChunkCtx,
|
|
458
443
|
}),
|
|
459
444
|
);
|
|
460
445
|
|
|
446
|
+
debugConfig?.(
|
|
447
|
+
"rango(%s) setup done: %d plugin(s) (%sms)",
|
|
448
|
+
preset,
|
|
449
|
+
plugins.length,
|
|
450
|
+
(performance.now() - rangoStart).toFixed(1),
|
|
451
|
+
);
|
|
461
452
|
return plugins;
|
|
462
453
|
}
|