vinext 1.0.0-beta.11 → 1.0.0-beta.13
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 +39 -12
- package/dist/build/action-owner-manifest.js +23 -5
- package/dist/build/lifecycle.d.ts +42 -0
- package/dist/build/lifecycle.js +246 -0
- package/dist/build/nitro-route-rules.js +1 -1
- package/dist/build/pages-client-assets-module.d.ts +0 -3
- package/dist/build/pages-client-assets-module.js +1 -13
- package/dist/build/precompress.js +1 -1
- package/dist/build/prerender-paths.d.ts +1 -1
- package/dist/build/prerender-paths.js +6 -6
- package/dist/build/prerender-server-pool.js +1 -1
- package/dist/build/prerender.d.ts +1 -1
- package/dist/build/prerender.js +5 -5
- package/dist/build/preview-credentials.d.ts +1 -1
- package/dist/build/preview-credentials.js +2 -2
- package/dist/build/report.js +1 -1
- package/dist/build/run-prerender.d.ts +2 -2
- package/dist/build/run-prerender.js +5 -5
- package/dist/build/standalone.js +2 -2
- package/dist/cli-args.d.ts +5 -13
- package/dist/cli-args.js +2 -45
- package/dist/cli-dev-config.d.ts +6 -2
- package/dist/cli-dev-config.js +160 -3
- package/dist/cli.js +104 -439
- package/dist/config/config-matchers.js +1 -1
- package/dist/config/next-config.d.ts +2 -2
- package/dist/config/next-config.js +5 -5
- package/dist/config/prerender.d.ts +3 -0
- package/dist/config/prerender.js +8 -2
- package/dist/entries/app-browser-entry.js +1 -1
- package/dist/entries/app-rsc-entry.d.ts +2 -0
- package/dist/entries/app-rsc-entry.js +25 -5
- package/dist/entries/pages-client-entry.d.ts +1 -0
- package/dist/entries/pages-client-entry.js +17 -2
- package/dist/index.d.ts +6 -8
- package/dist/index.js +282 -105
- package/dist/init-cloudflare.d.ts +3 -2
- package/dist/init-cloudflare.js +117 -5
- package/dist/init-platform.d.ts +2 -0
- package/dist/init-platform.js +9 -3
- package/dist/init.d.ts +7 -5
- package/dist/init.js +41 -22
- package/dist/plugins/dynamic-preload-metadata.js +1 -1
- package/dist/plugins/extensionless-dynamic-import.js +2 -2
- package/dist/plugins/fonts.js +1 -1
- package/dist/plugins/ignore-dynamic-requests.js +1 -1
- package/dist/plugins/import-meta-url.js +1 -1
- package/dist/plugins/instrumentation-client.js +1 -1
- package/dist/plugins/og-assets.js +32 -13
- package/dist/plugins/og-harfbuzz.d.ts +24 -0
- package/dist/plugins/og-harfbuzz.js +260 -0
- package/dist/plugins/optimize-imports.js +1 -1
- package/dist/plugins/require-condition-resolution.js +2 -2
- package/dist/plugins/require-context.js +2 -2
- package/dist/plugins/typeof-window.js +1 -1
- package/dist/plugins/use-cache-callable.d.ts +0 -2
- package/dist/plugins/use-cache-callable.js +40 -22
- package/dist/plugins/worker-image-imports.js +1 -1
- package/dist/routing/app-route-graph.js +1 -1
- package/dist/routing/app-router.js +1 -1
- package/dist/routing/pages-router.js +1 -1
- package/dist/server/app-action-forwarding.js +1 -1
- package/dist/server/app-browser-entry.js +1 -0
- package/dist/server/app-browser-error.js +1 -1
- package/dist/server/app-elements-wire.js +2 -2
- package/dist/server/app-middleware.js +1 -1
- package/dist/server/app-optimistic-routing.js +1 -1
- package/dist/server/app-page-cache-finalizer.d.ts +1 -0
- package/dist/server/app-page-cache-finalizer.js +14 -2
- package/dist/server/app-page-dispatch.js +1 -1
- package/dist/server/app-page-element-builder.js +3 -2
- package/dist/server/app-page-probe.js +3 -3
- package/dist/server/app-page-render.js +1 -0
- package/dist/server/app-page-request.d.ts +2 -0
- package/dist/server/app-page-request.js +16 -12
- package/dist/server/app-request-stage-dispatch.js +1 -1
- package/dist/server/app-request-stage-independent-entry.js +2 -2
- package/dist/server/app-route-handler-dispatch.d.ts +1 -0
- package/dist/server/app-route-handler-dispatch.js +3 -2
- package/dist/server/app-route-handler-execution.d.ts +1 -0
- package/dist/server/app-route-handler-execution.js +2 -2
- package/dist/server/app-route-handler-runtime.js +1 -1
- package/dist/server/app-router-entry.js +2 -2
- package/dist/server/app-rsc-handler.d.ts +9 -2
- package/dist/server/app-rsc-handler.js +30 -10
- package/dist/server/app-rsc-response-stage.js +6 -3
- package/dist/server/app-rsc-route-matching.js +1 -1
- package/dist/server/app-server-action-execution.js +35 -6
- package/dist/server/app-ssr-entry.js +7 -2
- package/dist/server/app-ssr-stream.js +25 -6
- package/dist/server/app-worker-stages.d.ts +4 -1
- package/dist/server/app-worker-stages.js +4 -4
- package/dist/server/artifact-compatibility.js +1 -1
- package/dist/server/client-reuse-manifest.js +1 -1
- package/dist/server/dev-lockfile.d.ts +1 -1
- package/dist/server/dev-lockfile.js +4 -1
- package/dist/server/dev-server.d.ts +1 -1
- package/dist/server/dev-server.js +28 -6
- package/dist/server/dev-stack-sourcemap.js +1 -1
- package/dist/server/html.d.ts +0 -20
- package/dist/server/html.js +16 -1
- package/dist/server/instrumentation.d.ts +4 -9
- package/dist/server/instrumentation.js +10 -15
- package/dist/server/isr-cache.js +3 -3
- package/dist/server/metadata-route-response.d.ts +1 -0
- package/dist/server/metadata-route-response.js +65 -0
- package/dist/server/middleware-runtime.js +3 -3
- package/dist/server/pages-asset-tags.d.ts +1 -0
- package/dist/server/pages-asset-tags.js +37 -2
- package/dist/server/pages-client-assets.d.ts +7 -0
- package/dist/server/pages-data-route.js +1 -1
- package/dist/server/pages-dev-hydration.d.ts +6 -0
- package/dist/server/pages-dev-hydration.js +19 -7
- package/dist/server/pages-document-initial-props.d.ts +1 -0
- package/dist/server/pages-document-initial-props.js +1 -1
- package/dist/server/pages-page-data.js +2 -2
- package/dist/server/pages-page-handler.js +5 -2
- package/dist/server/pages-page-response.d.ts +1 -0
- package/dist/server/pages-page-response.js +3 -2
- package/dist/server/pages-request-pipeline.js +3 -3
- package/dist/server/pages-request-stage-entry.js +3 -3
- package/dist/server/pages-revalidate.js +1 -1
- package/dist/server/prerender-route-params.js +1 -1
- package/dist/server/prod-server.js +19 -13
- package/dist/server/request-pipeline.js +2 -2
- package/dist/server/rsc-stream-hints.d.ts +12 -0
- package/dist/server/rsc-stream-hints.js +70 -35
- package/dist/server/seed-cache.js +3 -4
- package/dist/server/socket-error-backstop.js +1 -1
- package/dist/shims/cache-callable-runtime.d.ts +38 -0
- package/dist/shims/cache-callable-runtime.js +162 -11
- package/dist/shims/cache-runtime.d.ts +6 -8
- package/dist/shims/cache-runtime.js +89 -24
- package/dist/shims/constants.js +1 -1
- package/dist/shims/dynamic-preload-chunks.js +6 -2
- package/dist/shims/font-local.js +1 -1
- package/dist/shims/form.js +1 -1
- package/dist/shims/head.js +1 -1
- package/dist/shims/headers.js +2 -2
- package/dist/shims/image-config.js +2 -0
- package/dist/shims/internal/app-page-props-cache-key.d.ts +29 -0
- package/dist/shims/internal/app-page-props-cache-key.js +53 -1
- package/dist/shims/internal/format-url-object.d.ts +7 -0
- package/dist/shims/internal/format-url-object.js +53 -0
- package/dist/shims/internal/normalize-router-href.d.ts +15 -0
- package/dist/shims/internal/normalize-router-href.js +41 -0
- package/dist/shims/internal/pages-data-target.d.ts +4 -1
- package/dist/shims/internal/pages-data-target.js +28 -35
- package/dist/shims/internal/route-pattern-for-warning.d.ts +2 -2
- package/dist/shims/internal/route-pattern-for-warning.js +3 -3
- package/dist/shims/link.js +31 -92
- package/dist/shims/metadata.js +5 -4
- package/dist/shims/navigation.js +2 -2
- package/dist/shims/router-state.js +1 -1
- package/dist/shims/router.d.ts +8 -7
- package/dist/shims/router.js +312 -148
- package/dist/shims/script-nonce-context.d.ts +4 -1
- package/dist/shims/script-nonce-context.js +15 -6
- package/dist/shims/server.js +3 -3
- package/dist/utils/built-asset-url.js +1 -1
- package/dist/utils/client-runtime-metadata.d.ts +6 -0
- package/dist/utils/client-runtime-metadata.js +16 -0
- package/dist/utils/lazy-chunks.js +1 -1
- package/dist/utils/project.d.ts +1 -11
- package/dist/utils/project.js +20 -29
- package/dist/utils/react-version.d.ts +3 -1
- package/dist/utils/react-version.js +19 -1
- package/dist/utils/vite-cli-invocation.d.ts +21 -0
- package/dist/utils/vite-cli-invocation.js +144 -0
- package/package.json +10 -2
|
@@ -1,11 +1,11 @@
|
|
|
1
|
+
import { VINEXT_MW_CTX_HEADER } from "../utils/protocol-headers.js";
|
|
2
|
+
import { buildRequestHeadersFromMiddlewareResponse } from "../utils/middleware-request-headers.js";
|
|
3
|
+
import { parseEdgeRequestCookieHeader } from "../utils/parse-cookie.js";
|
|
4
|
+
import { isExternalUrl } from "../utils/external-url.js";
|
|
1
5
|
import { splitPathSegments } from "../routing/utils.js";
|
|
2
6
|
import { addBasePathToPathname, hasBasePath, stripBasePath } from "../utils/base-path.js";
|
|
3
|
-
import { parseEdgeRequestCookieHeader } from "../utils/parse-cookie.js";
|
|
4
|
-
import { VINEXT_MW_CTX_HEADER } from "../utils/protocol-headers.js";
|
|
5
7
|
import { NEXT_ROUTER_STATE_TREE_HEADER, VINEXT_RSC_VARY_HEADER } from "./app-rsc-vary.js";
|
|
6
8
|
import { ACTION_FORWARDED_HEADER, ACTION_REDIRECT_HEADER, ACTION_REDIRECT_STATUS_HEADER, ACTION_REDIRECT_TYPE_HEADER, ACTION_REVALIDATED_HEADER } from "./headers.js";
|
|
7
|
-
import { buildRequestHeadersFromMiddlewareResponse } from "../utils/middleware-request-headers.js";
|
|
8
|
-
import { isExternalUrl } from "../utils/external-url.js";
|
|
9
9
|
import { internalServerErrorResponse, payloadTooLargeResponse } from "./http-error-responses.js";
|
|
10
10
|
import { attachRequestCfMetadata, validateCsrfOrigin, validateServerActionPayload } from "./request-pipeline.js";
|
|
11
11
|
import { APP_RSC_RENDER_MODE_NAVIGATION } from "./app-rsc-render-mode.js";
|
|
@@ -324,6 +324,31 @@ function dedupePendingCookies(cookies) {
|
|
|
324
324
|
function isAppServerActionFunction(action) {
|
|
325
325
|
return typeof action === "function";
|
|
326
326
|
}
|
|
327
|
+
function normalizeDevServerReferenceId(id) {
|
|
328
|
+
const exportSeparator = id.indexOf("#");
|
|
329
|
+
if (exportSeparator === -1) return id;
|
|
330
|
+
const moduleId = id.slice(0, exportSeparator);
|
|
331
|
+
const cacheTag = moduleId.indexOf("$$cache=");
|
|
332
|
+
return (cacheTag === -1 ? moduleId : moduleId.slice(0, cacheTag)) + id.slice(exportSeparator);
|
|
333
|
+
}
|
|
334
|
+
function requiresRegisteredServerReferenceMatch(actionId) {
|
|
335
|
+
const exportSeparator = actionId.indexOf("#");
|
|
336
|
+
if (exportSeparator === -1) return true;
|
|
337
|
+
return !/^[0-9a-f]{12}$/.test(actionId.slice(0, exportSeparator));
|
|
338
|
+
}
|
|
339
|
+
function matchesRegisteredServerReference(action, actionId) {
|
|
340
|
+
const registeredId = Reflect.get(action, "$$id");
|
|
341
|
+
if (typeof registeredId !== "string") return false;
|
|
342
|
+
const normalizedRegisteredId = normalizeDevServerReferenceId(registeredId);
|
|
343
|
+
const normalizedActionId = normalizeDevServerReferenceId(actionId);
|
|
344
|
+
if (normalizedRegisteredId === normalizedActionId) return true;
|
|
345
|
+
const registeredSeparator = normalizedRegisteredId.indexOf("#");
|
|
346
|
+
const actionSeparator = normalizedActionId.indexOf("#");
|
|
347
|
+
if (registeredSeparator === -1 || actionSeparator === -1) return false;
|
|
348
|
+
if (normalizedRegisteredId.slice(0, registeredSeparator) !== normalizedActionId.slice(0, actionSeparator)) return false;
|
|
349
|
+
const registeredExport = normalizedRegisteredId.slice(registeredSeparator + 1);
|
|
350
|
+
return !/^\$\$vinext_cache_[0-9a-f]{64}$/.test(registeredExport);
|
|
351
|
+
}
|
|
327
352
|
function getServerActionFailureMessage(error) {
|
|
328
353
|
return error instanceof Error && error.message ? error.message : String(error);
|
|
329
354
|
}
|
|
@@ -542,6 +567,10 @@ async function handleProgressiveServerActionRequest(options) {
|
|
|
542
567
|
});
|
|
543
568
|
return null;
|
|
544
569
|
}
|
|
570
|
+
if (directActionId && requiresRegisteredServerReferenceMatch(directActionId) && !matchesRegisteredServerReference(action, directActionId)) return createActionNotFoundResponse(directActionId, {
|
|
571
|
+
clearRequestContext: options.clearRequestContext,
|
|
572
|
+
getAndClearPendingCookies: options.getAndClearPendingCookies
|
|
573
|
+
});
|
|
545
574
|
const decodedActionId = Reflect.get(action, "$$id");
|
|
546
575
|
if (typeof decodedActionId === "string" && decodedActionId !== directActionId && options.forwardAction) {
|
|
547
576
|
const forwardResponse = await options.forwardAction(decodedActionId);
|
|
@@ -717,7 +746,7 @@ async function handleServerActionRscRequest(options) {
|
|
|
717
746
|
});
|
|
718
747
|
throw error;
|
|
719
748
|
}
|
|
720
|
-
if (!isAppServerActionFunction(loadedAction)) return createActionNotFoundResponse(options.actionId, {
|
|
749
|
+
if (!isAppServerActionFunction(loadedAction) || requiresRegisteredServerReferenceMatch(options.actionId) && !matchesRegisteredServerReference(loadedAction, options.actionId)) return createActionNotFoundResponse(options.actionId, {
|
|
721
750
|
clearRequestContext: options.clearRequestContext,
|
|
722
751
|
getAndClearPendingCookies: options.getAndClearPendingCookies
|
|
723
752
|
});
|
|
@@ -747,7 +776,7 @@ async function handleServerActionRscRequest(options) {
|
|
|
747
776
|
});
|
|
748
777
|
throw error;
|
|
749
778
|
}
|
|
750
|
-
if (!isAppServerActionFunction(loadedAction)) return createActionNotFoundResponse(options.actionId, {
|
|
779
|
+
if (!isAppServerActionFunction(loadedAction) || requiresRegisteredServerReferenceMatch(options.actionId) && !matchesRegisteredServerReference(loadedAction, options.actionId)) return createActionNotFoundResponse(options.actionId, {
|
|
751
780
|
clearRequestContext: options.clearRequestContext,
|
|
752
781
|
getAndClearPendingCookies: options.getAndClearPendingCookies
|
|
753
782
|
});
|
|
@@ -153,7 +153,7 @@ function extractBootstrapModuleUrl(bootstrapScriptContent) {
|
|
|
153
153
|
}
|
|
154
154
|
function buildModulePreloadHtml(bootstrapModuleUrl, nonce) {
|
|
155
155
|
if (!bootstrapModuleUrl) return "";
|
|
156
|
-
return `<link rel="modulepreload"${createNonceAttribute(nonce)} href="${escapeHtmlAttr(bootstrapModuleUrl)}" />\n`;
|
|
156
|
+
return `<link rel="modulepreload"${createNonceAttribute(nonce)} href="${escapeHtmlAttr(bootstrapModuleUrl)}" crossorigin="${pagesClientAssets.crossOrigin ?? ""}" />\n`;
|
|
157
157
|
}
|
|
158
158
|
function buildHeadInjectionHtml(navContext, bootstrapModuleUrl, formState, insertedHTML, fontHTML, dynamicStaleTimeSeconds, searchParamsFromBrowser, scriptNonce) {
|
|
159
159
|
const navPayload = {
|
|
@@ -168,6 +168,7 @@ function requireNavigationContext(navContext) {
|
|
|
168
168
|
}
|
|
169
169
|
async function handleSsr(rscStream, navContext, fontData, options) {
|
|
170
170
|
return runWithNavigationContext(async () => {
|
|
171
|
+
const assetCrossOrigin = pagesClientAssets.crossOrigin ?? "";
|
|
171
172
|
const ssrNavigationContext = {
|
|
172
173
|
...requireNavigationContext(navContext),
|
|
173
174
|
isStaticGeneration: options?.isStaticGeneration,
|
|
@@ -206,6 +207,7 @@ async function handleSsr(rscStream, navContext, fontData, options) {
|
|
|
206
207
|
function VinextFlightRoot() {
|
|
207
208
|
for (const moduleUrl of pagesClientAssets.appBootstrapPreinitModules ?? []) preinitModule(moduleUrl, {
|
|
208
209
|
as: "script",
|
|
210
|
+
crossOrigin: assetCrossOrigin,
|
|
209
211
|
nonce: options?.scriptNonce
|
|
210
212
|
});
|
|
211
213
|
if (!flightRoot) flightRoot = createFromReadableStream(ssrStream);
|
|
@@ -236,7 +238,10 @@ async function handleSsr(rscStream, navContext, fontData, options) {
|
|
|
236
238
|
const maxHeadersLength = options?.reactMaxHeadersLength ?? DEFAULT_REACT_MAX_HEADERS_LENGTH;
|
|
237
239
|
const captureHeaders = maxHeadersLength > 0;
|
|
238
240
|
const renderOptions = {
|
|
239
|
-
bootstrapModules: bootstrapModuleUrl ? [
|
|
241
|
+
bootstrapModules: bootstrapModuleUrl ? [{
|
|
242
|
+
src: bootstrapModuleUrl,
|
|
243
|
+
crossOrigin: assetCrossOrigin
|
|
244
|
+
}] : void 0,
|
|
240
245
|
formState: options?.formState ?? null,
|
|
241
246
|
nonce: options?.scriptNonce,
|
|
242
247
|
onHeaders: captureHeaders ? (headers) => {
|
|
@@ -2,6 +2,7 @@ import { createInlineScriptTag, escapeHtmlAttr, htmlTokenListContains, safeJsonS
|
|
|
2
2
|
import { bytesToBase64, concatUint8Arrays } from "./app-rsc-embedded-chunks.js";
|
|
3
3
|
import { NAVIGATION_RUNTIME_SYMBOL_DESCRIPTION } from "../client/navigation-runtime.js";
|
|
4
4
|
//#region src/server/app-ssr-stream.ts
|
|
5
|
+
const RSC_EMBED_TEXT_BATCH_MAX_LENGTH = 65536;
|
|
5
6
|
function waitAtLeastOneReactRenderTask() {
|
|
6
7
|
return new Promise((resolve) => setTimeout(resolve, 0));
|
|
7
8
|
}
|
|
@@ -43,6 +44,10 @@ function createRscEmbedTransform(embedStream, optionsOrNonce = {}) {
|
|
|
43
44
|
const rawChunks = [];
|
|
44
45
|
let reading = false;
|
|
45
46
|
let mirroredNextFlightBootstrap = false;
|
|
47
|
+
const textDecoder = new TextDecoder("utf-8", {
|
|
48
|
+
fatal: true,
|
|
49
|
+
ignoreBOM: true
|
|
50
|
+
});
|
|
46
51
|
async function pumpReader() {
|
|
47
52
|
if (reading) return;
|
|
48
53
|
reading = true;
|
|
@@ -52,11 +57,7 @@ function createRscEmbedTransform(embedStream, optionsOrNonce = {}) {
|
|
|
52
57
|
if (result.done) break;
|
|
53
58
|
rawChunks.push(result.value);
|
|
54
59
|
try {
|
|
55
|
-
|
|
56
|
-
fatal: true,
|
|
57
|
-
ignoreBOM: true
|
|
58
|
-
}).decode(result.value);
|
|
59
|
-
pendingChunks.push(text);
|
|
60
|
+
pendingChunks.push(textDecoder.decode(result.value));
|
|
60
61
|
} catch {
|
|
61
62
|
pendingChunks.push([3, bytesToBase64(result.value)]);
|
|
62
63
|
}
|
|
@@ -74,8 +75,26 @@ function createRscEmbedTransform(embedStream, optionsOrNonce = {}) {
|
|
|
74
75
|
if (pendingChunks.length === 0) return "";
|
|
75
76
|
const chunks = pendingChunks;
|
|
76
77
|
pendingChunks = [];
|
|
78
|
+
const embeddedChunks = [];
|
|
79
|
+
let textChunks = [];
|
|
80
|
+
let textLength = 0;
|
|
81
|
+
const flushTextChunks = () => {
|
|
82
|
+
if (textChunks.length === 0) return;
|
|
83
|
+
embeddedChunks.push(textChunks.join(""));
|
|
84
|
+
textChunks = [];
|
|
85
|
+
textLength = 0;
|
|
86
|
+
};
|
|
87
|
+
for (const chunk of chunks) if (typeof chunk === "string") {
|
|
88
|
+
if (textLength > 0 && textLength + chunk.length > RSC_EMBED_TEXT_BATCH_MAX_LENGTH) flushTextChunks();
|
|
89
|
+
textChunks.push(chunk);
|
|
90
|
+
textLength += chunk.length;
|
|
91
|
+
} else {
|
|
92
|
+
flushTextChunks();
|
|
93
|
+
embeddedChunks.push(chunk);
|
|
94
|
+
}
|
|
95
|
+
flushTextChunks();
|
|
77
96
|
let scripts = "";
|
|
78
|
-
for (const chunk of
|
|
97
|
+
for (const chunk of embeddedChunks) {
|
|
79
98
|
scripts += createInlineScriptTag(createNavigationRuntimeRscChunkScript(chunk), options.scriptNonce);
|
|
80
99
|
if (options.mirrorNextFlight) {
|
|
81
100
|
if (!mirroredNextFlightBootstrap) {
|
|
@@ -2,7 +2,7 @@ import { VinextResponseStageCacheability, VinextResponseStageDispatchOptions, Vi
|
|
|
2
2
|
import { AppRscRenderMode } from "./app-rsc-render-mode.js";
|
|
3
3
|
import { TrustedPrerenderState } from "./prerender-route-params.js";
|
|
4
4
|
//#region src/server/app-worker-stages.d.ts
|
|
5
|
-
export declare const APP_WORKER_RESPONSE_STAGE_PROTOCOL_VERSION =
|
|
5
|
+
export declare const APP_WORKER_RESPONSE_STAGE_PROTOCOL_VERSION = 10;
|
|
6
6
|
export declare const APP_METADATA_RESPONSE_STAGE_NO_MATCH_HEADER = "x-vinext-app-metadata-stage-no-match";
|
|
7
7
|
type AppPageParams = Record<string, string | string[]>;
|
|
8
8
|
type AppWorkerResponseStageEnvelope = {
|
|
@@ -24,6 +24,8 @@ type AppFullRequestWorkerResponseStageProps = AppWorkerResponseStageEnvelope & {
|
|
|
24
24
|
export type AppMatchedWorkerResponseStageProps = AppWorkerResponseStageEnvelope & {
|
|
25
25
|
kind: "app-page" | "app-route-handler";
|
|
26
26
|
bypassInterceptionContextCache: boolean;
|
|
27
|
+
/** Origin-cache pathname; differs from cleanPathname after an internal rewrite. */
|
|
28
|
+
cachePathname: string;
|
|
27
29
|
canUseCanonicalLoadingShell: boolean;
|
|
28
30
|
canonicalPathname: string;
|
|
29
31
|
cleanPathname: string;
|
|
@@ -56,6 +58,7 @@ type AppMetadataWorkerResponseStageProps = AppWorkerResponseStageEnvelope & {
|
|
|
56
58
|
mountedSlotsHeader: string | null;
|
|
57
59
|
renderMode: AppRscRenderMode;
|
|
58
60
|
resolvedUrl: string;
|
|
61
|
+
routePathname: string;
|
|
59
62
|
};
|
|
60
63
|
type HybridPagesWorkerResponseStageProps = AppWorkerResponseStageEnvelope & {
|
|
61
64
|
kind: "hybrid-pages";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { isTrustedPrerenderState } from "./prerender-route-params.js";
|
|
2
2
|
//#region src/server/app-worker-stages.ts
|
|
3
|
-
const APP_WORKER_RESPONSE_STAGE_PROTOCOL_VERSION =
|
|
3
|
+
const APP_WORKER_RESPONSE_STAGE_PROTOCOL_VERSION = 10;
|
|
4
4
|
const APP_METADATA_RESPONSE_STAGE_NO_MATCH_HEADER = "x-vinext-app-metadata-stage-no-match";
|
|
5
5
|
const STATIC_FILE_SIGNAL_TOKEN_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
6
6
|
/** Normalize a shared App page HEAD request onto its method-invariant GET representation. */
|
|
@@ -27,7 +27,7 @@ function isCanonicalHttpOrigin(value) {
|
|
|
27
27
|
function isAppWorkerResponseStageProps(value) {
|
|
28
28
|
if (!value || typeof value !== "object") return false;
|
|
29
29
|
const props = value;
|
|
30
|
-
if (props.protocolVersion !==
|
|
30
|
+
if (props.protocolVersion !== 10 || props.buildId !== null && typeof props.buildId !== "string" || !isResponseStageCacheability(props.cacheability) || props.draftModeCookie !== null && typeof props.draftModeCookie !== "string" || props.middlewareCookieOverlay !== null && typeof props.middlewareCookieOverlay !== "string" || !isCanonicalHttpOrigin(props.requestOrigin) || props.scriptNonce !== null && typeof props.scriptNonce !== "string") return false;
|
|
31
31
|
if (props.kind === "app-full-request") return typeof props.prerenderDiscovery === "boolean" && typeof props.staticFileSignalToken === "string" && STATIC_FILE_SIGNAL_TOKEN_RE.test(props.staticFileSignalToken) && (props.trustedPrerenderState === null || isTrustedPrerenderState(props.trustedPrerenderState));
|
|
32
32
|
if (props.kind === "hybrid-pages") {
|
|
33
33
|
const hybrid = props;
|
|
@@ -36,9 +36,9 @@ function isAppWorkerResponseStageProps(value) {
|
|
|
36
36
|
}
|
|
37
37
|
if (props.kind === "app-metadata" || props.kind === "app-not-found") {
|
|
38
38
|
const special = props;
|
|
39
|
-
return typeof special.canonicalPathname === "string" && special.canonicalPathname.startsWith("/") && typeof special.cleanPathname === "string" && special.cleanPathname.startsWith("/") && typeof special.isRscRequest === "boolean" && (special.mountedSlotsHeader === null || typeof special.mountedSlotsHeader === "string") && typeof special.resolvedUrl === "string" && special.resolvedUrl.startsWith("/") && (special.renderMode === "navigation" || special.renderMode === "prefetch-empty" || special.renderMode === "prefetch-dynamic-shell" || special.renderMode === "prefetch-loading-shell");
|
|
39
|
+
return typeof special.canonicalPathname === "string" && special.canonicalPathname.startsWith("/") && typeof special.cleanPathname === "string" && special.cleanPathname.startsWith("/") && typeof special.isRscRequest === "boolean" && (special.mountedSlotsHeader === null || typeof special.mountedSlotsHeader === "string") && typeof special.resolvedUrl === "string" && special.resolvedUrl.startsWith("/") && (props.kind !== "app-metadata" || typeof props.routePathname === "string" && props.routePathname.startsWith("/")) && (special.renderMode === "navigation" || special.renderMode === "prefetch-empty" || special.renderMode === "prefetch-dynamic-shell" || special.renderMode === "prefetch-loading-shell");
|
|
40
40
|
}
|
|
41
|
-
return (props.kind === "app-page" || props.kind === "app-route-handler") && typeof props.bypassInterceptionContextCache === "boolean" && typeof props.canUseCanonicalLoadingShell === "boolean" && typeof props.canonicalPathname === "string" && props.canonicalPathname.startsWith("/") && typeof props.cleanPathname === "string" && props.cleanPathname.startsWith("/") && (props.forceDynamic === void 0 || typeof props.forceDynamic === "boolean") && (props.interceptionContext === null || typeof props.interceptionContext === "string") && (props.interceptionId === null || typeof props.interceptionId === "string") && typeof props.isRscRequest === "boolean" && (props.matchKind === "interception" || props.matchKind === "request" || props.matchKind === "resolved") && (props.mountedSlotsHeader === null || typeof props.mountedSlotsHeader === "string") && isAppPageParams(props.params) && typeof props.resolvedUrl === "string" && props.resolvedUrl.startsWith("/") && typeof props.routePattern === "string" && props.routePattern.startsWith("/") && typeof props.routePathname === "string" && props.routePathname.startsWith("/") && (props.renderMode === "navigation" || props.renderMode === "prefetch-empty" || props.renderMode === "prefetch-dynamic-shell" || props.renderMode === "prefetch-loading-shell");
|
|
41
|
+
return (props.kind === "app-page" || props.kind === "app-route-handler") && typeof props.bypassInterceptionContextCache === "boolean" && typeof props.cachePathname === "string" && props.cachePathname.startsWith("/") && typeof props.canUseCanonicalLoadingShell === "boolean" && typeof props.canonicalPathname === "string" && props.canonicalPathname.startsWith("/") && typeof props.cleanPathname === "string" && props.cleanPathname.startsWith("/") && (props.forceDynamic === void 0 || typeof props.forceDynamic === "boolean") && (props.interceptionContext === null || typeof props.interceptionContext === "string") && (props.interceptionId === null || typeof props.interceptionId === "string") && typeof props.isRscRequest === "boolean" && (props.matchKind === "interception" || props.matchKind === "request" || props.matchKind === "resolved") && (props.mountedSlotsHeader === null || typeof props.mountedSlotsHeader === "string") && isAppPageParams(props.params) && typeof props.resolvedUrl === "string" && props.resolvedUrl.startsWith("/") && typeof props.routePattern === "string" && props.routePattern.startsWith("/") && typeof props.routePathname === "string" && props.routePathname.startsWith("/") && (props.renderMode === "navigation" || props.renderMode === "prefetch-empty" || props.renderMode === "prefetch-dynamic-shell" || props.renderMode === "prefetch-loading-shell");
|
|
42
42
|
}
|
|
43
43
|
function isSerializedHeaders(value) {
|
|
44
44
|
return Array.isArray(value) && value.every((entry) => Array.isArray(entry) && entry.length === 2 && typeof entry[0] === "string" && typeof entry[1] === "string");
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { fnv1a64 } from "../utils/hash.js";
|
|
2
1
|
import { isUnknownRecord } from "../utils/record.js";
|
|
2
|
+
import { fnv1a64 } from "../utils/hash.js";
|
|
3
3
|
//#region src/server/artifact-compatibility.ts
|
|
4
4
|
const ARTIFACT_COMPATIBILITY_SCHEMA_VERSION = 1;
|
|
5
5
|
const APP_ELEMENTS_SCHEMA_VERSION = 1;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import { isUnknownRecord } from "../utils/record.js";
|
|
1
2
|
import { fnv1a64 } from "../utils/hash.js";
|
|
2
3
|
import { parseAppElementsWireElementKey } from "./app-elements-wire-key.js";
|
|
3
|
-
import { isUnknownRecord } from "../utils/record.js";
|
|
4
4
|
import { parseArtifactCompatibilityEnvelope } from "./artifact-compatibility.js";
|
|
5
5
|
import { isNonNegativeSafeInteger } from "../utils/number.js";
|
|
6
6
|
//#region src/server/client-reuse-manifest.ts
|
|
@@ -36,7 +36,7 @@ export type DevServerInfo = {
|
|
|
36
36
|
/** Project directory the server is running in. Used to detect stale entries. */
|
|
37
37
|
cwd: string;
|
|
38
38
|
};
|
|
39
|
-
|
|
39
|
+
type DevLockfile = {
|
|
40
40
|
/** Update the lock file contents (e.g. once the port is known after listen). */
|
|
41
41
|
update(info: DevServerInfo): void;
|
|
42
42
|
/** Release the lock — deletes the file. Safe to call multiple times. */
|
|
@@ -99,7 +99,7 @@ function formatAlreadyRunningError(opts) {
|
|
|
99
99
|
"Another vinext dev server appears to be running in this directory.",
|
|
100
100
|
"",
|
|
101
101
|
`Stale lock file: ${path.relative(cwd, lockfilePath)}`,
|
|
102
|
-
"Remove it manually if no server is running, then re-run `
|
|
102
|
+
"Remove it manually if no server is running, then re-run `vite dev`."
|
|
103
103
|
].join("\n");
|
|
104
104
|
const killCommand = process.platform === "win32" ? `taskkill /PID ${existing.pid} /F` : `kill ${existing.pid}`;
|
|
105
105
|
return [
|
|
@@ -160,7 +160,10 @@ function tryAcquireLockfile(opts) {
|
|
|
160
160
|
lockfile: {
|
|
161
161
|
path: lockfilePath,
|
|
162
162
|
update(next) {
|
|
163
|
+
if (released) return;
|
|
163
164
|
try {
|
|
165
|
+
const current = readLockfile(lockfilePath);
|
|
166
|
+
if (!current || current.pid !== ownerPid) return;
|
|
164
167
|
writeLockfile(lockfilePath, next);
|
|
165
168
|
} catch {}
|
|
166
169
|
},
|
|
@@ -44,7 +44,7 @@ reactStrictMode?: boolean,
|
|
|
44
44
|
/** Next.js `expireTime`, used when formatting terminal GSP responses. */
|
|
45
45
|
expireTime?: number, crossOrigin?: string,
|
|
46
46
|
/** Resolved Pages Router build ID shared with the dev data-route parser. */
|
|
47
|
-
buildId?: string): (req: IncomingMessage, res: ServerResponse, url: string,
|
|
47
|
+
buildId?: string, clientMiddlewareMatcher?: unknown, classifyPageRoute?: (route: Route) => "static" | "server" | "none"): (req: IncomingMessage, res: ServerResponse, url: string,
|
|
48
48
|
/** Status code override — propagated from middleware rewrite status. */
|
|
49
49
|
statusCode?: number,
|
|
50
50
|
/**
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { closeAfterResponse, createRequestContext, runWithRequestContext } from "../shims/unified-request-context.js";
|
|
2
2
|
import { createValidFileMatcher, findFileWithExts } from "../routing/file-matcher.js";
|
|
3
|
+
import { isBotUserAgent } from "../utils/html-limited-bots.js";
|
|
4
|
+
import { PRERENDER_REVALIDATE_HEADER } from "../utils/protocol-headers.js";
|
|
5
|
+
import { sanitizeDestination } from "../config/config-matchers.js";
|
|
3
6
|
import { patternToNextFormat } from "../routing/route-validation.js";
|
|
4
7
|
import { matchRoute } from "../routing/pages-router.js";
|
|
5
|
-
import { PRERENDER_REVALIDATE_HEADER } from "../utils/protocol-headers.js";
|
|
6
8
|
import { NEXTJS_CACHE_HEADER, NEXTJS_DEPLOYMENT_ID_HEADER } from "./headers.js";
|
|
7
9
|
import { isDangerousScheme } from "../shims/url-safety.js";
|
|
8
|
-
import { sanitizeDestination } from "../config/config-matchers.js";
|
|
9
10
|
import { extractLocaleFromUrl as extractLocaleFromUrl$1, resolvePagesI18nRequest } from "./pages-i18n.js";
|
|
10
11
|
import { importModule, reportRequestError } from "./instrumentation.js";
|
|
11
12
|
import { NEVER_CACHE_CONTROL } from "./cache-control.js";
|
|
@@ -26,7 +27,6 @@ import { buildPagesReadinessNextData } from "./pages-readiness.js";
|
|
|
26
27
|
import { resolvePagesPageMethodResponse } from "./pages-page-method.js";
|
|
27
28
|
import { loadUserDocumentInitialProps, runDocumentRenderPage } from "./pages-document-initial-props.js";
|
|
28
29
|
import { callDocumentGetInitialProps } from "./document-initial-head.js";
|
|
29
|
-
import { isBotUserAgent } from "../utils/html-limited-bots.js";
|
|
30
30
|
import { hasPagesGetInitialProps, loadDevAppInitialProps, loadPagesGetInitialProps } from "./pages-get-initial-props.js";
|
|
31
31
|
import { isSerializableProps } from "./pages-serializable-props.js";
|
|
32
32
|
import { traceFindPageComponents, tracePagesData, tracePagesDocument, tracePagesDocumentStream } from "./pages-execution-tracing.js";
|
|
@@ -315,9 +315,20 @@ function extractLocaleFromUrl(url, i18nConfig) {
|
|
|
315
315
|
* 4. Render the component to HTML
|
|
316
316
|
* 5. Wrap in _document shell and send response
|
|
317
317
|
*/
|
|
318
|
-
function createSSRHandler(server, runner, routes, pagesDir, i18nConfig, fileMatcher, basePath = "", trailingSlash = false, hasMiddleware = false, hasRewrites = false, clientTraceMetadata, htmlLimitedBots, reactStrictMode = false, expireTime = PAGES_CACHE_ONE_YEAR_SECONDS, crossOrigin, buildId = process.env.__VINEXT_BUILD_ID ?? "development") {
|
|
318
|
+
function createSSRHandler(server, runner, routes, pagesDir, i18nConfig, fileMatcher, basePath = "", trailingSlash = false, hasMiddleware = false, hasRewrites = false, clientTraceMetadata, htmlLimitedBots, reactStrictMode = false, expireTime = PAGES_CACHE_ONE_YEAR_SECONDS, crossOrigin, buildId = process.env.__VINEXT_BUILD_ID ?? "development", clientMiddlewareMatcher, classifyPageRoute) {
|
|
319
319
|
const matcher = fileMatcher ?? createValidFileMatcher();
|
|
320
320
|
const pagePatterns = routes.map((r) => patternToNextFormat(r.pattern));
|
|
321
|
+
const pageLoaders = routes.map((route) => ({
|
|
322
|
+
pattern: patternToNextFormat(route.pattern),
|
|
323
|
+
moduleSource: createPagesDevModuleUrl(server.config.root, route.filePath, "/"),
|
|
324
|
+
dataKind: classifyPageRoute?.(route) ?? "none"
|
|
325
|
+
}));
|
|
326
|
+
const errorFile = findFileWithExts(pagesDir, "_error", matcher);
|
|
327
|
+
pageLoaders.push({
|
|
328
|
+
pattern: "/_error",
|
|
329
|
+
moduleSource: errorFile ? createPagesDevModuleUrl(server.config.root, errorFile, "/") : "next/error",
|
|
330
|
+
dataKind: "none"
|
|
331
|
+
});
|
|
321
332
|
const _alsRegistration = Promise.all([runner.import("vinext/head-state"), runner.import("vinext/router-state")]);
|
|
322
333
|
_alsRegistration.catch(() => {});
|
|
323
334
|
return async (req, res, url, statusCode, isDataReq = false, originalUrl = url) => {
|
|
@@ -357,6 +368,9 @@ function createSSRHandler(server, runner, routes, pagesDir, i18nConfig, fileMatc
|
|
|
357
368
|
basePath,
|
|
358
369
|
buildId,
|
|
359
370
|
clientTraceMetadata,
|
|
371
|
+
pageLoaders,
|
|
372
|
+
hasMiddleware,
|
|
373
|
+
clientMiddlewareMatcher,
|
|
360
374
|
locale: locale ?? currentDefaultLocale,
|
|
361
375
|
locales: i18nConfig?.locales,
|
|
362
376
|
defaultLocale: currentDefaultLocale,
|
|
@@ -798,12 +812,14 @@ function createSSRHandler(server, runner, routes, pagesDir, i18nConfig, fileMatc
|
|
|
798
812
|
pageModuleUrl,
|
|
799
813
|
appModuleUrl,
|
|
800
814
|
hasMiddleware,
|
|
801
|
-
routeUrl: requestAsPath
|
|
815
|
+
routeUrl: requestAsPath,
|
|
816
|
+
clientMiddlewareMatcher
|
|
802
817
|
}
|
|
803
818
|
};
|
|
804
819
|
const hydrationScript = createPagesDevHydrationScript({
|
|
805
820
|
appModuleSource,
|
|
806
821
|
pageModuleSource,
|
|
822
|
+
pageLoaders,
|
|
807
823
|
reactStrictMode: reactStrictMode === true,
|
|
808
824
|
replaceFallbackRoute: true,
|
|
809
825
|
scriptNonce
|
|
@@ -1037,16 +1053,22 @@ async function renderErrorPage(server, runner, req, res, url, pagesDir, statusCo
|
|
|
1037
1053
|
query: parseQueryString(url),
|
|
1038
1054
|
buildId: context.buildId ?? process.env.__VINEXT_BUILD_ID ?? "development",
|
|
1039
1055
|
isFallback: false,
|
|
1056
|
+
locale: context.locale,
|
|
1057
|
+
locales: context.locales,
|
|
1058
|
+
defaultLocale: context.defaultLocale,
|
|
1040
1059
|
notFoundSrcPage: context.notFoundSrcPage,
|
|
1041
1060
|
__vinext: {
|
|
1042
1061
|
pageModuleUrl: errorModuleUrl ?? void 0,
|
|
1043
|
-
appModuleUrl: appModuleUrl ?? void 0
|
|
1062
|
+
appModuleUrl: appModuleUrl ?? void 0,
|
|
1063
|
+
hasMiddleware: context.hasMiddleware,
|
|
1064
|
+
clientMiddlewareMatcher: context.clientMiddlewareMatcher
|
|
1044
1065
|
}
|
|
1045
1066
|
})}<\/script>`}\n${createPagesDevHydrationScript({
|
|
1046
1067
|
appModuleSource,
|
|
1047
1068
|
forceRouterReady: true,
|
|
1048
1069
|
normalizePageProps: false,
|
|
1049
1070
|
pageModuleSource: errorModuleSource,
|
|
1071
|
+
pageLoaders: context.pageLoaders,
|
|
1050
1072
|
reactStrictMode: reactStrictMode === true,
|
|
1051
1073
|
scriptNonce,
|
|
1052
1074
|
setPagePatternsFromNextData: true
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { toSlash } from "../deps/.pnpm/pathslash@0.1.0/deps/pathslash/dist/index.js";
|
|
2
2
|
import { VINEXT_ORIGINAL_STACK_TRACE_ENDPOINT } from "../utils/dev-stack-sourcemap-endpoint.js";
|
|
3
|
-
import { readFile } from "node:fs/promises";
|
|
4
3
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
4
|
+
import { readFile } from "node:fs/promises";
|
|
5
5
|
//#region src/server/dev-stack-sourcemap.ts
|
|
6
6
|
const MAX_ORIGINAL_STACK_TRACE_BODY_BYTES = 1048576;
|
|
7
7
|
const V8_PAREN_STACK_LINE = /^(\s*at\s+.*?\()(.+):(\d+):(\d+)(\)\s*)$/;
|
package/dist/server/html.d.ts
CHANGED
|
@@ -1,24 +1,4 @@
|
|
|
1
1
|
//#region src/server/html.d.ts
|
|
2
|
-
/**
|
|
3
|
-
* HTML-safe JSON serialization for embedding data in <script> tags.
|
|
4
|
-
*
|
|
5
|
-
* JSON.stringify does NOT escape characters that are meaningful to the
|
|
6
|
-
* HTML parser. If a JSON string value contains "</script>", the browser
|
|
7
|
-
* closes the script tag early — anything after it executes as HTML.
|
|
8
|
-
* This is a well-known stored XSS vector in SSR frameworks.
|
|
9
|
-
*
|
|
10
|
-
* Next.js mitigates this with htmlEscapeJsonString(). We do the same.
|
|
11
|
-
*
|
|
12
|
-
* Characters escaped:
|
|
13
|
-
* < → \u003c (prevents </script> and <!-- breakout)
|
|
14
|
-
* > → \u003e (prevents --> and other HTML close sequences)
|
|
15
|
-
* & → \u0026 (prevents < entity interpretation in XHTML)
|
|
16
|
-
* \u2028 → \\u2028 (line separator — invalid in JS string literals pre-ES2019)
|
|
17
|
-
* \u2029 → \\u2029 (paragraph separator — same)
|
|
18
|
-
*
|
|
19
|
-
* The result is valid JSON that is also safe to embed in any HTML context
|
|
20
|
-
* without additional escaping.
|
|
21
|
-
*/
|
|
22
2
|
export declare function safeJsonStringify(data: unknown): string;
|
|
23
3
|
export declare function escapeHtmlAttr(value: string): string;
|
|
24
4
|
export declare function htmlTokenListContains(value: string | null, token: string): boolean;
|
package/dist/server/html.js
CHANGED
|
@@ -19,8 +19,23 @@
|
|
|
19
19
|
* The result is valid JSON that is also safe to embed in any HTML context
|
|
20
20
|
* without additional escaping.
|
|
21
21
|
*/
|
|
22
|
+
const HTML_UNSAFE_JSON_CHAR_RE = /[<>&\u2028\u2029]/;
|
|
23
|
+
const HTML_UNSAFE_JSON_CHARS_RE = /[<>&\u2028\u2029]/g;
|
|
24
|
+
const HTML_UNSAFE_JSON_ESCAPES = {
|
|
25
|
+
"<": "\\u003c",
|
|
26
|
+
">": "\\u003e",
|
|
27
|
+
"&": "\\u0026",
|
|
28
|
+
"\u2028": "\\u2028",
|
|
29
|
+
"\u2029": "\\u2029"
|
|
30
|
+
};
|
|
31
|
+
function escapeHtmlUnsafeJsonChar(char) {
|
|
32
|
+
return HTML_UNSAFE_JSON_ESCAPES[char];
|
|
33
|
+
}
|
|
22
34
|
function safeJsonStringify(data) {
|
|
23
|
-
|
|
35
|
+
const json = JSON.stringify(data);
|
|
36
|
+
if (json === void 0) throw new TypeError("Cannot serialize value as JSON");
|
|
37
|
+
if (!HTML_UNSAFE_JSON_CHAR_RE.test(json)) return json;
|
|
38
|
+
return json.replace(HTML_UNSAFE_JSON_CHARS_RE, escapeHtmlUnsafeJsonChar);
|
|
24
39
|
}
|
|
25
40
|
function escapeHtmlAttr(value) {
|
|
26
41
|
return value.replace(/&/g, "&").replace(/"/g, """).replace(/</g, "<").replace(/>/g, ">");
|
|
@@ -55,21 +55,16 @@ export declare function getOnRequestErrorHandler(): OnRequestErrorHandler | null
|
|
|
55
55
|
/**
|
|
56
56
|
* Load and execute the instrumentation file via a ModuleRunner.
|
|
57
57
|
*
|
|
58
|
-
* Called
|
|
58
|
+
* Called during Node development startup (`configureServer`). It:
|
|
59
59
|
* 1. Loads the instrumentation module via `runner.import()`.
|
|
60
60
|
* 2. Calls the `register()` function if exported.
|
|
61
61
|
* 3. Stores the `onRequestError()` handler on `globalThis` so it is visible
|
|
62
62
|
* to all Vite environment module graphs (SSR and the host process share
|
|
63
63
|
* the same Node.js `globalThis`).
|
|
64
64
|
*
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
* @param runner - A ModuleRunner created via `createDirectRunner()`. Must be
|
|
70
|
-
* the same long-lived runner used for middleware and SSR so the module graph
|
|
71
|
-
* is shared. Safe with all Vite plugin combinations, including
|
|
72
|
-
* `@cloudflare/vite-plugin`, because it never touches the hot channel.
|
|
65
|
+
* @param runner - The existing RSC runner for App Router, or the long-lived
|
|
66
|
+
* direct runner for Pages-only apps. Reusing the request runner preserves
|
|
67
|
+
* module state initialized by `register()`.
|
|
73
68
|
* @param instrumentationPath - Absolute path to the instrumentation file
|
|
74
69
|
*/
|
|
75
70
|
export declare function runInstrumentation(runner: ModuleImporter, instrumentationPath: string): Promise<void>;
|
|
@@ -20,12 +20,12 @@ import fs from "node:fs";
|
|
|
20
20
|
*
|
|
21
21
|
* ## App Router
|
|
22
22
|
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
23
|
+
* Node development eagerly calls `runInstrumentation()` through the same RSC
|
|
24
|
+
* runner used for requests. The generated RSC entry also awaits the shared
|
|
25
|
+
* registration promise before importing user server modules. This preserves
|
|
26
|
+
* react-server conditions, module state, and initialization order.
|
|
27
|
+
* Workers and production initialize through the generated entry in their own
|
|
28
|
+
* runtime, without an extra registration in the Node development host.
|
|
29
29
|
*
|
|
30
30
|
* The `onRequestError` handler is stored on `globalThis` so it is visible across
|
|
31
31
|
* the RSC and SSR Vite environments (separate module graphs, same Node.js process).
|
|
@@ -81,21 +81,16 @@ function getOnRequestErrorHandler() {
|
|
|
81
81
|
/**
|
|
82
82
|
* Load and execute the instrumentation file via a ModuleRunner.
|
|
83
83
|
*
|
|
84
|
-
* Called
|
|
84
|
+
* Called during Node development startup (`configureServer`). It:
|
|
85
85
|
* 1. Loads the instrumentation module via `runner.import()`.
|
|
86
86
|
* 2. Calls the `register()` function if exported.
|
|
87
87
|
* 3. Stores the `onRequestError()` handler on `globalThis` so it is visible
|
|
88
88
|
* to all Vite environment module graphs (SSR and the host process share
|
|
89
89
|
* the same Node.js `globalThis`).
|
|
90
90
|
*
|
|
91
|
-
*
|
|
92
|
-
*
|
|
93
|
-
*
|
|
94
|
-
*
|
|
95
|
-
* @param runner - A ModuleRunner created via `createDirectRunner()`. Must be
|
|
96
|
-
* the same long-lived runner used for middleware and SSR so the module graph
|
|
97
|
-
* is shared. Safe with all Vite plugin combinations, including
|
|
98
|
-
* `@cloudflare/vite-plugin`, because it never touches the hot channel.
|
|
91
|
+
* @param runner - The existing RSC runner for App Router, or the long-lived
|
|
92
|
+
* direct runner for Pages-only apps. Reusing the request runner preserves
|
|
93
|
+
* module state initialized by `register()`.
|
|
99
94
|
* @param instrumentationPath - Absolute path to the instrumentation file
|
|
100
95
|
*/
|
|
101
96
|
async function runInstrumentation(runner, instrumentationPath) {
|
package/dist/server/isr-cache.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { getRequestExecutionContext } from "../shims/request-context.js";
|
|
2
1
|
import { PRERENDER_REVALIDATE_HEADER, PRERENDER_REVALIDATE_ONLY_GENERATED_HEADER } from "../utils/protocol-headers.js";
|
|
2
|
+
import { getRequestExecutionContext } from "../shims/request-context.js";
|
|
3
3
|
import { reportRequestError } from "./instrumentation.js";
|
|
4
4
|
import { getCdnCacheAdapter } from "../shims/cdn-cache.js";
|
|
5
5
|
import { fnv1a64 } from "../utils/hash.js";
|
|
@@ -163,7 +163,7 @@ function isrCacheKey(router, pathname, buildId) {
|
|
|
163
163
|
* Cloudflare KV key under its 512-byte limit for long pathnames.
|
|
164
164
|
*/
|
|
165
165
|
function appIsrCacheKey(pathname, suffix, buildId = process.env.__VINEXT_BUILD_ID) {
|
|
166
|
-
return buildCacheKey(buildId ? `app:${buildId}` : "app", pathname, suffix);
|
|
166
|
+
return buildCacheKey(buildId ? `app:v2:${buildId}` : "app:v2", pathname, suffix);
|
|
167
167
|
}
|
|
168
168
|
function appIsrHtmlKey(pathname) {
|
|
169
169
|
return appIsrCacheKey(pathname, "html");
|
|
@@ -194,7 +194,7 @@ function appIsrRscKey(pathname, mountedSlotsHeader, renderMode = APP_RSC_RENDER_
|
|
|
194
194
|
return appIsrCacheKey(pathname, variant ? `rsc:${variant}` : "rsc");
|
|
195
195
|
}
|
|
196
196
|
function appIsrRouteKey(pathname) {
|
|
197
|
-
return appIsrCacheKey(pathname, "route");
|
|
197
|
+
return appIsrCacheKey(pathname, pathname !== "/" && pathname.endsWith("/") ? "route:trailing-slash" : "route");
|
|
198
198
|
}
|
|
199
199
|
//#endregion
|
|
200
200
|
export { PRERENDER_REVALIDATE_HEADER, PRERENDER_REVALIDATE_ONLY_GENERATED_HEADER, appIsrCacheKey, appIsrHtmlKey, appIsrRouteKey, appIsrRscKey, buildAppPageCacheValue, buildPagesCacheValue, coalesceOnDemandRevalidation, getRevalidateSecret, isOnDemandRevalidateRequest, isRevalidateSecret, isrCacheControl, isrCacheKey, isrGet, isrSet, isrSetPrerenderedAppPage, normalizeMountedSlotsHeader, triggerBackgroundRegeneration };
|
|
@@ -21,6 +21,7 @@ type MetadataRouteRequestOptions = {
|
|
|
21
21
|
isrRouteKey?: (pathname: string) => string;
|
|
22
22
|
isrSet?: MetadataRouteCacheSetter;
|
|
23
23
|
makeThenableParams: MetadataRouteMakeThenableParams;
|
|
24
|
+
routePathname?: string;
|
|
24
25
|
scheduleBackgroundRegeneration?: MetadataRouteBackgroundRegenerator;
|
|
25
26
|
};
|
|
26
27
|
export type PrerenderableMetadataRoute = {
|