vinext 1.2.0 → 1.3.0
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/README.md +13 -10
- package/dist/build/client-build-config.d.ts +64 -3
- package/dist/build/client-build-config.js +131 -4
- package/dist/build/client-reference-groups.d.ts +163 -0
- package/dist/build/client-reference-groups.js +534 -0
- package/dist/build/module-dependency-cache.d.ts +31 -0
- package/dist/build/module-dependency-cache.js +51 -1
- package/dist/build/next-client-runtime-manifests.d.ts +10 -1
- package/dist/build/next-client-runtime-manifests.js +19 -4
- package/dist/build/nitro-public-files.d.ts +24 -0
- package/dist/build/nitro-public-files.js +60 -0
- package/dist/build/output-root-externals.d.ts +21 -0
- package/dist/build/output-root-externals.js +40 -0
- package/dist/build/pages-client-assets-module.js +1 -1
- package/dist/build/prerender-paths.js +6 -3
- package/dist/build/prerender.js +1 -1
- package/dist/build/server-actions-encryption-key.d.ts +23 -0
- package/dist/build/server-actions-encryption-key.js +101 -0
- package/dist/build/ssr-manifest.d.ts +3 -0
- package/dist/build/ssr-manifest.js +10 -1
- package/dist/check.js +5 -6
- package/dist/cli-dev-config.js +3 -3
- package/dist/cli.js +1 -1
- package/dist/client/client-rewrite-params.d.ts +9 -0
- package/dist/client/client-rewrite-params.js +20 -0
- package/dist/client/dev-error-overlay.js +2 -1
- package/dist/client/navigation-runtime.d.ts +25 -2
- package/dist/client/navigation-runtime.js +42 -11
- package/dist/client/vinext-next-data.d.ts +0 -1
- package/dist/config/config-matchers.d.ts +15 -40
- package/dist/config/config-matchers.js +195 -262
- package/dist/config/config-source.d.ts +34 -0
- package/dist/config/config-source.js +141 -0
- package/dist/config/header-params.d.ts +29 -0
- package/dist/config/header-params.js +106 -0
- package/dist/config/next-config.d.ts +7 -5
- package/dist/config/next-config.js +120 -7
- package/dist/entries/app-browser-entry.d.ts +14 -1
- package/dist/entries/app-browser-entry.js +26 -36
- package/dist/entries/app-rsc-entry.d.ts +2 -0
- package/dist/entries/app-rsc-entry.js +92 -57
- package/dist/entries/app-rsc-manifest.d.ts +10 -0
- package/dist/entries/app-rsc-manifest.js +20 -1
- package/dist/entries/app-ssr-entry.d.ts +4 -1
- package/dist/entries/app-ssr-entry.js +9 -2
- package/dist/entries/pages-client-entry.d.ts +1 -0
- package/dist/entries/pages-client-entry.js +6 -6
- package/dist/entries/pages-server-entry.js +17 -14
- package/dist/index.d.ts +11 -0
- package/dist/index.js +350 -175
- package/dist/init.d.ts +1 -1
- package/dist/init.js +103 -6
- package/dist/plugins/ast-utils.d.ts +53 -2
- package/dist/plugins/ast-utils.js +90 -2
- package/dist/plugins/cloudflare-dev-module-urls.d.ts +41 -0
- package/dist/plugins/cloudflare-dev-module-urls.js +271 -0
- package/dist/plugins/commonjs-esm-facade.js +2 -2
- package/dist/plugins/css-module-imports.js +13 -20
- package/dist/plugins/dynamic-preload-metadata.js +2 -3
- package/dist/plugins/extensionless-dynamic-import.js +2 -3
- package/dist/plugins/fonts.d.ts +1 -1
- package/dist/plugins/fonts.js +3 -3
- package/dist/plugins/ignore-dynamic-requests.js +2 -3
- package/dist/plugins/import-meta-url.js +3 -4
- package/dist/plugins/instrumentation-client.js +3 -2
- package/dist/plugins/middleware-export-validation.js +2 -3
- package/dist/plugins/og-harfbuzz.js +2 -3
- package/dist/plugins/optimize-imports.d.ts +25 -2
- package/dist/plugins/optimize-imports.js +109 -24
- package/dist/plugins/pages-node-externals.js +2 -3
- package/dist/plugins/remove-console.js +2 -18
- package/dist/plugins/require-condition-resolution.js +3 -3
- package/dist/plugins/require-context.js +2 -3
- package/dist/plugins/rsc-client-reference-loaders.d.ts +45 -1
- package/dist/plugins/rsc-client-reference-loaders.js +336 -18
- package/dist/plugins/strip-server-exports.js +3 -4
- package/dist/plugins/styled-jsx.js +2 -3
- package/dist/plugins/use-cache-callable.d.ts +26 -2
- package/dist/plugins/use-cache-callable.js +101 -36
- package/dist/plugins/worker-image-imports.d.ts +1 -0
- package/dist/plugins/worker-image-imports.js +31 -34
- package/dist/plugins/worker-use-server.js +38 -14
- package/dist/routing/app-route-graph.d.ts +1 -1
- package/dist/routing/browser-route-manifest.d.ts +43 -0
- package/dist/routing/browser-route-manifest.js +195 -0
- package/dist/routing/hashed-route-patterns.d.ts +4 -0
- package/dist/routing/hashed-route-patterns.js +22 -0
- package/dist/routing/optimistic-route-trie.d.ts +27 -0
- package/dist/routing/optimistic-route-trie.js +102 -0
- package/dist/routing/route-validation.d.ts +6 -1
- package/dist/routing/route-validation.js +26 -10
- package/dist/server/api-handler.js +1 -1
- package/dist/server/app-action-forwarding.d.ts +8 -0
- package/dist/server/app-action-forwarding.js +17 -3
- package/dist/server/app-browser-entry.js +149 -62
- package/dist/server/app-browser-error.d.ts +3 -1
- package/dist/server/app-browser-error.js +7 -2
- package/dist/server/app-browser-interception-context.d.ts +2 -2
- package/dist/server/app-browser-interception-context.js +1 -1
- package/dist/server/app-browser-mpa-navigation.d.ts +1 -0
- package/dist/server/app-browser-mpa-navigation.js +6 -5
- package/dist/server/app-browser-navigation-controller.d.ts +17 -6
- package/dist/server/app-browser-navigation-controller.js +88 -26
- package/dist/server/app-browser-prefetch-response.js +2 -2
- package/dist/server/app-browser-state.d.ts +2 -2
- package/dist/server/app-browser-state.js +1 -1
- package/dist/server/app-browser-supplemental-refresh.js +1 -1
- package/dist/server/app-browser-visible-commit.d.ts +4 -4
- package/dist/server/app-client-reference-preloader.d.ts +23 -0
- package/dist/server/app-client-reference-preloader.js +30 -7
- package/dist/server/app-fallback-renderer.js +2 -1
- package/dist/server/app-middleware.d.ts +6 -0
- package/dist/server/app-middleware.js +8 -10
- package/dist/server/app-optimistic-routing.d.ts +8 -10
- package/dist/server/app-optimistic-routing.js +4 -95
- package/dist/server/app-page-boundary-render.js +8 -1
- package/dist/server/app-page-cache-render.js +1 -0
- package/dist/server/app-page-dispatch.js +3 -1
- package/dist/server/app-page-render.js +4 -2
- package/dist/server/app-page-rsc-render-status.d.ts +1 -0
- package/dist/server/app-page-rsc-render-status.js +1 -0
- package/dist/server/app-page-search-params-observation.d.ts +1 -4
- package/dist/server/app-page-search-params-observation.js +8 -10
- package/dist/server/app-page-stream.d.ts +7 -0
- package/dist/server/app-page-stream.js +1 -0
- package/dist/server/app-pages-bridge.d.ts +2 -1
- package/dist/server/app-pages-bridge.js +12 -8
- package/dist/server/app-prerender-endpoints.js +1 -1
- package/dist/server/app-prerender-static-params.js +3 -2
- package/dist/server/app-render-abort-error.d.ts +19 -0
- package/dist/server/app-render-abort-error.js +31 -1
- package/dist/server/app-render-dependency.js +42 -2
- package/dist/server/app-request-stage-independent-entry.js +7 -7
- package/dist/server/app-response-stage-entry.js +5 -5
- package/dist/server/app-route-handler-dispatch.js +3 -1
- package/dist/server/app-route-handler-execution.d.ts +2 -0
- package/dist/server/app-route-handler-execution.js +9 -2
- package/dist/server/app-route-handler-middleware-context.d.ts +2 -1
- package/dist/server/app-route-handler-middleware-context.js +3 -3
- package/dist/server/app-route-handler-response.d.ts +2 -1
- package/dist/server/app-route-handler-response.js +2 -2
- package/dist/server/app-route-handler-runtime.d.ts +2 -0
- package/dist/server/app-route-handler-runtime.js +21 -4
- package/dist/server/app-route-module-loader.js +7 -6
- package/dist/server/app-route-tree.d.ts +20 -0
- package/dist/server/app-route-tree.js +18 -0
- package/dist/server/app-router-entry.js +7 -7
- package/dist/server/app-rsc-cache-busting.d.ts +16 -0
- package/dist/server/app-rsc-cache-busting.js +29 -12
- package/dist/server/app-rsc-combined-handler.js +8 -1
- package/dist/server/app-rsc-errors.d.ts +7 -0
- package/dist/server/app-rsc-errors.js +9 -2
- package/dist/server/app-rsc-handler.d.ts +4 -1
- package/dist/server/app-rsc-handler.js +151 -135
- package/dist/server/app-rsc-request-normalization.js +3 -3
- package/dist/server/app-rsc-response-finalizer.d.ts +5 -0
- package/dist/server/app-rsc-response-finalizer.js +4 -1
- package/dist/server/app-rsc-response-stage.js +5 -3
- package/dist/server/app-rsc-route-matching.d.ts +1 -0
- package/dist/server/app-rsc-route-matching.js +1 -1
- package/dist/server/app-server-action-execution.d.ts +23 -6
- package/dist/server/app-server-action-execution.js +51 -57
- package/dist/server/app-ssr-entry.d.ts +6 -0
- package/dist/server/app-ssr-entry.js +21 -11
- package/dist/server/app-ssr-stream.d.ts +7 -0
- package/dist/server/app-ssr-stream.js +13 -1
- package/dist/server/app-visited-response-cache.js +2 -2
- package/dist/server/config-headers.js +13 -4
- package/dist/server/defer-until-stream-consumed.d.ts +2 -1
- package/dist/server/defer-until-stream-consumed.js +3 -1
- package/dist/server/dev-server.js +1 -1
- package/dist/server/image-optimization.js +1 -0
- package/dist/server/isolate-shared-promise.d.ts +10 -0
- package/dist/server/isolate-shared-promise.js +33 -0
- package/dist/server/isr-cache.js +3 -2
- package/dist/server/metadata-route-response.js +2 -2
- package/dist/server/middleware-matcher-pattern.d.ts +0 -1
- package/dist/server/middleware-matcher-pattern.js +11 -140
- package/dist/server/middleware-matcher.js +5 -6
- package/dist/server/middleware-response-headers.d.ts +31 -0
- package/dist/server/middleware-response-headers.js +57 -1
- package/dist/server/middleware-runtime.js +30 -17
- package/dist/server/navigation-planner.d.ts +2 -2
- package/dist/server/navigation-planner.js +1 -1
- package/dist/server/nitro-public-files-plugin.d.ts +38 -0
- package/dist/server/nitro-public-files-plugin.js +106 -0
- package/dist/server/nitro-public-files.d.ts +21 -0
- package/dist/server/nitro-public-files.js +39 -0
- package/dist/server/open-redirect.d.ts +11 -4
- package/dist/server/open-redirect.js +11 -4
- package/dist/server/pages-api-route.js +2 -2
- package/dist/server/pages-asset-tags.d.ts +5 -0
- package/dist/server/pages-asset-tags.js +9 -2
- package/dist/server/pages-client-assets.d.ts +4 -1
- package/dist/server/pages-data-route.js +2 -1
- package/dist/server/pages-i18n.d.ts +18 -0
- package/dist/server/pages-i18n.js +18 -2
- package/dist/server/pages-node-compat.d.ts +5 -3
- package/dist/server/pages-node-compat.js +35 -16
- package/dist/server/pages-page-data.js +1 -1
- package/dist/server/pages-page-handler.js +1 -1
- package/dist/server/pages-page-response.js +1 -1
- package/dist/server/pages-request-pipeline.d.ts +6 -1
- package/dist/server/pages-request-pipeline.js +35 -39
- package/dist/server/pages-request-stage-entry.js +20 -10
- package/dist/server/pages-response-stage-entry.js +1 -1
- package/dist/server/pages-revalidate.js +3 -2
- package/dist/server/pages-router-entry.js +2 -2
- package/dist/server/prod-server.d.ts +2 -2
- package/dist/server/prod-server.js +74 -36
- package/dist/server/proxy-trust.d.ts +6 -0
- package/dist/server/proxy-trust.js +12 -6
- package/dist/server/request-pipeline.d.ts +5 -0
- package/dist/server/request-pipeline.js +12 -1
- package/dist/server/rsc-stream-hints.d.ts +1 -1
- package/dist/server/rsc-stream-hints.js +21 -3
- package/dist/server/server-reference-loader.js +10 -1
- package/dist/server/static-file-cache.js +15 -3
- package/dist/server/worker-image-optimization.js +19 -6
- package/dist/server/worker-utils.js +1 -1
- package/dist/shims/cache-handler.js +3 -2
- package/dist/shims/cache-request-state.d.ts +40 -3
- package/dist/shims/cache-request-state.js +70 -5
- package/dist/shims/cache-runtime.js +47 -19
- package/dist/shims/cache.d.ts +2 -2
- package/dist/shims/cache.js +17 -8
- package/dist/shims/cdn-purge-routes.d.ts +24 -0
- package/dist/shims/cdn-purge-routes.js +77 -0
- package/dist/shims/dynamic.js +17 -4
- package/dist/shims/form.js +8 -3
- package/dist/shims/head.js +1 -1
- package/dist/shims/headers.js +2 -2
- package/dist/shims/image-props.d.ts +93 -0
- package/dist/shims/image-props.js +323 -0
- package/dist/shims/image.d.ts +4 -18
- package/dist/shims/image.js +4 -319
- package/dist/shims/internal/headers-state.d.ts +7 -0
- package/dist/shims/internal/headers-state.js +14 -2
- package/dist/shims/internal/hybrid-client-route-owner-direct.d.ts +4 -1
- package/dist/shims/internal/hybrid-client-route-owner-direct.js +32 -15
- package/dist/shims/internal/hybrid-client-route-owner.js +9 -8
- package/dist/shims/link-prefetch.js +5 -4
- package/dist/shims/link.js +7 -5
- package/dist/shims/navigation.d.ts +1 -1
- package/dist/shims/navigation.js +21 -10
- package/dist/shims/og.js +35 -10
- package/dist/shims/request-context.d.ts +13 -0
- package/dist/shims/router.js +28 -52
- package/dist/shims/server.d.ts +42 -8
- package/dist/shims/server.js +99 -15
- package/dist/shims/thenable-params.d.ts +6 -1
- package/dist/shims/thenable-params.js +11 -2
- package/dist/shims/unified-request-context.d.ts +5 -0
- package/dist/shims/unified-request-context.js +2 -0
- package/dist/shims/url-utils.d.ts +7 -0
- package/dist/shims/url-utils.js +12 -3
- package/dist/utils/asset-prefix.d.ts +7 -0
- package/dist/utils/asset-prefix.js +10 -1
- package/dist/utils/client-build-manifest.js +12 -5
- package/dist/utils/client-runtime-metadata.d.ts +1 -0
- package/dist/utils/client-runtime-metadata.js +15 -2
- package/dist/utils/domain-locale.js +1 -1
- package/dist/utils/lazy-chunks.d.ts +4 -0
- package/dist/utils/manifest-paths.d.ts +14 -0
- package/dist/utils/manifest-paths.js +22 -1
- package/dist/utils/path-to-regexp.d.ts +21 -0
- package/dist/{server/middleware-path-to-regexp.js → utils/path-to-regexp.js} +14 -11
- package/dist/utils/plugin-react-version.d.ts +15 -0
- package/dist/utils/plugin-react-version.js +64 -0
- package/dist/utils/plugin-rsc-version.d.ts +2 -0
- package/dist/utils/plugin-rsc-version.js +28 -2
- package/dist/utils/public-routes.d.ts +2 -0
- package/dist/utils/public-routes.js +18 -7
- package/dist/utils/react-version.d.ts +7 -0
- package/dist/utils/react-version.js +39 -16
- package/package.json +6 -6
- package/dist/build/nitro-route-rules.d.ts +0 -47
- package/dist/build/nitro-route-rules.js +0 -79
- package/dist/plugins/cache-flight-codec.d.ts +0 -19
- package/dist/plugins/cache-flight-codec.js +0 -68
- package/dist/server/middleware-path-to-regexp.d.ts +0 -13
- package/dist/utils/regex-safety.d.ts +0 -17
- package/dist/utils/regex-safety.js +0 -789
|
@@ -1,46 +1,364 @@
|
|
|
1
|
+
import path from "../deps/.pnpm/pathslash@0.1.0/deps/pathslash/dist/index.js";
|
|
2
|
+
import { CLIENT_REFERENCE_GROUP_MAX_COST_BYTES, collectClientReferencePreloadPlan, collectClientReferenceRouteSignatures, measureClientReferenceGroupCosts, planClientReferenceGroups, readClientModuleBindings } from "../build/client-reference-groups.js";
|
|
3
|
+
import { hasUserClientChunkGroups } from "../build/client-build-config.js";
|
|
4
|
+
import fs from "node:fs";
|
|
5
|
+
import { isCSSRequest } from "vite";
|
|
1
6
|
//#region src/plugins/rsc-client-reference-loaders.ts
|
|
2
7
|
const CLIENT_REFERENCES_ID = "\0virtual:vite-rsc/client-references";
|
|
3
8
|
const RESOLVED_ID_PROXY_PREFIX = "virtual:vite-rsc/resolved-id/";
|
|
9
|
+
const RESOLVED_CLIENT_REFERENCE_GROUP_PREFIX = `\0virtual:vinext-client-reference-group-`;
|
|
10
|
+
const CLIENT_REFERENCES_ID_RE = /^\0virtual:vite-rsc\/client-references$/;
|
|
11
|
+
const CLIENT_REFERENCE_GROUP_RE = /^virtual:vinext-client-reference-group-/;
|
|
12
|
+
const RESOLVED_CLIENT_REFERENCE_GROUP_RE = /^\0virtual:vinext-client-reference-group-/;
|
|
13
|
+
/**
|
|
14
|
+
* Whether the cost estimate loads a module. Rolldown keeps externals and
|
|
15
|
+
* unresolved `require()`s in `importedIds` under their specifier (a bare name
|
|
16
|
+
* or URL), and never settles a load of one, so only files and `\0` virtual
|
|
17
|
+
* modules are measured.
|
|
18
|
+
*/
|
|
19
|
+
function isMeasured(id) {
|
|
20
|
+
return id.startsWith("\0") || path.isAbsolute(id);
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Whether `id` shares the package `sideEffects` flag of `owner`: it is in the
|
|
24
|
+
* same package, and the package's `sideEffects` field is not a list of files.
|
|
25
|
+
* `uniformSideEffects` caches that last check per package.json path.
|
|
26
|
+
*/
|
|
27
|
+
function isInPackage(id, owner, uniformSideEffects) {
|
|
28
|
+
const packageJsonPath = owner.packageJsonPath;
|
|
29
|
+
if (!packageJsonPath) return false;
|
|
30
|
+
const relative = path.relative(path.dirname(packageJsonPath), id);
|
|
31
|
+
if (relative.startsWith("..") || relative.split("/").includes("node_modules")) return false;
|
|
32
|
+
let uniform = uniformSideEffects.get(packageJsonPath);
|
|
33
|
+
if (uniform === void 0) {
|
|
34
|
+
try {
|
|
35
|
+
const { sideEffects } = JSON.parse(fs.readFileSync(packageJsonPath, "utf8"));
|
|
36
|
+
uniform = sideEffects === void 0 || typeof sideEffects === "boolean";
|
|
37
|
+
} catch {
|
|
38
|
+
uniform = false;
|
|
39
|
+
}
|
|
40
|
+
uniformSideEffects.set(packageJsonPath, uniform);
|
|
41
|
+
}
|
|
42
|
+
return uniform;
|
|
43
|
+
}
|
|
4
44
|
function withResolvedIdProxy(resolvedId) {
|
|
5
45
|
return resolvedId.startsWith("\0") ? RESOLVED_ID_PROXY_PREFIX + encodeURIComponent(resolvedId) : resolvedId;
|
|
6
46
|
}
|
|
7
|
-
function
|
|
8
|
-
|
|
47
|
+
function sortedRenderedExports(meta) {
|
|
48
|
+
return meta.renderedExports.slice().sort();
|
|
49
|
+
}
|
|
50
|
+
function groupExportName(slotIndex, exportIndex) {
|
|
51
|
+
return `r${slotIndex}_${exportIndex}`;
|
|
52
|
+
}
|
|
53
|
+
function generateClientReferenceObject(meta, slot) {
|
|
54
|
+
const exports = sortedRenderedExports(meta).map((name, exportIndex) => {
|
|
55
|
+
const value = slot ? `m.${groupExportName(slot.index, exportIndex)}` : `m[${JSON.stringify(name)}]`;
|
|
56
|
+
return ` get ${JSON.stringify(name)}() { return ${value}; },`;
|
|
57
|
+
}).join("\n");
|
|
9
58
|
return exports ? `{\n${exports}\n }` : "{}";
|
|
10
59
|
}
|
|
11
|
-
function
|
|
60
|
+
function generateClientReferenceLoaders(metas, slots = /* @__PURE__ */ new Map()) {
|
|
12
61
|
return `export default {\n${metas.slice().sort((a, b) => a.referenceKey.localeCompare(b.referenceKey)).map((meta) => {
|
|
13
|
-
const
|
|
62
|
+
const slot = slots.get(meta);
|
|
63
|
+
const source = slot ? slot.groupId : withResolvedIdProxy(meta.importId);
|
|
14
64
|
return [
|
|
15
65
|
` ${JSON.stringify(meta.referenceKey)}: async () => {`,
|
|
16
|
-
` const m = await import(${JSON.stringify(
|
|
17
|
-
` return ${generateClientReferenceObject(meta)};`,
|
|
66
|
+
` const m = await import(${JSON.stringify(source)});`,
|
|
67
|
+
` return ${generateClientReferenceObject(meta, slot)};`,
|
|
18
68
|
` },`
|
|
19
69
|
].join("\n");
|
|
20
70
|
}).join("\n")}\n};\n`;
|
|
21
71
|
}
|
|
22
|
-
|
|
72
|
+
/**
|
|
73
|
+
* Re-export only each member's rendered exports, as live bindings, so unused
|
|
74
|
+
* exports and their dependencies still tree-shake as they do with direct
|
|
75
|
+
* loaders. A member without rendered exports is imported for its side effects.
|
|
76
|
+
*/
|
|
77
|
+
function generateClientReferenceGroupModule(metas) {
|
|
78
|
+
return `${metas.map((meta, slotIndex) => {
|
|
79
|
+
const source = JSON.stringify(withResolvedIdProxy(meta.importId));
|
|
80
|
+
const specifiers = sortedRenderedExports(meta).map((name, exportIndex) => {
|
|
81
|
+
return `${/^[A-Za-z_$][\w$]*$/.test(name) ? name : JSON.stringify(name)} as ${groupExportName(slotIndex, exportIndex)}`;
|
|
82
|
+
});
|
|
83
|
+
return specifiers.length > 0 ? `export { ${specifiers.join(", ")} } from ${source};` : `import ${source};`;
|
|
84
|
+
}).join("\n")}\n`;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* The SSR build's `routeClientReferences` export: the reference keys each route
|
|
88
|
+
* preloads before it renders (see server/app-client-reference-preloader.ts),
|
|
89
|
+
* stored as indices into `references`. Client references the plan doesn't know
|
|
90
|
+
* join `always`.
|
|
91
|
+
*/
|
|
92
|
+
function generateRouteClientReferencesExport(plan, metaEntries) {
|
|
93
|
+
if (!plan) return "export const routeClientReferences = null;\n";
|
|
94
|
+
const metaById = new Map(metaEntries);
|
|
95
|
+
const references = [];
|
|
96
|
+
const indices = /* @__PURE__ */ new Map();
|
|
97
|
+
const toIndices = (referenceIds) => referenceIds.flatMap((referenceId) => {
|
|
98
|
+
const meta = metaById.get(referenceId);
|
|
99
|
+
if (!meta) return [];
|
|
100
|
+
let index = indices.get(referenceId);
|
|
101
|
+
if (index === void 0) {
|
|
102
|
+
index = references.length;
|
|
103
|
+
indices.set(referenceId, index);
|
|
104
|
+
references.push(meta.referenceKey);
|
|
105
|
+
}
|
|
106
|
+
return [index];
|
|
107
|
+
});
|
|
108
|
+
const manifest = {
|
|
109
|
+
references,
|
|
110
|
+
always: toIndices([...plan.preloads.always, ...metaEntries.map(([referenceId]) => referenceId).filter((referenceId) => !plan.referenceIds.has(referenceId))]),
|
|
111
|
+
files: plan.preloads.files.map(toIndices),
|
|
112
|
+
routes: Object.fromEntries(plan.preloads.routes),
|
|
113
|
+
routeless: plan.preloads.routeless
|
|
114
|
+
};
|
|
115
|
+
return `export const routeClientReferences = ${JSON.stringify(manifest)};\n`;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Replaces @vitejs/plugin-rsc's client-reference facades with per-reference
|
|
119
|
+
* loaders. With `routes`, the SSR build also exports the client references
|
|
120
|
+
* each App Router route preloads. With `grouping`, production client builds
|
|
121
|
+
* additionally load references that the same App Router routes reach through
|
|
122
|
+
* one shared route group module (see build/client-reference-groups.ts), so a
|
|
123
|
+
* page fetches one chunk per route group instead of one per `"use client"`
|
|
124
|
+
* module.
|
|
125
|
+
*/
|
|
126
|
+
function createRscClientReferenceLoadersPlugin(options = {}) {
|
|
127
|
+
const { routes: routeOptions } = options;
|
|
128
|
+
const grouping = routeOptions && options.grouping;
|
|
23
129
|
let rscApi;
|
|
130
|
+
let root = "";
|
|
131
|
+
let groupingEnabled = false;
|
|
132
|
+
let routeSignatures = /* @__PURE__ */ new Map();
|
|
133
|
+
// @vitejs/plugin-rsc also builds before the SSR environment.
|
|
134
|
+
let preloadPlan = null;
|
|
135
|
+
const groupModules = /* @__PURE__ */ new Map();
|
|
24
136
|
return {
|
|
25
137
|
name: "vinext:rsc-client-reference-loaders",
|
|
26
138
|
enforce: "post",
|
|
27
139
|
configResolved(config) {
|
|
140
|
+
root = config.root;
|
|
28
141
|
rscApi = config.plugins.find((plugin) => plugin.name === "rsc:minimal")?.api;
|
|
29
142
|
},
|
|
30
|
-
|
|
31
|
-
|
|
143
|
+
outputOptions: {
|
|
144
|
+
order: "post",
|
|
145
|
+
handler(output) {
|
|
146
|
+
if (this.environment?.name !== "client") return;
|
|
147
|
+
groupingEnabled = !!grouping && !hasUserClientChunkGroups(output, grouping.ownClientChunkGroups);
|
|
148
|
+
}
|
|
149
|
+
},
|
|
150
|
+
buildStart() {
|
|
151
|
+
if (this.environment.name === "rsc") {
|
|
152
|
+
routeSignatures = /* @__PURE__ */ new Map();
|
|
153
|
+
preloadPlan = null;
|
|
154
|
+
}
|
|
155
|
+
if (this.environment.name === "client") groupModules.clear();
|
|
156
|
+
},
|
|
157
|
+
buildEnd(error) {
|
|
158
|
+
if (error || !routeOptions) return;
|
|
159
|
+
if (this.environment.name !== "rsc" || this.environment.mode !== "build") return;
|
|
32
160
|
const manager = rscApi?.manager;
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
161
|
+
const routes = routeOptions.getRoutes();
|
|
162
|
+
if (!manager || manager.isScanBuild || !routes) return;
|
|
163
|
+
const clientReferenceIds = new Set(Object.keys(manager.clientReferenceMetaMap));
|
|
164
|
+
const getModuleInfo = (id) => this.getModuleInfo(id);
|
|
165
|
+
preloadPlan = {
|
|
166
|
+
referenceIds: clientReferenceIds,
|
|
167
|
+
preloads: collectClientReferencePreloadPlan({
|
|
168
|
+
alwaysRoots: routeOptions.getAlwaysRenderedFiles(),
|
|
169
|
+
canonicalizeModuleId: routeOptions.canonicalizeModuleId,
|
|
170
|
+
clientReferenceIds,
|
|
171
|
+
entryIds: [...this.getModuleIds()].filter((id) => this.getModuleInfo(id)?.isEntry),
|
|
172
|
+
getModuleInfo,
|
|
173
|
+
routelessFiles: routeOptions.getRoutelessFiles(),
|
|
174
|
+
routes
|
|
175
|
+
})
|
|
41
176
|
};
|
|
177
|
+
if (!grouping) return;
|
|
178
|
+
routeSignatures = collectClientReferenceRouteSignatures({
|
|
179
|
+
canonicalizeModuleId: routeOptions.canonicalizeModuleId,
|
|
180
|
+
clientReferenceIds,
|
|
181
|
+
getModuleInfo,
|
|
182
|
+
root,
|
|
183
|
+
routes,
|
|
184
|
+
sharedRoots: routeOptions.getSharedRoots()
|
|
185
|
+
});
|
|
186
|
+
},
|
|
187
|
+
resolveId: {
|
|
188
|
+
filter: { id: CLIENT_REFERENCE_GROUP_RE },
|
|
189
|
+
handler(source) {
|
|
190
|
+
return groupModules.has(`\0${source}`) ? `\0${source}` : null;
|
|
191
|
+
}
|
|
192
|
+
},
|
|
193
|
+
load: {
|
|
194
|
+
filter: { id: RESOLVED_CLIENT_REFERENCE_GROUP_RE },
|
|
195
|
+
handler(id) {
|
|
196
|
+
return groupModules.get(id) ?? null;
|
|
197
|
+
}
|
|
198
|
+
},
|
|
199
|
+
transform: {
|
|
200
|
+
filter: { id: CLIENT_REFERENCES_ID_RE },
|
|
201
|
+
async handler(code) {
|
|
202
|
+
const manager = rscApi?.manager;
|
|
203
|
+
if (!manager || manager.isScanBuild) return null;
|
|
204
|
+
const isServer = this.environment.config.consumer === "server";
|
|
205
|
+
const metaEntries = Object.entries(manager.clientReferenceMetaMap).filter(([, meta]) => meta.serverChunk);
|
|
206
|
+
const metas = metaEntries.map(([, meta]) => meta);
|
|
207
|
+
const routeClientReferencesExport = isServer ? generateRouteClientReferencesExport(preloadPlan, metaEntries) : "";
|
|
208
|
+
if (metas.length === 0) return isServer ? {
|
|
209
|
+
code: `${code}\n${routeClientReferencesExport}`,
|
|
210
|
+
map: null
|
|
211
|
+
} : null;
|
|
212
|
+
for (const [id, meta] of metaEntries) meta.groupChunkId = id;
|
|
213
|
+
const slots = /* @__PURE__ */ new Map();
|
|
214
|
+
const referenceIds = new Set(metaEntries.map(([referenceId]) => referenceId));
|
|
215
|
+
const referenceKeys = new Map(metaEntries.map(([referenceId, meta]) => [referenceId, meta.referenceKey]));
|
|
216
|
+
if (grouping && groupingEnabled && this.environment.name === "client" && this.environment.mode === "build" && planClientReferenceGroups({
|
|
217
|
+
referenceIds,
|
|
218
|
+
referenceKeys,
|
|
219
|
+
signatures: routeSignatures,
|
|
220
|
+
costs: new Map([...referenceIds].map((referenceId) => [referenceId, 0])),
|
|
221
|
+
maxCostBytes: 0
|
|
222
|
+
}).length > 0) {
|
|
223
|
+
const references = /* @__PURE__ */ new Map();
|
|
224
|
+
const resolutions = /* @__PURE__ */ new Map();
|
|
225
|
+
const packages = /* @__PURE__ */ new Map();
|
|
226
|
+
const externalIds = /* @__PURE__ */ new Set();
|
|
227
|
+
const uniformSideEffects = /* @__PURE__ */ new Map();
|
|
228
|
+
const resolveCache = /* @__PURE__ */ new Map();
|
|
229
|
+
const addResolution = (resolved) => {
|
|
230
|
+
resolutions.set(resolved.id, resolved);
|
|
231
|
+
packages.set(resolved.id, resolved);
|
|
232
|
+
};
|
|
233
|
+
await Promise.all(metaEntries.map(async ([referenceId, meta]) => {
|
|
234
|
+
if (meta.importId.startsWith("\0")) {
|
|
235
|
+
references.set(referenceId, meta.importId);
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
const resolved = await this.resolve(meta.importId);
|
|
239
|
+
if (!resolved || resolved.external) return;
|
|
240
|
+
references.set(referenceId, resolved.id);
|
|
241
|
+
addResolution(resolved);
|
|
242
|
+
}));
|
|
243
|
+
const { external } = this.environment.config.build.rolldownOptions;
|
|
244
|
+
const moduleInfos = /* @__PURE__ */ new Map();
|
|
245
|
+
const excludedById = /* @__PURE__ */ new Map();
|
|
246
|
+
const isExcludedById = (moduleId) => {
|
|
247
|
+
let excluded = excludedById.get(moduleId);
|
|
248
|
+
if (excluded === void 0) {
|
|
249
|
+
excluded = !isMeasured(moduleId) || moduleId === CLIENT_REFERENCES_ID || moduleId.startsWith(RESOLVED_CLIENT_REFERENCE_GROUP_PREFIX) || isCSSRequest(moduleId) || grouping.isAlwaysLoadedClientModule(moduleId);
|
|
250
|
+
excludedById.set(moduleId, excluded);
|
|
251
|
+
}
|
|
252
|
+
return excluded;
|
|
253
|
+
};
|
|
254
|
+
const costs = await measureClientReferenceGroupCosts({
|
|
255
|
+
references,
|
|
256
|
+
loadModule: async (moduleId) => {
|
|
257
|
+
if (external && !resolutions.has(moduleId) && !moduleId.startsWith("\0")) {
|
|
258
|
+
const resolved = await this.resolve(moduleId);
|
|
259
|
+
if (!resolved || resolved.external) return {
|
|
260
|
+
code: "",
|
|
261
|
+
importedIds: []
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
const info = await this.load(resolutions.get(moduleId) ?? { id: moduleId });
|
|
265
|
+
moduleInfos.set(moduleId, info);
|
|
266
|
+
const { code, importedIds } = info;
|
|
267
|
+
if (code === null) return {
|
|
268
|
+
code,
|
|
269
|
+
importedIds
|
|
270
|
+
};
|
|
271
|
+
const importedIdSet = new Set(importedIds);
|
|
272
|
+
const owner = packages.get(moduleId);
|
|
273
|
+
return {
|
|
274
|
+
code,
|
|
275
|
+
importedIds,
|
|
276
|
+
bindings: await readClientModuleBindings({
|
|
277
|
+
code,
|
|
278
|
+
importedIds,
|
|
279
|
+
resolve: async (specifier) => {
|
|
280
|
+
if (owner && path.isAbsolute(moduleId) && (specifier.startsWith("./") || specifier.startsWith("../"))) {
|
|
281
|
+
const candidate = path.resolve(path.dirname(moduleId), specifier);
|
|
282
|
+
if (importedIdSet.has(candidate) && isInPackage(candidate, owner, uniformSideEffects)) {
|
|
283
|
+
packages.set(candidate, owner);
|
|
284
|
+
return candidate;
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
const key = `${path.dirname(moduleId)}\0${specifier}`;
|
|
288
|
+
let resolving = resolveCache.get(key);
|
|
289
|
+
if (!resolving) {
|
|
290
|
+
resolving = this.resolve(specifier, moduleId).then((resolved) => {
|
|
291
|
+
if (!resolved) return null;
|
|
292
|
+
if (resolved.external) externalIds.add(resolved.id);
|
|
293
|
+
else addResolution(resolved);
|
|
294
|
+
return resolved.id;
|
|
295
|
+
});
|
|
296
|
+
resolveCache.set(key, resolving);
|
|
297
|
+
}
|
|
298
|
+
return resolving;
|
|
299
|
+
}
|
|
300
|
+
})
|
|
301
|
+
};
|
|
302
|
+
},
|
|
303
|
+
isSideEffectFree: (moduleId) => packages.get(moduleId)?.moduleSideEffects === false,
|
|
304
|
+
isExcluded: (moduleId) => externalIds.has(moduleId) || isExcludedById(moduleId)
|
|
305
|
+
});
|
|
306
|
+
for (const [referenceId, meta] of metaEntries) {
|
|
307
|
+
const moduleId = references.get(referenceId);
|
|
308
|
+
const info = moduleId === void 0 ? void 0 : moduleInfos.get(moduleId);
|
|
309
|
+
if (!info || info.inputFormat === "cjs") continue;
|
|
310
|
+
if (meta.renderedExports.some((name) => !info.exports.includes(name))) costs.set(referenceId, null);
|
|
311
|
+
}
|
|
312
|
+
const groups = planClientReferenceGroups({
|
|
313
|
+
referenceIds,
|
|
314
|
+
referenceKeys,
|
|
315
|
+
signatures: routeSignatures,
|
|
316
|
+
costs,
|
|
317
|
+
maxCostBytes: CLIENT_REFERENCE_GROUP_MAX_COST_BYTES
|
|
318
|
+
});
|
|
319
|
+
const metaById = new Map(metaEntries);
|
|
320
|
+
for (const group of groups) {
|
|
321
|
+
const groupMetas = group.referenceIds.map((referenceId) => metaById.get(referenceId));
|
|
322
|
+
const resolvedGroupId = `${RESOLVED_CLIENT_REFERENCE_GROUP_PREFIX}${group.key}`;
|
|
323
|
+
groupModules.set(resolvedGroupId, generateClientReferenceGroupModule(groupMetas));
|
|
324
|
+
groupMetas.forEach((meta, index) => {
|
|
325
|
+
meta.groupChunkId = resolvedGroupId;
|
|
326
|
+
slots.set(meta, {
|
|
327
|
+
groupId: resolvedGroupId.slice(1),
|
|
328
|
+
index
|
|
329
|
+
});
|
|
330
|
+
});
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
return {
|
|
334
|
+
code: generateClientReferenceLoaders(metas, slots) + routeClientReferencesExport,
|
|
335
|
+
map: null
|
|
336
|
+
};
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
};
|
|
340
|
+
}
|
|
341
|
+
/**
|
|
342
|
+
* Exports a null preload plan from the client-references virtual module when
|
|
343
|
+
* the app registers @vitejs/plugin-rsc itself (`rsc: false`), where vinext
|
|
344
|
+
* doesn't add the loaders plugin above. The App Router SSR entry imports the
|
|
345
|
+
* plan, and null makes it preload every client reference.
|
|
346
|
+
*/
|
|
347
|
+
function createRouteClientReferencesFallbackPlugin() {
|
|
348
|
+
return {
|
|
349
|
+
name: "vinext:route-client-references-fallback",
|
|
350
|
+
enforce: "post",
|
|
351
|
+
transform: {
|
|
352
|
+
filter: { id: CLIENT_REFERENCES_ID_RE },
|
|
353
|
+
handler(code) {
|
|
354
|
+
if (this.environment.config.consumer !== "server") return null;
|
|
355
|
+
return {
|
|
356
|
+
code: `${code}\n${generateRouteClientReferencesExport(null, [])}`,
|
|
357
|
+
map: null
|
|
358
|
+
};
|
|
359
|
+
}
|
|
42
360
|
}
|
|
43
361
|
};
|
|
44
362
|
}
|
|
45
363
|
//#endregion
|
|
46
|
-
export { createRscClientReferenceLoadersPlugin };
|
|
364
|
+
export { createRouteClientReferencesFallbackPlugin, createRscClientReferenceLoadersPlugin };
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { getAstName } from "./ast-utils.js";
|
|
1
|
+
import { getAstName, parseProgram } from "./ast-utils.js";
|
|
2
2
|
import { magicStringTransformResult } from "./transform-result.js";
|
|
3
3
|
import { findAstBindingScope, walkAstScopes } from "./ast-scope.js";
|
|
4
|
-
import { parseAst } from "vite";
|
|
5
4
|
import MagicString from "magic-string";
|
|
6
5
|
//#region src/plugins/strip-server-exports.ts
|
|
7
6
|
const SERVER_EXPORTS = /* @__PURE__ */ new Set([
|
|
@@ -225,7 +224,7 @@ function validatePageExports(code) {
|
|
|
225
224
|
if (!hasExportAllCandidate(code)) return;
|
|
226
225
|
let ast;
|
|
227
226
|
try {
|
|
228
|
-
ast =
|
|
227
|
+
ast = parseProgram(code);
|
|
229
228
|
} catch {
|
|
230
229
|
return;
|
|
231
230
|
}
|
|
@@ -243,7 +242,7 @@ function stripServerExports(code) {
|
|
|
243
242
|
if (!hasServerExportCandidate(code) && !hasExportAllCandidate(code)) return null;
|
|
244
243
|
let ast;
|
|
245
244
|
try {
|
|
246
|
-
ast =
|
|
245
|
+
ast = parseProgram(code);
|
|
247
246
|
} catch {
|
|
248
247
|
return null;
|
|
249
248
|
}
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import path from "../deps/.pnpm/pathslash@0.1.0/deps/pathslash/dist/index.js";
|
|
2
|
-
import { SCRIPT_MODULE_ID_RE, walkAst } from "./ast-utils.js";
|
|
2
|
+
import { SCRIPT_MODULE_ID_RE, parseProgram, walkAst } from "./ast-utils.js";
|
|
3
3
|
import { NODE_MODULES_PATH_RE, stripViteModuleQuery } from "../utils/path.js";
|
|
4
4
|
import { createRequire } from "node:module";
|
|
5
5
|
import { pathToFileURL } from "node:url";
|
|
6
|
-
import { parseAst } from "vite";
|
|
7
6
|
//#region src/plugins/styled-jsx.ts
|
|
8
7
|
const STYLED_JSX_IMPORT_RE = /^styled-jsx(?:\/.*)?$/;
|
|
9
8
|
const STYLED_JSX_SOURCE_RE = /(?:<style\b|from\s+["']styled-jsx\/css["']|require\s*\(\s*["']styled-jsx\/css["']\s*\))/;
|
|
@@ -14,7 +13,7 @@ function hasStyledJsxTag(source, id) {
|
|
|
14
13
|
const lang = extension === ".ts" || extension === ".mts" || extension === ".cts" ? "ts" : "tsx";
|
|
15
14
|
let ast;
|
|
16
15
|
try {
|
|
17
|
-
ast =
|
|
16
|
+
ast = parseProgram(source, { lang });
|
|
18
17
|
} catch {
|
|
19
18
|
return false;
|
|
20
19
|
}
|
|
@@ -1,9 +1,33 @@
|
|
|
1
1
|
import { Plugin } from "vite";
|
|
2
2
|
//#region src/plugins/use-cache-callable.d.ts
|
|
3
|
+
type RscTransforms = typeof import("@vitejs/plugin-rsc/transforms");
|
|
3
4
|
type Options = {
|
|
4
5
|
projectRoot: string;
|
|
5
6
|
cacheRuntime: string;
|
|
6
7
|
allowMissingRsc?: boolean;
|
|
8
|
+
/**
|
|
9
|
+
* The Server Actions encryption key vinext loaded for an auto-registered
|
|
10
|
+
* @vitejs/plugin-rsc, so reference names derive from the same key.
|
|
11
|
+
*/
|
|
12
|
+
getEncryptionKey?: () => string | undefined;
|
|
7
13
|
};
|
|
8
|
-
|
|
9
|
-
|
|
14
|
+
type BrowserTransformOptions = {
|
|
15
|
+
environmentName: string;
|
|
16
|
+
reference: {
|
|
17
|
+
referenceKey: string;
|
|
18
|
+
};
|
|
19
|
+
secureExportName: (name: string) => string;
|
|
20
|
+
createReference: (referenceId: string, name: string) => string;
|
|
21
|
+
};
|
|
22
|
+
type BrowserTransformOutput = NonNullable<ReturnType<RscTransforms["transformDirectiveProxyExport"]>>;
|
|
23
|
+
export type UseCacheCallableApi = {
|
|
24
|
+
/**
|
|
25
|
+
* Compile a browser Web Worker module like the client environment does,
|
|
26
|
+
* with the same reference ids, without claiming references.
|
|
27
|
+
*/
|
|
28
|
+
transformWorkerModule(code: string, id: string, createReference: BrowserTransformOptions["createReference"]): Promise<BrowserTransformOutput["output"] | undefined>;
|
|
29
|
+
};
|
|
30
|
+
declare const PLUGIN_NAME = "vinext:server-function-directives";
|
|
31
|
+
export declare function createUseCacheCallablePlugin(options: Options): Promise<Plugin<UseCacheCallableApi>>;
|
|
32
|
+
//#endregion
|
|
33
|
+
export { PLUGIN_NAME as USE_CACHE_PLUGIN_NAME };
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import path from "../deps/.pnpm/pathslash@0.1.0/deps/pathslash/dist/index.js";
|
|
2
|
+
import { parseProgramAsync } from "./ast-utils.js";
|
|
2
3
|
import { magicStringTransformResult } from "./transform-result.js";
|
|
3
4
|
import { NODE_MODULES_PATH_RE } from "../utils/path.js";
|
|
5
|
+
import { getServerActionsKeyCacheFsDeny, loadOrGenerateServerActionsEncryptionKey } from "../build/server-actions-encryption-key.js";
|
|
4
6
|
import { createRequire } from "node:module";
|
|
5
7
|
import { pathToFileURL } from "node:url";
|
|
6
|
-
import {
|
|
7
|
-
import { createHmac, randomBytes } from "node:crypto";
|
|
8
|
+
import { createHmac } from "node:crypto";
|
|
8
9
|
//#region src/plugins/use-cache-callable.ts
|
|
9
10
|
const PLUGIN_NAME = "vinext:server-function-directives";
|
|
10
11
|
const SOURCE_MODULE_ID_RE = /\.(?:tsx?|jsx?|mjs)(?:\?.*)?$/;
|
|
@@ -79,19 +80,105 @@ function getCacheWrapperOptions(meta) {
|
|
|
79
80
|
...captureCount === 0 ? {} : { captureCount }
|
|
80
81
|
};
|
|
81
82
|
}
|
|
83
|
+
/**
|
|
84
|
+
* Compile a module for a browser graph: module-level cache functions become
|
|
85
|
+
* server references, and inline ones are rejected as in Next.js Client
|
|
86
|
+
* Components. Returns undefined when the module is unchanged.
|
|
87
|
+
*/
|
|
88
|
+
function transformBrowserModule(transforms, code, ast, id, moduleDirective, options) {
|
|
89
|
+
if (!moduleDirective) {
|
|
90
|
+
transforms.transformHoistInlineDirective(code, ast, {
|
|
91
|
+
directive: USE_CACHE_DIRECTIVE_CANDIDATE,
|
|
92
|
+
rejectNonAsyncFunction: true,
|
|
93
|
+
runtime: (_value, _name, meta) => {
|
|
94
|
+
matchUseCacheDirective(meta.directiveMatch[0]);
|
|
95
|
+
throw new Error(`It is not allowed to define inline "use cache" annotated functions in Client Components. Export them from a separate file with a module-level "use cache" or "use server" directive, or pass them down through props from a Server Component. (${options.environmentName}: ${id})`);
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
const useServerExportNames = getFunctionDirectiveExportNames(transforms, ast, "use server");
|
|
101
|
+
const referenceName = (name) => useServerExportNames.has(name) ? name : options.secureExportName(name);
|
|
102
|
+
const result = transforms.transformDirectiveProxyExport(ast, {
|
|
103
|
+
code,
|
|
104
|
+
directive: moduleDirective,
|
|
105
|
+
filter: (name, meta) => {
|
|
106
|
+
if (!shouldTransformModuleExport(name, id, meta)) return false;
|
|
107
|
+
validateModuleExport(transforms, meta);
|
|
108
|
+
return true;
|
|
109
|
+
},
|
|
110
|
+
runtime: (name) => options.createReference(`${options.reference.referenceKey}#${referenceName(name)}`, name)
|
|
111
|
+
});
|
|
112
|
+
if (!result?.output.hasChanged()) return;
|
|
113
|
+
return {
|
|
114
|
+
output: result.output,
|
|
115
|
+
referenceNames: result.exportNames.map(referenceName)
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Ported from Next.js: crates/next-custom-transforms/src/transforms/server_actions.rs
|
|
120
|
+
* salts server-reference IDs with the encryption key (`serverReferenceHashSalt`
|
|
121
|
+
* in packages/next/src/build/webpack-config.ts), so rebuilds of identical
|
|
122
|
+
* source emit identical client chunks. See
|
|
123
|
+
* loadOrGenerateServerActionsEncryptionKey for where the key comes from. The
|
|
124
|
+
* secret is derived under a label rather than used directly so the reference
|
|
125
|
+
* names reveal nothing about the key.
|
|
126
|
+
*/
|
|
127
|
+
function createReferenceSecret(encryptionKey) {
|
|
128
|
+
return createHmac("sha256", encryptionKey).update("vinext use cache reference").digest();
|
|
129
|
+
}
|
|
82
130
|
async function createUseCacheCallablePlugin(options) {
|
|
83
131
|
const rscModulePath = resolvePluginRscModule(options.projectRoot, "@vitejs/plugin-rsc");
|
|
84
132
|
const transformsPath = resolvePluginRscModule(options.projectRoot, "@vitejs/plugin-rsc/transforms");
|
|
85
133
|
const rscModule = await import(pathToFileURL(rscModulePath).href);
|
|
86
134
|
const transforms = await import(pathToFileURL(transformsPath).href);
|
|
87
|
-
|
|
135
|
+
let referenceSecret;
|
|
88
136
|
let manager;
|
|
137
|
+
async function analyzeModule(manager, secret, code, id) {
|
|
138
|
+
const ast = await parseProgramAsync(code);
|
|
139
|
+
const moduleDirective = findModuleUseCacheDirective(ast);
|
|
140
|
+
const useServerBoundary = transforms.hasDirective(ast.body, "use server");
|
|
141
|
+
if (moduleDirective && useServerBoundary) throw new Error(`A module cannot contain both ${JSON.stringify(moduleDirective)} and "use server" directives.`);
|
|
142
|
+
const reference = manager.serverReferences.resolve(id, "rsc");
|
|
143
|
+
const relativeImportId = manager.toRelativeId(reference.importId);
|
|
144
|
+
const secureExportName = (name) => `$$vinext_cache_${createHmac("sha256", secret).update(relativeImportId).update("\0").update(name).digest("hex")}`;
|
|
145
|
+
return {
|
|
146
|
+
ast,
|
|
147
|
+
moduleDirective,
|
|
148
|
+
useServerBoundary,
|
|
149
|
+
reference,
|
|
150
|
+
secureExportName
|
|
151
|
+
};
|
|
152
|
+
}
|
|
89
153
|
return {
|
|
90
154
|
name: PLUGIN_NAME,
|
|
155
|
+
api: { async transformWorkerModule(code, id, createReference) {
|
|
156
|
+
if (!code.includes("use cache")) return;
|
|
157
|
+
const secret = referenceSecret;
|
|
158
|
+
if (!manager || !secret) {
|
|
159
|
+
if (findModuleUseCacheDirective(await parseProgramAsync(code))) throw new Error("vinext: cannot compile a \"use cache\" module in a Web Worker without @vitejs/plugin-rsc.");
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
const { ast, moduleDirective, useServerBoundary, reference, secureExportName } = await analyzeModule(manager, secret, code, id);
|
|
163
|
+
if (useServerBoundary) return;
|
|
164
|
+
return transformBrowserModule(transforms, code, ast, id, moduleDirective, {
|
|
165
|
+
environmentName: "worker",
|
|
166
|
+
reference,
|
|
167
|
+
secureExportName,
|
|
168
|
+
createReference
|
|
169
|
+
})?.output;
|
|
170
|
+
} },
|
|
171
|
+
config(config) {
|
|
172
|
+
return { server: { fs: { deny: getServerActionsKeyCacheFsDeny(config.server?.fs?.deny) } } };
|
|
173
|
+
},
|
|
91
174
|
configResolved(config) {
|
|
92
175
|
const pluginApi = rscModule.getPluginApi(config);
|
|
93
176
|
const hasRscPlugin = config.plugins.some((plugin) => plugin.name === "rsc");
|
|
94
177
|
if (!pluginApi && options.allowMissingRsc && !hasRscPlugin) return;
|
|
178
|
+
referenceSecret ??= createReferenceSecret(options.getEncryptionKey?.() ?? loadOrGenerateServerActionsEncryptionKey({
|
|
179
|
+
root: config.root,
|
|
180
|
+
isBuild: config.command === "build"
|
|
181
|
+
}));
|
|
95
182
|
if (!pluginApi?.manager.serverReferences) throw new Error("vinext: callable use cache requires @vitejs/plugin-rsc 0.5.34 or newer.");
|
|
96
183
|
if (options.allowMissingRsc) {
|
|
97
184
|
const useCacheIndex = config.plugins.findIndex((plugin) => plugin.name === PLUGIN_NAME);
|
|
@@ -106,53 +193,31 @@ async function createUseCacheCallablePlugin(options) {
|
|
|
106
193
|
exclude: [NODE_MODULES_PATH_RE, RESOLVED_VIRTUAL_MODULE_ID_RE]
|
|
107
194
|
} },
|
|
108
195
|
async handler(code, id) {
|
|
109
|
-
|
|
196
|
+
const secret = referenceSecret;
|
|
197
|
+
if (!manager || !secret) return;
|
|
110
198
|
if (!code.includes("use cache")) {
|
|
111
199
|
manager.serverReferences.deleteClaim(PLUGIN_NAME, id);
|
|
112
200
|
return;
|
|
113
201
|
}
|
|
114
|
-
const ast = await
|
|
115
|
-
const moduleDirective = findModuleUseCacheDirective(ast);
|
|
116
|
-
const useServerBoundary = transforms.hasDirective(ast.body, "use server");
|
|
117
|
-
if (moduleDirective && useServerBoundary) throw new Error(`A module cannot contain both ${JSON.stringify(moduleDirective)} and "use server" directives.`);
|
|
118
|
-
const reference = manager.serverReferences.resolve(id, "rsc");
|
|
119
|
-
const relativeImportId = manager.toRelativeId(reference.importId);
|
|
120
|
-
const secureExportName = (name) => `$$vinext_cache_${createHmac("sha256", referenceSecret).update(relativeImportId).update("\0").update(name).digest("hex")}`;
|
|
202
|
+
const { ast, moduleDirective, useServerBoundary, reference, secureExportName } = await analyzeModule(manager, secret, code, id);
|
|
121
203
|
if (!(this.environment.name === "rsc")) {
|
|
122
204
|
if (useServerBoundary) {
|
|
123
205
|
manager.serverReferences.deleteClaim(PLUGIN_NAME, id);
|
|
124
206
|
return;
|
|
125
207
|
}
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
matchUseCacheDirective(meta.directiveMatch[0]);
|
|
132
|
-
throw new Error(`It is not allowed to define inline "use cache" annotated functions in Client Components. Export them from a separate file with a module-level "use cache" or "use server" directive, or pass them down through props from a Server Component. (${this.environment.name}: ${id})`);
|
|
133
|
-
}
|
|
134
|
-
});
|
|
135
|
-
manager.serverReferences.deleteClaim(PLUGIN_NAME, id);
|
|
136
|
-
return;
|
|
137
|
-
}
|
|
138
|
-
const useServerExportNames = getFunctionDirectiveExportNames(transforms, ast, "use server");
|
|
139
|
-
const result = transforms.transformDirectiveProxyExport(ast, {
|
|
140
|
-
code,
|
|
141
|
-
directive: moduleDirective,
|
|
142
|
-
filter: (name, meta) => {
|
|
143
|
-
if (!shouldTransformModuleExport(name, id, meta)) return false;
|
|
144
|
-
validateModuleExport(transforms, meta);
|
|
145
|
-
return true;
|
|
146
|
-
},
|
|
147
|
-
runtime: (name) => `$$ReactClient.createServerReference(${JSON.stringify(`${reference.referenceKey}#${useServerExportNames.has(name) ? name : secureExportName(name)}`)},$$ReactClient.callServer,undefined,${this.environment.mode === "dev" ? "$$ReactClient.findSourceMapURL" : "undefined"},${JSON.stringify(name)})`
|
|
208
|
+
const result = transformBrowserModule(transforms, code, ast, id, moduleDirective, {
|
|
209
|
+
environmentName: this.environment.name,
|
|
210
|
+
reference,
|
|
211
|
+
secureExportName,
|
|
212
|
+
createReference: (referenceId, name) => `$$ReactClient.createServerReference(${JSON.stringify(referenceId)},$$ReactClient.callServer,undefined,${this.environment.mode === "dev" ? "$$ReactClient.findSourceMapURL" : "undefined"},${JSON.stringify(name)})`
|
|
148
213
|
});
|
|
149
|
-
if (!result
|
|
214
|
+
if (!result) {
|
|
150
215
|
manager.serverReferences.deleteClaim(PLUGIN_NAME, id);
|
|
151
216
|
return;
|
|
152
217
|
}
|
|
153
218
|
manager.serverReferences.replaceClaim(PLUGIN_NAME, id, {
|
|
154
219
|
...reference,
|
|
155
|
-
exportNames: result.
|
|
220
|
+
exportNames: result.referenceNames
|
|
156
221
|
});
|
|
157
222
|
const runtimeEnvironment = this.environment.name === "client" ? "browser" : "ssr";
|
|
158
223
|
result.output.prepend(`import * as $$ReactClient from "@vitejs/plugin-rsc/react/${runtimeEnvironment}";\n`);
|
|
@@ -223,4 +288,4 @@ async function createUseCacheCallablePlugin(options) {
|
|
|
223
288
|
};
|
|
224
289
|
}
|
|
225
290
|
//#endregion
|
|
226
|
-
export { createUseCacheCallablePlugin };
|
|
291
|
+
export { PLUGIN_NAME as USE_CACHE_PLUGIN_NAME, createUseCacheCallablePlugin };
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Plugin } from "vite";
|
|
2
2
|
//#region src/plugins/worker-image-imports.d.ts
|
|
3
|
+
export declare const WORKER_IMAGE_METADATA_PREFIX = "\0vinext-worker-image-meta:";
|
|
3
4
|
/**
|
|
4
5
|
* Preserve Next.js's StaticImageData shape for dynamic image imports inside
|
|
5
6
|
* Vite worker graphs. Worker builds use their own plugin container, so the
|