vinext 1.1.0 → 1.2.1
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 +22 -10
- package/dist/build/client-build-config.d.ts +10 -0
- package/dist/build/client-build-config.js +18 -2
- 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.d.ts +8 -0
- package/dist/build/pages-client-assets-module.js +21 -1
- package/dist/build/prerender-paths.js +6 -4
- package/dist/build/prerender.js +1 -1
- package/dist/build/run-prerender.js +1 -1
- package/dist/build/ssr-manifest.d.ts +2 -0
- package/dist/build/ssr-manifest.js +6 -2
- package/dist/check.js +12 -12
- package/dist/cli-dev-config.js +3 -3
- package/dist/cli.js +3 -2
- package/dist/client/client-redirect-matcher.d.ts +14 -0
- package/dist/client/client-redirect-matcher.js +37 -0
- package/dist/client/client-redirects.d.ts +27 -0
- package/dist/client/client-redirects.js +28 -0
- package/dist/client/client-rewrites.d.ts +2 -1
- package/dist/client/client-rewrites.js +1 -1
- package/dist/config/config-matchers.d.ts +26 -11
- package/dist/config/config-matchers.js +90 -88
- package/dist/config/destination-params.d.ts +47 -0
- package/dist/config/destination-params.js +116 -0
- package/dist/config/next-config.d.ts +7 -0
- package/dist/config/next-config.js +3 -0
- package/dist/entries/app-rsc-entry.d.ts +4 -0
- package/dist/entries/app-rsc-entry.js +20 -6
- package/dist/entries/pages-client-entry.js +3 -1
- package/dist/entries/pages-server-entry.js +13 -37
- package/dist/index.d.ts +3 -1
- package/dist/index.js +246 -136
- package/dist/init-cloudflare.d.ts +9 -0
- package/dist/init-cloudflare.js +107 -31
- package/dist/init-platform.d.ts +4 -0
- package/dist/init-platform.js +27 -2
- package/dist/init.d.ts +2 -1
- package/dist/init.js +153 -9
- package/dist/plugins/ast-scope.d.ts +7 -0
- package/dist/plugins/ast-scope.js +59 -3
- 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.d.ts +1 -1
- package/dist/plugins/dynamic-preload-metadata.js +11 -11
- 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.d.ts +1 -1
- package/dist/plugins/ignore-dynamic-requests.js +5 -7
- 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/middleware-server-only.d.ts +5 -4
- package/dist/plugins/middleware-server-only.js +8 -5
- package/dist/plugins/og-harfbuzz.js +2 -3
- package/dist/plugins/optimize-imports.js +3 -4
- package/dist/plugins/pages-node-externals.js +3 -4
- 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-scan-glob-imports.d.ts +19 -0
- package/dist/plugins/rsc-scan-glob-imports.js +50 -0
- package/dist/plugins/strip-server-exports.js +265 -102
- package/dist/plugins/styled-jsx.js +2 -3
- package/dist/plugins/transform-result.d.ts +9 -5
- package/dist/plugins/transitive-externals.js +1 -1
- package/dist/plugins/typeof-window.d.ts +2 -2
- package/dist/plugins/use-cache-callable.d.ts +21 -2
- package/dist/plugins/use-cache-callable.js +84 -35
- package/dist/plugins/worker-image-imports.js +30 -33
- package/dist/plugins/worker-server-only-imports.d.ts +20 -0
- package/dist/plugins/worker-server-only-imports.js +31 -0
- package/dist/plugins/worker-use-server.d.ts +25 -0
- package/dist/plugins/worker-use-server.js +153 -0
- package/dist/server/api-handler.d.ts +1 -0
- package/dist/server/api-handler.js +3 -2
- package/dist/server/app-action-forwarding.js +2 -2
- package/dist/server/app-browser-action-result.d.ts +1 -1
- package/dist/server/app-browser-action-result.js +9 -2
- package/dist/server/app-browser-entry.js +3 -3
- package/dist/server/app-browser-interception-context.js +1 -1
- package/dist/server/app-browser-navigation-controller.js +1 -1
- package/dist/server/app-browser-prefetch-response.js +2 -2
- package/dist/server/app-browser-server-action-client.js +1 -1
- package/dist/server/app-browser-state.js +1 -1
- package/dist/server/app-browser-supplemental-refresh.js +1 -1
- package/dist/server/app-middleware.d.ts +11 -0
- package/dist/server/app-middleware.js +17 -2
- package/dist/server/app-optimistic-routing.js +1 -1
- package/dist/server/app-page-cache.d.ts +1 -1
- package/dist/server/app-page-cache.js +1 -1
- package/dist/server/app-page-dispatch.d.ts +3 -1
- package/dist/server/app-page-dispatch.js +5 -4
- package/dist/server/app-page-ppr-runtime.js +1 -1
- package/dist/server/app-page-render-observation.js +1 -1
- package/dist/server/app-page-render.js +1 -1
- package/dist/server/app-page-request.js +53 -15
- package/dist/server/app-page-route-wiring.js +2 -2
- package/dist/server/app-pages-bridge.d.ts +1 -1
- package/dist/server/app-pages-bridge.js +3 -4
- package/dist/server/app-prerender-endpoints.js +9 -6
- 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-request-stage-dispatch.js +6 -2
- package/dist/server/app-request-stage-independent-entry.js +29 -9
- package/dist/server/app-response-stage-entry.js +11 -3
- package/dist/server/app-route-handler-cache.d.ts +1 -0
- package/dist/server/app-route-handler-cache.js +1 -0
- package/dist/server/app-route-handler-dispatch.d.ts +1 -0
- package/dist/server/app-route-handler-dispatch.js +5 -2
- package/dist/server/app-route-handler-execution.d.ts +1 -0
- package/dist/server/app-route-handler-execution.js +1 -0
- package/dist/server/app-route-handler-runtime.d.ts +4 -1
- package/dist/server/app-route-handler-runtime.js +46 -25
- package/dist/server/app-router-entry.js +29 -10
- package/dist/server/app-rsc-cache-busting.d.ts +16 -0
- package/dist/server/app-rsc-cache-busting.js +30 -13
- package/dist/server/app-rsc-errors.js +20 -16
- package/dist/server/app-rsc-handler.d.ts +7 -0
- package/dist/server/app-rsc-handler.js +89 -39
- package/dist/server/app-rsc-request-normalization.js +3 -3
- package/dist/server/app-rsc-response-stage.js +5 -3
- package/dist/server/app-segment-config.d.ts +2 -1
- package/dist/server/app-server-action-execution.d.ts +2 -1
- package/dist/server/app-server-action-execution.js +62 -23
- package/dist/server/app-ssr-entry.js +7 -5
- package/dist/server/app-visited-response-cache.js +2 -2
- package/dist/server/app-worker-stages.d.ts +5 -0
- package/dist/server/app-worker-stages.js +1 -1
- package/dist/server/cacheability-request.js +2 -2
- package/dist/server/client-build-files.d.ts +16 -0
- package/dist/server/client-build-files.js +36 -0
- package/dist/server/client-reuse-manifest.js +1 -1
- package/dist/server/config-headers.js +1 -1
- 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 +39 -28
- package/dist/server/dev-stack-sourcemap.js +18 -23
- package/dist/server/document-initial-head.d.ts +0 -11
- package/dist/server/document-initial-head.js +1 -1
- package/dist/server/forwarded-middleware-context.d.ts +5 -0
- package/dist/server/forwarded-middleware-context.js +22 -0
- package/dist/server/headers.d.ts +4 -1
- package/dist/server/headers.js +4 -1
- package/dist/server/http-conditional.d.ts +11 -0
- package/dist/server/http-conditional.js +10 -1
- package/dist/server/http-error-responses.d.ts +1 -1
- package/dist/server/image-optimization.d.ts +38 -0
- package/dist/server/image-optimization.js +94 -4
- package/dist/server/isr-cache.d.ts +10 -0
- package/dist/server/isr-cache.js +41 -6
- package/dist/server/metadata-route-response.js +11 -10
- package/dist/server/middleware-matcher.d.ts +2 -0
- package/dist/server/middleware-matcher.js +23 -2
- package/dist/server/middleware-path-to-regexp.js +1 -1
- package/dist/server/middleware-runtime.d.ts +13 -0
- package/dist/server/middleware-runtime.js +38 -25
- package/dist/server/middleware.d.ts +1 -1
- package/dist/server/middleware.js +3 -1
- package/dist/server/multi-stage.d.ts +11 -0
- package/dist/server/navigation-planner.js +1 -1
- package/dist/server/normalize-path.d.ts +0 -13
- package/dist/server/normalize-path.js +1 -34
- package/dist/server/open-redirect.d.ts +11 -4
- package/dist/server/open-redirect.js +11 -4
- package/dist/server/pages-api-route.d.ts +3 -2
- package/dist/server/pages-api-route.js +6 -5
- package/dist/server/pages-cache-tag.d.ts +12 -0
- package/dist/server/pages-cache-tag.js +19 -0
- package/dist/server/pages-client-assets.d.ts +2 -0
- package/dist/server/pages-data-route.d.ts +10 -0
- package/dist/server/pages-data-route.js +21 -3
- package/dist/server/pages-document-asset-props.d.ts +5 -1
- package/dist/server/pages-document-asset-props.js +13 -5
- package/dist/server/pages-document-splice.d.ts +19 -0
- package/dist/server/pages-document-splice.js +55 -0
- package/dist/server/pages-i18n.d.ts +12 -1
- package/dist/server/pages-i18n.js +18 -4
- package/dist/server/pages-node-compat.d.ts +16 -5
- package/dist/server/pages-node-compat.js +20 -12
- package/dist/server/pages-page-data.d.ts +32 -24
- package/dist/server/pages-page-data.js +51 -121
- package/dist/server/pages-page-handler.d.ts +0 -6
- package/dist/server/pages-page-handler.js +189 -127
- package/dist/server/pages-page-response.d.ts +12 -6
- package/dist/server/pages-page-response.js +42 -35
- package/dist/server/pages-request-pipeline.d.ts +10 -2
- package/dist/server/pages-request-pipeline.js +41 -22
- package/dist/server/pages-request-stage-entry.d.ts +6 -0
- package/dist/server/pages-request-stage-entry.js +75 -16
- package/dist/server/pages-response-stage-entry.js +4 -0
- package/dist/server/pages-revalidate.js +3 -3
- package/dist/server/pages-router-entry.js +5 -4
- package/dist/server/prerender-manifest.d.ts +3 -3
- package/dist/server/prerender-manifest.js +4 -3
- package/dist/server/prerender-work-unit-setup.js +4 -0
- package/dist/server/prod-server.d.ts +12 -0
- package/dist/server/prod-server.js +204 -74
- package/dist/server/proper-error.d.ts +4 -0
- package/dist/server/proper-error.js +31 -0
- package/dist/server/request-pipeline.d.ts +4 -1
- package/dist/server/request-pipeline.js +3 -2
- package/dist/server/revalidation-request.d.ts +1 -0
- package/dist/server/revalidation-request.js +1 -1
- package/dist/server/rsc-stream-hints.d.ts +1 -1
- package/dist/server/rsc-stream-hints.js +52 -5
- package/dist/server/seed-cache.d.ts +1 -0
- package/dist/server/seed-cache.js +5 -4
- package/dist/server/server-reference-loader.d.ts +4 -0
- package/dist/server/server-reference-loader.js +29 -0
- package/dist/server/socket-error-backstop.d.ts +9 -1
- package/dist/server/socket-error-backstop.js +46 -17
- package/dist/server/static-file-signal.d.ts +15 -4
- package/dist/server/static-file-signal.js +46 -12
- package/dist/server/worker-image-optimization.d.ts +34 -0
- package/dist/server/worker-image-optimization.js +99 -0
- package/dist/server/worker-stages.d.ts +1 -1
- package/dist/server/worker-stages.js +2 -2
- package/dist/server/worker-utils.d.ts +8 -3
- package/dist/server/worker-utils.js +12 -7
- package/dist/shims/app-router-scroll.js +4 -1
- package/dist/shims/app-router-tree-context.d.ts +5 -0
- package/dist/shims/app-router-tree-context.js +27 -0
- package/dist/shims/cache-callable-runtime.d.ts +4 -2
- package/dist/shims/cache-callable-runtime.js +21 -12
- package/dist/shims/cache-handler.js +1 -9
- package/dist/shims/cache-runtime.d.ts +6 -1
- package/dist/shims/cache-runtime.js +2 -1
- package/dist/shims/cache.d.ts +2 -2
- package/dist/shims/cache.js +40 -13
- package/dist/shims/cdn-cache.d.ts +8 -0
- package/dist/shims/cdn-cache.js +17 -1
- package/dist/shims/disable-smooth-scroll.d.ts +3 -0
- package/dist/shims/disable-smooth-scroll.js +36 -0
- package/dist/shims/document-placeholders.d.ts +19 -0
- package/dist/shims/document-placeholders.js +45 -0
- package/dist/shims/document.js +21 -5
- package/dist/shims/dynamic-preload-chunks.d.ts +1 -0
- package/dist/shims/dynamic-preload-chunks.js +13 -9
- package/dist/shims/dynamic.d.ts +1 -1
- package/dist/shims/dynamic.js +60 -8
- package/dist/shims/fetch-cache-state.d.ts +66 -0
- package/dist/shims/fetch-cache-state.js +92 -0
- package/dist/shims/fetch-cache.d.ts +3 -67
- package/dist/shims/fetch-cache.js +160 -125
- package/dist/shims/head.d.ts +10 -6
- package/dist/shims/head.js +16 -14
- package/dist/shims/headers.js +2 -2
- package/dist/shims/image.js +2 -1
- package/dist/shims/internal/hybrid-client-route-owner-direct.js +1 -1
- package/dist/shims/internal/hybrid-client-route-owner.js +1 -0
- package/dist/shims/internal/work-store-scope.d.ts +5 -0
- package/dist/shims/internal/work-store-scope.js +24 -0
- package/dist/shims/link-prefetch.js +5 -4
- package/dist/shims/link.js +2 -2
- package/dist/shims/navigation.js +34 -9
- package/dist/shims/request-context.d.ts +2 -0
- package/dist/shims/request-state-types.d.ts +2 -1
- package/dist/shims/router.js +21 -32
- package/dist/shims/server.d.ts +27 -4
- package/dist/shims/server.js +65 -9
- package/dist/shims/unified-request-context.d.ts +1 -1
- package/dist/shims/url-utils.d.ts +9 -0
- package/dist/shims/url-utils.js +15 -4
- package/dist/utils/client-runtime-metadata.js +1 -1
- package/dist/utils/domain-locale.js +1 -1
- package/dist/utils/hash.d.ts +7 -0
- package/dist/utils/hash.js +11 -1
- package/dist/utils/package-name.d.ts +6 -0
- package/dist/utils/package-name.js +12 -1
- package/dist/utils/plugin-rsc-version.d.ts +6 -0
- package/dist/utils/plugin-rsc-version.js +41 -0
- package/dist/utils/prerender-output-paths.js +15 -4
- package/dist/utils/public-file-path.d.ts +10 -2
- package/dist/utils/public-file-path.js +13 -9
- package/dist/utils/public-routes.js +2 -2
- package/dist/utils/react-version.d.ts +10 -0
- package/dist/utils/react-version.js +39 -16
- package/package.json +11 -7
- 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
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { createRequestContext, runWithRequestContext } from "../shims/unified-request-context.js";
|
|
2
|
-
import { runWithExecutionContext } from "../shims/request-context.js";
|
|
3
2
|
import { serializeStaticFileSignalForTransport } from "./static-file-signal.js";
|
|
3
|
+
import { attachRequestCfMetadata } from "./request-pipeline.js";
|
|
4
|
+
import { runWithExecutionContext } from "../shims/request-context.js";
|
|
5
|
+
import { runInWorkStoreScope } from "../shims/internal/work-store-scope.js";
|
|
4
6
|
import { validateCdnRequest } from "./cache-control.js";
|
|
5
7
|
import { ensureFetchPatch } from "../shims/fetch-cache.js";
|
|
8
|
+
import { serializeImageOptimizationSignalForTransport } from "./image-optimization.js";
|
|
6
9
|
import { serializeResponseStageLinkProvenance } from "./app-response-header-provenance.js";
|
|
7
10
|
import { attachFrameworkRequestError, attachFrameworkRequestRoute, captureFrameworkRequestRoute, clearFrameworkRequestError } from "./request-tracing.js";
|
|
8
11
|
import { isAppWorkerResponseStageProps } from "./app-worker-stages.js";
|
|
@@ -26,10 +29,11 @@ async function invokeCacheFunction(invocation, env, platformCtx, dispatchRequest
|
|
|
26
29
|
executionContext,
|
|
27
30
|
rootParams: invocation.rootParams
|
|
28
31
|
});
|
|
29
|
-
await runWithRequestContext(context, () => invokeRegisteredCacheFunction(invocation, loadServerAction));
|
|
32
|
+
await runWithRequestContext(context, () => runInWorkStoreScope(() => invokeRegisteredCacheFunction(invocation, loadServerAction)));
|
|
30
33
|
}
|
|
31
34
|
async function handleResponseStage(request, env, platformCtx, props, dispatchRequestStage, options = { cache: "bypass" }) {
|
|
32
35
|
if (!isAppWorkerResponseStageProps(props)) return new Response("Invalid vinext App response stage", { status: 400 });
|
|
36
|
+
if (props.kind === "app-full-request" && props.headRequest) request = attachRequestCfMetadata(new Request(request, { method: "HEAD" }), request);
|
|
33
37
|
if (props.requestOrigin !== new URL(request.url).origin) return new Response("Invalid vinext App response stage", { status: 400 });
|
|
34
38
|
const currentBuildId = process.env.__VINEXT_BUILD_ID ?? null;
|
|
35
39
|
if (props.buildId !== currentBuildId) return new Response("Incompatible vinext App response stage", { status: 409 });
|
|
@@ -41,6 +45,10 @@ async function handleResponseStage(request, env, platformCtx, props, dispatchReq
|
|
|
41
45
|
...ctx,
|
|
42
46
|
isPrerenderPathDiscovery: true
|
|
43
47
|
};
|
|
48
|
+
else if (props.kind === "hybrid-pages" && options.regeneratesStoredEntry === true) ctx = {
|
|
49
|
+
...ctx,
|
|
50
|
+
isStoredEntryRegeneration: true
|
|
51
|
+
};
|
|
44
52
|
return withResponseStageCacheability({
|
|
45
53
|
buildId: process.env.__VINEXT_BUILD_ID,
|
|
46
54
|
cache: options.cache,
|
|
@@ -76,7 +84,7 @@ async function handleResponseStage(request, env, platformCtx, props, dispatchReq
|
|
|
76
84
|
failure = error;
|
|
77
85
|
result = new Response("Internal Server Error", { status: 500 });
|
|
78
86
|
}
|
|
79
|
-
const serialized = serializeStaticFileSignalForTransport(result, props.staticFileSignalToken);
|
|
87
|
+
const serialized = serializeImageOptimizationSignalForTransport(serializeStaticFileSignalForTransport(result, props.staticFileSignalToken), props.staticFileSignalToken);
|
|
80
88
|
return attachFrameworkRequestRoute(failed ? attachFrameworkRequestError(serialized, failure) : clearFrameworkRequestError(serialized), route);
|
|
81
89
|
}
|
|
82
90
|
const render = () => rscHandler.handleResponseStage(request, cacheabilityContext, props, options);
|
|
@@ -19,6 +19,7 @@ type ReadAppRouteHandlerCacheOptions = {
|
|
|
19
19
|
handlerFn: AppRouteHandlerFunction;
|
|
20
20
|
i18n?: NextI18nConfig | null;
|
|
21
21
|
trailingSlash?: boolean;
|
|
22
|
+
skipTrailingSlashRedirect?: boolean;
|
|
22
23
|
isAutoHead: boolean;
|
|
23
24
|
appendResponseLink?: boolean;
|
|
24
25
|
isrDebug?: AppRouteDebugLogger;
|
|
@@ -49,6 +49,7 @@ async function readAppRouteHandlerCacheResponse(options) {
|
|
|
49
49
|
handlerFn: options.handlerFn,
|
|
50
50
|
i18n: options.i18n,
|
|
51
51
|
trailingSlash: options.trailingSlash,
|
|
52
|
+
skipTrailingSlashRedirect: options.skipTrailingSlashRedirect,
|
|
52
53
|
markDynamicUsage: options.markDynamicUsage,
|
|
53
54
|
params: options.params === null ? null : makeThenableParams(options.params),
|
|
54
55
|
request: new Request(options.requestUrl, { method: "GET" }),
|
|
@@ -31,6 +31,7 @@ type DispatchAppRouteHandlerOptions = {
|
|
|
31
31
|
isrRouteKey: (pathname: string) => string;
|
|
32
32
|
isrSet: RouteHandlerCacheSetter;
|
|
33
33
|
trailingSlash?: boolean;
|
|
34
|
+
skipTrailingSlashRedirect?: boolean;
|
|
34
35
|
middlewareContext: RouteHandlerMiddlewareContext;
|
|
35
36
|
middlewareRequestHeaders?: Headers | null;
|
|
36
37
|
/**
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { closeAfterResponse, createRequestContext, runWithRequestContext } from "../shims/unified-request-context.js";
|
|
2
2
|
import "../utils/protocol-headers.js";
|
|
3
3
|
import { getRequestExecutionContext } from "../shims/request-context.js";
|
|
4
|
+
import { runInWorkStoreScope } from "../shims/internal/work-store-scope.js";
|
|
4
5
|
import { reportRequestError } from "./instrumentation.js";
|
|
5
6
|
import { beginRouteCacheability, getRouteCacheabilityDynamicReason } from "../shims/cacheability-classification.js";
|
|
6
7
|
import { applyCdnResponseBuildIdentityHeaders } from "./cache-control.js";
|
|
@@ -41,7 +42,7 @@ async function runInRouteHandlerRevalidationContext(options, renderFn) {
|
|
|
41
42
|
executionContext: getRequestExecutionContext(),
|
|
42
43
|
unstableCacheRevalidation: "foreground"
|
|
43
44
|
});
|
|
44
|
-
const revalidation = runWithRequestContext(requestContext, async () => {
|
|
45
|
+
const revalidation = runWithRequestContext(requestContext, () => runInWorkStoreScope(async () => {
|
|
45
46
|
ensureFetchPatch();
|
|
46
47
|
setCurrentFetchSoftTags(buildRouteHandlerPageCacheTags(options.cleanPathname, [], options.routeSegments));
|
|
47
48
|
setCurrentFetchCacheMode(options.fetchCacheMode);
|
|
@@ -52,7 +53,7 @@ async function runInRouteHandlerRevalidationContext(options, renderFn) {
|
|
|
52
53
|
} finally {
|
|
53
54
|
await _drainPendingRevalidations();
|
|
54
55
|
}
|
|
55
|
-
});
|
|
56
|
+
}));
|
|
56
57
|
try {
|
|
57
58
|
await revalidation;
|
|
58
59
|
} finally {
|
|
@@ -122,6 +123,7 @@ async function dispatchAppRouteHandlerImpl(options) {
|
|
|
122
123
|
handlerFn: resolvedHandlerFn,
|
|
123
124
|
i18n: options.i18n,
|
|
124
125
|
trailingSlash: options.trailingSlash,
|
|
126
|
+
skipTrailingSlashRedirect: options.skipTrailingSlashRedirect,
|
|
125
127
|
isAutoHead,
|
|
126
128
|
appendResponseLink,
|
|
127
129
|
isrDebug: options.isrDebug,
|
|
@@ -184,6 +186,7 @@ async function dispatchAppRouteHandlerImpl(options) {
|
|
|
184
186
|
handlerFn: resolvedHandlerFn,
|
|
185
187
|
i18n: options.i18n,
|
|
186
188
|
trailingSlash: options.trailingSlash,
|
|
189
|
+
skipTrailingSlashRedirect: options.skipTrailingSlashRedirect,
|
|
187
190
|
isAutoHead,
|
|
188
191
|
initialDraftModeCookie,
|
|
189
192
|
isDraftMode,
|
|
@@ -47,6 +47,7 @@ type RunAppRouteHandlerOptions = {
|
|
|
47
47
|
i18n?: NextI18nConfig | null;
|
|
48
48
|
isDraftMode?: boolean;
|
|
49
49
|
trailingSlash?: boolean;
|
|
50
|
+
skipTrailingSlashRedirect?: boolean;
|
|
50
51
|
markDynamicUsage: MarkAppRouteDynamicUsageFn;
|
|
51
52
|
middlewareRequestHeaders?: Headers | null;
|
|
52
53
|
/**
|
|
@@ -112,6 +112,7 @@ async function runAppRouteHandler(options) {
|
|
|
112
112
|
basePath: options.basePath,
|
|
113
113
|
i18n: options.i18n,
|
|
114
114
|
trailingSlash: options.trailingSlash,
|
|
115
|
+
skipTrailingSlashRedirect: options.skipTrailingSlashRedirect,
|
|
115
116
|
middlewareHeaders: options.middlewareRequestHeaders,
|
|
116
117
|
onDynamicAccess() {
|
|
117
118
|
options.markDynamicUsage();
|
|
@@ -17,13 +17,16 @@ export declare function buildRouteHandlerAllowHeader(exportedMethods: readonly s
|
|
|
17
17
|
export declare function isKnownDynamicAppRoute(pattern: string): boolean;
|
|
18
18
|
export declare function markKnownDynamicAppRoute(pattern: string): void;
|
|
19
19
|
type RequestDynamicAccess = "request.headers" | "request.cookies" | "request.cf" | "request.ip" | "request.geo" | "request.url" | "request.body" | "request.blob" | "request.bytes" | "request.json" | "request.text" | "request.arrayBuffer" | "request.formData";
|
|
20
|
-
type NextUrlDynamicAccess = "nextUrl.search" | "nextUrl.searchParams" | "nextUrl.url" | "nextUrl.href" | "nextUrl.toJSON" | "nextUrl.toString" | "nextUrl.origin";
|
|
20
|
+
type NextUrlDynamicAccess = "nextUrl.search" | "nextUrl.searchParams" | "nextUrl.url" | "nextUrl.href" | "nextUrl.toJSON" | "nextUrl.toString" | "nextUrl.origin" | HostDerivedNextUrlDynamicAccess;
|
|
21
|
+
type HostDerivedNextUrlDynamicAccess = "nextUrl.protocol" | "nextUrl.username" | "nextUrl.password" | "nextUrl.host" | "nextUrl.hostname" | "nextUrl.port" | DomainLocaleNextUrlDynamicAccess;
|
|
22
|
+
type DomainLocaleNextUrlDynamicAccess = "nextUrl.locale" | "nextUrl.defaultLocale" | "nextUrl.domainLocale";
|
|
21
23
|
type AppRouteDynamicRequestAccess = RequestDynamicAccess | NextUrlDynamicAccess;
|
|
22
24
|
type AppRouteRequestMode = "auto" | "force-static" | "error";
|
|
23
25
|
type TrackedAppRouteRequestOptions = {
|
|
24
26
|
basePath?: string;
|
|
25
27
|
i18n?: NextI18nConfig | null;
|
|
26
28
|
trailingSlash?: boolean;
|
|
29
|
+
skipTrailingSlashRedirect?: boolean;
|
|
27
30
|
middlewareHeaders?: Headers | null;
|
|
28
31
|
onDynamicAccess?: (access: AppRouteDynamicRequestAccess) => void;
|
|
29
32
|
requestMode?: AppRouteRequestMode;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { buildRequestHeadersFromMiddlewareResponse } from "../utils/middleware-request-headers.js";
|
|
2
2
|
import { addBasePathToPathname } from "../utils/base-path.js";
|
|
3
|
-
import { NextRequest, RequestCookies, sealRequestCookies, sealRequestHeaders } from "../shims/server.js";
|
|
4
3
|
import { cloneRequestWithHeaders, cloneRequestWithUrl } from "./request-pipeline.js";
|
|
4
|
+
import { NextRequest, RequestCookies, sealRequestCookies, sealRequestHeaders } from "../shims/server.js";
|
|
5
5
|
import { BUILT_IN_REQUEST_PROPERTIES } from "./app-route-request-built-ins.js";
|
|
6
6
|
//#region src/server/app-route-handler-runtime.ts
|
|
7
7
|
const BUILT_IN_REQUEST_PROPERTY_MAP = new Map(BUILT_IN_REQUEST_PROPERTIES.map((property) => [property.key, property]));
|
|
@@ -64,11 +64,12 @@ function getRequestProperty(target, prop, receiver, builtInProperties) {
|
|
|
64
64
|
return bindMethodIfNeeded(Reflect.get(target, prop, bindingTarget), bindingTarget);
|
|
65
65
|
}
|
|
66
66
|
function buildNextConfig(options) {
|
|
67
|
-
if (!options.basePath && !options.i18n && !options.trailingSlash) return null;
|
|
67
|
+
if (!options.basePath && !options.i18n && !options.trailingSlash && !options.skipTrailingSlashRedirect) return null;
|
|
68
68
|
return {
|
|
69
69
|
basePath: options.basePath,
|
|
70
70
|
i18n: options.i18n ?? void 0,
|
|
71
|
-
trailingSlash: options.trailingSlash
|
|
71
|
+
trailingSlash: options.trailingSlash,
|
|
72
|
+
skipTrailingSlashRedirect: options.skipTrailingSlashRedirect
|
|
72
73
|
};
|
|
73
74
|
}
|
|
74
75
|
function createForceStaticNextRequest(input, nextConfig) {
|
|
@@ -128,21 +129,41 @@ function createTrackedAppRouteRequest(request, options = {}) {
|
|
|
128
129
|
didAccessDynamicRequest = true;
|
|
129
130
|
options.onDynamicAccess?.(access);
|
|
130
131
|
};
|
|
132
|
+
const isNextDynamicNextUrlProperty = (prop) => {
|
|
133
|
+
switch (prop) {
|
|
134
|
+
case "search":
|
|
135
|
+
case "searchParams":
|
|
136
|
+
case "url":
|
|
137
|
+
case "href":
|
|
138
|
+
case "toJSON":
|
|
139
|
+
case "toString":
|
|
140
|
+
case "origin": return true;
|
|
141
|
+
default: return false;
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
const hasI18nDomains = (options.i18n?.domains?.length ?? 0) > 0;
|
|
145
|
+
const isHostDerivedNextUrlProperty = (prop) => {
|
|
146
|
+
switch (prop) {
|
|
147
|
+
case "protocol":
|
|
148
|
+
case "username":
|
|
149
|
+
case "password":
|
|
150
|
+
case "host":
|
|
151
|
+
case "hostname":
|
|
152
|
+
case "port": return true;
|
|
153
|
+
case "locale":
|
|
154
|
+
case "defaultLocale":
|
|
155
|
+
case "domainLocale": return hasI18nDomains;
|
|
156
|
+
default: return false;
|
|
157
|
+
}
|
|
158
|
+
};
|
|
131
159
|
const wrapNextUrl = (nextUrl) => {
|
|
132
160
|
return new Proxy(nextUrl, { get(target, prop) {
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
case "url":
|
|
137
|
-
case "href":
|
|
138
|
-
case "toJSON":
|
|
139
|
-
case "toString":
|
|
140
|
-
case "origin":
|
|
141
|
-
markDynamicAccess(`nextUrl.${String(prop)}`);
|
|
142
|
-
return bindMethodIfNeeded(Reflect.get(target, prop, target), target);
|
|
143
|
-
case "clone": return () => wrapNextUrl(target.clone());
|
|
144
|
-
default: return bindMethodIfNeeded(Reflect.get(target, prop, target), target);
|
|
161
|
+
if (isNextDynamicNextUrlProperty(prop) || isHostDerivedNextUrlProperty(prop)) {
|
|
162
|
+
markDynamicAccess(`nextUrl.${String(prop)}`);
|
|
163
|
+
return bindMethodIfNeeded(Reflect.get(target, prop, target), target);
|
|
145
164
|
}
|
|
165
|
+
if (prop === "clone") return () => wrapNextUrl(target.clone());
|
|
166
|
+
return bindMethodIfNeeded(Reflect.get(target, prop, target), target);
|
|
146
167
|
} });
|
|
147
168
|
};
|
|
148
169
|
const wrapForceStaticNextUrl = (nextUrl) => {
|
|
@@ -165,18 +186,18 @@ function createTrackedAppRouteRequest(request, options = {}) {
|
|
|
165
186
|
throw new Error(options.staticGenerationErrorMessage?.(expression) ?? `Route handler with \`dynamic = "error"\` used ${expression}.`);
|
|
166
187
|
};
|
|
167
188
|
const wrapRequireStaticNextUrl = (nextUrl) => {
|
|
189
|
+
let staticNextUrl = null;
|
|
168
190
|
return new Proxy(nextUrl, { get(target, prop) {
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
case "origin": return throwStaticGenerationError(`nextUrl.${String(prop)}`);
|
|
177
|
-
case "clone": return () => wrapRequireStaticNextUrl(target.clone());
|
|
178
|
-
default: return bindMethodIfNeeded(Reflect.get(target, prop, target), target);
|
|
191
|
+
if (isNextDynamicNextUrlProperty(prop)) return throwStaticGenerationError(`nextUrl.${String(prop)}`);
|
|
192
|
+
if (isHostDerivedNextUrlProperty(prop)) {
|
|
193
|
+
if (staticNextUrl === null) {
|
|
194
|
+
staticNextUrl = target.clone();
|
|
195
|
+
staticNextUrl.href = cleanStaticUrl(target.href);
|
|
196
|
+
}
|
|
197
|
+
return Reflect.get(staticNextUrl, prop, staticNextUrl);
|
|
179
198
|
}
|
|
199
|
+
if (prop === "clone") return () => wrapRequireStaticNextUrl(target.clone());
|
|
200
|
+
return bindMethodIfNeeded(Reflect.get(target, prop, target), target);
|
|
180
201
|
} });
|
|
181
202
|
};
|
|
182
203
|
const wrapRequest = (rawInput) => {
|
|
@@ -1,24 +1,26 @@
|
|
|
1
1
|
import { VINEXT_PRERENDER_ROUTE_PARAMS_HEADER, VINEXT_PRERENDER_SECRET_HEADER, VINEXT_REVALIDATE_HOST_HEADER } from "../utils/protocol-headers.js";
|
|
2
|
-
import { assetPrefixPathname, isNextStaticPath } from "../utils/asset-prefix.js";
|
|
3
|
-
import { runWithExecutionContext } from "../shims/request-context.js";
|
|
4
|
-
import "./server-globals.js";
|
|
5
2
|
import "./app-rsc-vary.js";
|
|
6
3
|
import { VINEXT_CACHEABILITY_PROBE_QUERY_PARAM } from "./headers.js";
|
|
7
4
|
import { badRequestResponse, notFoundResponse, notFoundStaticAssetResponse } from "./http-error-responses.js";
|
|
8
|
-
import { cloneRequestWithHeaders, filterInternalHeaders, guardProtocolRelativeUrl } from "./request-pipeline.js";
|
|
5
|
+
import { cloneRequestWithHeaders, cloneRequestWithUrl, filterInternalHeaders, guardProtocolRelativeUrl } from "./request-pipeline.js";
|
|
6
|
+
import { assetPrefixPathname, isNextStaticPath } from "../utils/asset-prefix.js";
|
|
7
|
+
import { runWithExecutionContext } from "../shims/request-context.js";
|
|
8
|
+
import "./server-globals.js";
|
|
9
9
|
import { getCdnCacheAdapter } from "../shims/cdn-cache.js";
|
|
10
10
|
import { applyCdnResponseIdentityHeaders, validateCdnRequest } from "./cache-control.js";
|
|
11
|
-
import { getImageOptimizer,
|
|
11
|
+
import { getImageOptimizer, readImageOptimizationSignal } from "./image-optimization.js";
|
|
12
12
|
import { traceFrameworkRequest } from "./request-tracing.js";
|
|
13
13
|
import { createStaticAssetRequest, resolveStaticAssetSignal } from "./worker-utils.js";
|
|
14
14
|
import { readTrustedPrerenderRouteParams, serializePrerenderRouteParamsHeader } from "./prerender-route-params.js";
|
|
15
|
+
import { resolveClientBuildFile } from "./client-build-files.js";
|
|
15
16
|
import { createWorkerRevalidationContext } from "./worker-revalidation-context.js";
|
|
16
17
|
import { createWorkerPrerenderDiscoveryContext, createWorkerPrerenderReadinessResponse } from "./worker-prerender-discovery.js";
|
|
17
18
|
import { registerConfiguredImageOptimizer } from "virtual:vinext-image-adapters";
|
|
18
19
|
import { registerConfiguredCacheAdapters } from "virtual:vinext-cache-adapters";
|
|
19
|
-
import rscHandler, { __assetPrefix, __basePath, __cacheabilityManifest, __ensureHybridPagesApplication, __ensureInstrumentation, __imageAllowedWidths, __imageConfig, __prerenderSecret } from "virtual:vinext-rsc-entry";
|
|
20
|
+
import rscHandler, { __assetPrefix, __basePath, __cacheabilityManifest, __clientBuildFiles, __ensureHybridPagesApplication, __ensureInstrumentation, __imageAllowedWidths, __imageConfig, __prerenderSecret } from "virtual:vinext-rsc-entry";
|
|
20
21
|
//#region src/server/app-router-entry.ts
|
|
21
22
|
const __workerBasePath = typeof __basePath === "string" ? __basePath : "";
|
|
23
|
+
const __workerClientBuildFiles = new Set(Array.isArray(__clientBuildFiles) ? __clientBuildFiles : []);
|
|
22
24
|
const __workerAssetPathPrefix = assetPrefixPathname(typeof __assetPrefix === "string" ? __assetPrefix : "");
|
|
23
25
|
function isPotentialCompletedAdmissionRequest(request) {
|
|
24
26
|
if (request.method !== "GET" && request.method !== "HEAD") return false;
|
|
@@ -64,7 +66,7 @@ async function handleRequest(request, env, platformCtx) {
|
|
|
64
66
|
const probeUrl = new URL(request.url);
|
|
65
67
|
if (probeUrl.searchParams.has("__vinext_cacheability_probe")) {
|
|
66
68
|
probeUrl.searchParams.delete(VINEXT_CACHEABILITY_PROBE_QUERY_PARAM);
|
|
67
|
-
request =
|
|
69
|
+
request = cloneRequestWithUrl(request, probeUrl.href);
|
|
68
70
|
}
|
|
69
71
|
}
|
|
70
72
|
}
|
|
@@ -81,7 +83,7 @@ async function handleRequest(request, env, platformCtx) {
|
|
|
81
83
|
const cdnValidationResponse = await validateCdnRequest(request);
|
|
82
84
|
if (cdnValidationResponse) return cdnValidationResponse;
|
|
83
85
|
const url = new URL(request.url);
|
|
84
|
-
|
|
86
|
+
const servesImages = Boolean(assets) && getImageOptimizer() !== null;
|
|
85
87
|
const protocolRelativeGuard = guardProtocolRelativeUrl(url.pathname, url.search);
|
|
86
88
|
if (protocolRelativeGuard) return protocolRelativeGuard;
|
|
87
89
|
try {
|
|
@@ -89,6 +91,10 @@ async function handleRequest(request, env, platformCtx) {
|
|
|
89
91
|
} catch {
|
|
90
92
|
return badRequestResponse();
|
|
91
93
|
}
|
|
94
|
+
if (assets && (request.method === "GET" || request.method === "HEAD")) {
|
|
95
|
+
const clientBuildFile = resolveClientBuildFile(url.pathname, __workerBasePath, __workerClientBuildFiles);
|
|
96
|
+
if (clientBuildFile) return await assets.fetch(createStaticAssetRequest(clientBuildFile, request));
|
|
97
|
+
}
|
|
92
98
|
const missingBuildAsset = isNextStaticPath(url.pathname, __workerBasePath, __workerAssetPathPrefix);
|
|
93
99
|
{
|
|
94
100
|
const trustedPrerenderRouteParams = ctx.hostRuntime === "node" ? readTrustedPrerenderRouteParams(request) : null;
|
|
@@ -103,8 +109,21 @@ async function handleRequest(request, env, platformCtx) {
|
|
|
103
109
|
const result = await (ctx ? runWithExecutionContext(ctx, handleFn) : handleFn());
|
|
104
110
|
if (result instanceof Response) {
|
|
105
111
|
let response = result;
|
|
106
|
-
|
|
107
|
-
|
|
112
|
+
const imageSignal = servesImages ? readImageOptimizationSignal(response) : null;
|
|
113
|
+
if (imageSignal && assets) {
|
|
114
|
+
const { fetchSignalledPublicFile, serveWorkerImageOptimization } = await import("./worker-image-optimization.js");
|
|
115
|
+
response = await serveWorkerImageOptimization(request, imageSignal, __imageAllowedWidths, __imageConfig, {
|
|
116
|
+
assets,
|
|
117
|
+
basePath: __workerBasePath,
|
|
118
|
+
assetPathPrefix: __workerAssetPathPrefix,
|
|
119
|
+
clientBuildFiles: __workerClientBuildFiles,
|
|
120
|
+
fetchPublicFile: async (sourceRequest) => {
|
|
121
|
+
const sourceResult = await runWithExecutionContext(requestCtx, () => rscHandler(sourceRequest, requestCtx));
|
|
122
|
+
return sourceResult instanceof Response ? fetchSignalledPublicFile(sourceResult, sourceRequest, assets) : null;
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
} else if (assets) {
|
|
126
|
+
const assetResponse = await resolveStaticAssetSignal(response, { fetchAsset: (path, requestHeaders) => Promise.resolve(assets.fetch(createStaticAssetRequest(path, request, requestHeaders))) });
|
|
108
127
|
if (assetResponse) response = assetResponse;
|
|
109
128
|
}
|
|
110
129
|
return finalizeCacheabilityResponse ? finalizeCacheabilityResponse(response, ctx) : response;
|
|
@@ -89,6 +89,22 @@ export declare function canonicalizePrewarmableRscRequestHeaders(headers: Header
|
|
|
89
89
|
* router state is transport context and must not fragment the shared response.
|
|
90
90
|
*/
|
|
91
91
|
export declare function canonicalizeLoadingShellRscRequestHeaders(headers: Headers): boolean;
|
|
92
|
+
/**
|
|
93
|
+
* Callers pass a path (usually a parsed URL's pathname + search) or an
|
|
94
|
+
* absolute URL. A pathname can begin with "//", and resolving that as a
|
|
95
|
+
* relative reference would read its first segment as a host, so a path is
|
|
96
|
+
* appended to the base instead of resolved against it.
|
|
97
|
+
*/
|
|
98
|
+
export declare function parseRscRequestPath(href: string): URL;
|
|
99
|
+
/**
|
|
100
|
+
* Serialize the path-absolute reference callers fetch against the app origin.
|
|
101
|
+
* A pathname that begins with "//" would serialize as a protocol-relative URL
|
|
102
|
+
* and send the request to another host, so it keeps a "/." prefix, as the
|
|
103
|
+
* WHATWG URL serializer does. URL resolution drops the dot segment, so the
|
|
104
|
+
* request still targets the same pathname on the app origin, as Next.js's
|
|
105
|
+
* full-URL fetch does.
|
|
106
|
+
*/
|
|
107
|
+
export declare function formatRscRequestPath(url: URL): string;
|
|
92
108
|
export declare function createRscRequestUrl(href: string, headers: Headers): Promise<string>;
|
|
93
109
|
/** Build the definitive full-route RSC URL shared by prefetch and navigation. */
|
|
94
110
|
export declare function createCanonicalRscRequestUrl(href: string): string;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { NEXT_ROUTER_PREFETCH_HEADER, NEXT_ROUTER_SEGMENT_PREFETCH_HEADER, NEXT_ROUTER_STATE_TREE_HEADER, NEXT_URL_HEADER, VINEXT_INTERCEPTION_CONTEXT_HEADER, VINEXT_INTERCEPTION_ID_HEADER, VINEXT_MOUNTED_SLOTS_HEADER, VINEXT_RSC_RENDER_MODE_HEADER, VINEXT_RSC_STATE_FINGERPRINT_HEADER, VINEXT_RSC_VARY_HEADER } from "./app-rsc-vary.js";
|
|
2
2
|
import { NEXTJS_DEPLOYMENT_ID_HEADER, VINEXT_CLIENT_REUSE_MANIFEST_HEADER } from "./headers.js";
|
|
3
|
-
import { fnv1a64 } from "../utils/hash.js";
|
|
4
3
|
import { APP_RSC_RENDER_MODE_PREFETCH_LOADING_SHELL, parseAppRscRenderMode } from "./app-rsc-render-mode.js";
|
|
4
|
+
import { fnv1a64 } from "../utils/hash.js";
|
|
5
5
|
import { applyDeploymentIdHeader, getDeploymentId } from "../utils/deployment-id.js";
|
|
6
6
|
import { createAppRscStateFingerprint } from "./app-rsc-state-fingerprint.js";
|
|
7
7
|
//#region src/server/app-rsc-cache-busting.ts
|
|
@@ -218,33 +218,50 @@ function canonicalizeLoadingShellRscRequestHeaders(headers) {
|
|
|
218
218
|
headers.delete(VINEXT_CLIENT_REUSE_MANIFEST_HEADER);
|
|
219
219
|
return true;
|
|
220
220
|
}
|
|
221
|
-
|
|
221
|
+
const RSC_REQUEST_URL_BASE = "http://vinext.local";
|
|
222
|
+
/**
|
|
223
|
+
* Callers pass a path (usually a parsed URL's pathname + search) or an
|
|
224
|
+
* absolute URL. A pathname can begin with "//", and resolving that as a
|
|
225
|
+
* relative reference would read its first segment as a host, so a path is
|
|
226
|
+
* appended to the base instead of resolved against it.
|
|
227
|
+
*/
|
|
228
|
+
function parseRscRequestPath(href) {
|
|
222
229
|
const hashIndex = href.indexOf("#");
|
|
223
|
-
|
|
230
|
+
const beforeHash = hashIndex === -1 ? href : href.slice(0, hashIndex);
|
|
231
|
+
if (beforeHash.startsWith("/") || beforeHash.startsWith("\\")) return new URL(`${RSC_REQUEST_URL_BASE}${beforeHash}`);
|
|
232
|
+
return new URL(beforeHash, RSC_REQUEST_URL_BASE);
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Serialize the path-absolute reference callers fetch against the app origin.
|
|
236
|
+
* A pathname that begins with "//" would serialize as a protocol-relative URL
|
|
237
|
+
* and send the request to another host, so it keeps a "/." prefix, as the
|
|
238
|
+
* WHATWG URL serializer does. URL resolution drops the dot segment, so the
|
|
239
|
+
* request still targets the same pathname on the app origin, as Next.js's
|
|
240
|
+
* full-URL fetch does.
|
|
241
|
+
*/
|
|
242
|
+
function formatRscRequestPath(url) {
|
|
243
|
+
return `${url.pathname.startsWith("//") ? `/.${url.pathname}` : url.pathname}${url.search}`;
|
|
224
244
|
}
|
|
225
245
|
async function createRscRequestUrl(href, headers) {
|
|
226
|
-
const url =
|
|
246
|
+
const url = parseRscRequestPath(href);
|
|
227
247
|
if (typeof window !== "undefined" && process.env.NODE_ENV === "production" && process.env.__NEXT_CONFIG_OUTPUT === "export") {
|
|
228
248
|
const basePath = process.env.__NEXT_ROUTER_BASEPATH ?? "";
|
|
229
249
|
const isBasePathRoot = basePath !== "" && url.pathname === basePath;
|
|
230
250
|
if (url.pathname.endsWith("/")) url.pathname += "index.txt";
|
|
231
251
|
else url.pathname += isBasePathRoot ? "/index.txt" : ".txt";
|
|
232
|
-
return
|
|
252
|
+
return formatRscRequestPath(url);
|
|
233
253
|
}
|
|
234
254
|
setRscCacheBustingSearchParam(url, await computeRscCacheBustingSearchParam(headers));
|
|
235
|
-
return
|
|
255
|
+
return formatRscRequestPath(url);
|
|
236
256
|
}
|
|
237
257
|
/** Build the definitive full-route RSC URL shared by prefetch and navigation. */
|
|
238
258
|
function createCanonicalRscRequestUrl(href) {
|
|
239
|
-
const url =
|
|
259
|
+
const url = parseRscRequestPath(href);
|
|
240
260
|
setRscCacheBustingSearchParam(url, "");
|
|
241
|
-
return
|
|
261
|
+
return formatRscRequestPath(url);
|
|
242
262
|
}
|
|
243
263
|
function createServerActionRequestUrl(href) {
|
|
244
|
-
|
|
245
|
-
const beforeHash = hashIndex === -1 ? href : href.slice(0, hashIndex);
|
|
246
|
-
const url = new URL(beforeHash, "http://vinext.local");
|
|
247
|
-
return `${url.pathname}${url.search}`;
|
|
264
|
+
return formatRscRequestPath(parseRscRequestPath(href));
|
|
248
265
|
}
|
|
249
266
|
async function createRscRedirectLocation(location, request) {
|
|
250
267
|
const requestUrl = new URL(request.url);
|
|
@@ -309,4 +326,4 @@ async function resolveInvalidRscCacheBustingRequest(options) {
|
|
|
309
326
|
});
|
|
310
327
|
}
|
|
311
328
|
//#endregion
|
|
312
|
-
export { VINEXT_RSC_BUILD_ID_HEADER, VINEXT_RSC_CACHE_BUSTING_SEARCH_PARAM, VINEXT_RSC_COMPATIBILITY_ID_HEADER, VINEXT_RSC_CONTENT_TYPE, VINEXT_RSC_RENDER_MODE_HEADER, VINEXT_RSC_VARY_HEADER, applyRscCompatibilityIdHeader, applyRscDeploymentIdHeader, canonicalizeLoadingShellRscRequestHeaders, canonicalizePrewarmableRscRequestHeaders, computeRscCacheBustingSearchParam, createCanonicalLoadingShellRscRequestHeaders, createCanonicalRscRequestHeaders, createCanonicalRscRequestUrl, createRscRedirectLocation, createRscRequestHeaders, createRscRequestUrl, createServerActionRequestUrl, getVinextRscCompatibilityId, hasRscCacheBustingSearchParam, isRscCompatibilityIdCompatible, keepOnlyValidatedRscCacheBustingSearchParam, resolveHardNavigationTargetFromRscResponse, resolveInvalidRscCacheBustingRequest, resolveRscCompatibilityNavigationDecision, setRscCacheBustingSearchParam, stripRscCacheBustingSearchParam, stripRscSuffix };
|
|
329
|
+
export { VINEXT_RSC_BUILD_ID_HEADER, VINEXT_RSC_CACHE_BUSTING_SEARCH_PARAM, VINEXT_RSC_COMPATIBILITY_ID_HEADER, VINEXT_RSC_CONTENT_TYPE, VINEXT_RSC_RENDER_MODE_HEADER, VINEXT_RSC_VARY_HEADER, applyRscCompatibilityIdHeader, applyRscDeploymentIdHeader, canonicalizeLoadingShellRscRequestHeaders, canonicalizePrewarmableRscRequestHeaders, computeRscCacheBustingSearchParam, createCanonicalLoadingShellRscRequestHeaders, createCanonicalRscRequestHeaders, createCanonicalRscRequestUrl, createRscRedirectLocation, createRscRequestHeaders, createRscRequestUrl, createServerActionRequestUrl, formatRscRequestPath, getVinextRscCompatibilityId, hasRscCacheBustingSearchParam, isRscCompatibilityIdCompatible, keepOnlyValidatedRscCacheBustingSearchParam, parseRscRequestPath, resolveHardNavigationTargetFromRscResponse, resolveInvalidRscCacheBustingRequest, resolveRscCompatibilityNavigationDecision, setRscCacheBustingSearchParam, stripRscCacheBustingSearchParam, stripRscSuffix };
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { isNavigationSignalError } from "../utils/navigation-signal.js";
|
|
2
2
|
import { resolveAppPageSpecialError } from "./app-page-execution.js";
|
|
3
3
|
import { isAppRenderAbortError } from "./app-render-abort-error.js";
|
|
4
|
+
import { getProperError } from "./proper-error.js";
|
|
4
5
|
//#region src/server/app-rsc-errors.ts
|
|
5
6
|
const ORIGINAL_SERVER_ERROR = Symbol.for("vinext.originalServerError");
|
|
6
7
|
function hasDigest(error) {
|
|
@@ -23,11 +24,14 @@ function getDigestForWellKnownError(error) {
|
|
|
23
24
|
const digest = String(error.digest);
|
|
24
25
|
if (isNavigationSignalError(error) || digest === BAILOUT_TO_CSR_DIGEST || digest === DYNAMIC_SERVER_USAGE_DIGEST) return digest;
|
|
25
26
|
}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
27
|
+
/**
|
|
28
|
+
* Next.js hashes a thrown string as is, and other values once they are an
|
|
29
|
+
* Error (packages/next/src/server/app-render/create-error-handler.tsx).
|
|
30
|
+
*/
|
|
31
|
+
function getThrownValueDigest(error) {
|
|
32
|
+
if (typeof error === "string") return errorDigest(error);
|
|
33
|
+
const properError = getProperError(error);
|
|
34
|
+
return errorDigest(properError.message + (properError.stack || ""));
|
|
31
35
|
}
|
|
32
36
|
/**
|
|
33
37
|
* djb2 hash matching Next.js's string-hash package for RSC error digests.
|
|
@@ -41,7 +45,7 @@ function sanitizeErrorForClient(error, nodeEnv = process.env.NODE_ENV) {
|
|
|
41
45
|
if (resolveAppPageSpecialError(error)) return error;
|
|
42
46
|
if (nodeEnv !== "production") return error;
|
|
43
47
|
const sanitized = /* @__PURE__ */ new Error("An error occurred in the Server Components render. The specific message is omitted in production builds to avoid leaking sensitive details. A digest property is included on this error instance which may provide additional details about the nature of the error.");
|
|
44
|
-
sanitized.digest = hasDigest(error) ? String(error.digest) :
|
|
48
|
+
sanitized.digest = hasDigest(error) ? String(error.digest) : getThrownValueDigest(error);
|
|
45
49
|
Object.defineProperty(sanitized, ORIGINAL_SERVER_ERROR, {
|
|
46
50
|
configurable: false,
|
|
47
51
|
enumerable: false,
|
|
@@ -55,6 +59,7 @@ function createRscOnErrorHandler(options) {
|
|
|
55
59
|
return (error) => {
|
|
56
60
|
const nodeEnv = options.nodeEnv ?? process.env.NODE_ENV;
|
|
57
61
|
const reportableError = error && typeof error === "object" && ORIGINAL_SERVER_ERROR in error ? Reflect.get(error, ORIGINAL_SERVER_ERROR) : error;
|
|
62
|
+
if (typeof reportableError === "string") return hasDigest(error) ? String(error.digest) : errorDigest(reportableError);
|
|
58
63
|
if (isAppRenderAbortError(error) || isAppRenderAbortError(reportableError)) return;
|
|
59
64
|
const wellKnownDigest = getDigestForWellKnownError(error) ?? getDigestForWellKnownError(reportableError);
|
|
60
65
|
if (wellKnownDigest !== void 0) return wellKnownDigest;
|
|
@@ -62,22 +67,21 @@ function createRscOnErrorHandler(options) {
|
|
|
62
67
|
console.error("[vinext] RSC serialization error: a non-plain object was passed from a Server Component to a Client Component.\n\nCommon causes:\n * Passing a module namespace (import * as X) directly as a prop.\n Unlike Next.js (webpack), Vite produces real ESM module namespace objects\n which are not serializable. Fix: pass individual values instead,\n e.g. <Comp value={module.value} />\n * Passing a class instance (new Foo()) as a prop.\n Fix: convert to a plain object, e.g. { id: foo.id, name: foo.name }\n * Passing a Date, Map, or Set. Use .toISOString(), [...map.entries()], etc.\n * Passing Object.create(null). Use { ...obj } to restore a prototype.\n\nOriginal error:", error.message);
|
|
63
68
|
return;
|
|
64
69
|
}
|
|
65
|
-
|
|
70
|
+
const thrownHasDigest = hasDigest(error);
|
|
71
|
+
const properError = getProperError(reportableError);
|
|
72
|
+
const digest = thrownHasDigest ? String(error.digest) : errorDigest(properError.message + (properError.stack || ""));
|
|
73
|
+
if (!hasDigest(properError) && (properError !== reportableError || options.attachDigest !== false)) try {
|
|
74
|
+
Object.assign(properError, { digest });
|
|
75
|
+
} catch {}
|
|
76
|
+
if (options.requestInfo && options.errorContext) options.reportRequestError(properError, options.requestInfo, options.errorContext);
|
|
66
77
|
if (process.env.VINEXT_PRERENDER === "1" && error) {
|
|
67
78
|
if (!loggedPrerenderErrors?.has(reportableError)) {
|
|
68
79
|
(loggedPrerenderErrors ??= /* @__PURE__ */ new Set()).add(reportableError);
|
|
69
80
|
const route = options.requestInfo?.path ?? options.errorContext?.routePath ?? "<unknown>";
|
|
70
81
|
console.error(`[vinext] Error prerendering route ${JSON.stringify(route)}:`, reportableError);
|
|
71
82
|
}
|
|
72
|
-
} else if (nodeEnv !== "production" &&
|
|
73
|
-
|
|
74
|
-
if (error) {
|
|
75
|
-
const digest = errorDigest(getThrownValueMessage(error) + getThrownValueStack(error));
|
|
76
|
-
if (options.attachDigest !== false && error instanceof Error) try {
|
|
77
|
-
Object.assign(error, { digest });
|
|
78
|
-
} catch {}
|
|
79
|
-
return digest;
|
|
80
|
-
}
|
|
83
|
+
} else if (nodeEnv !== "production" && !thrownHasDigest) console.error("[vinext] Server render error:", properError);
|
|
84
|
+
return digest;
|
|
81
85
|
};
|
|
82
86
|
}
|
|
83
87
|
//#endregion
|
|
@@ -204,6 +204,11 @@ export type CreateAppRscHandlerOptions<TRoute extends AppRscHandlerRoute> = {
|
|
|
204
204
|
fallback: NextRewrite[];
|
|
205
205
|
};
|
|
206
206
|
draftModeSecret: string;
|
|
207
|
+
/**
|
|
208
|
+
* Dev-only key the hybrid Pages handler seals x-vinext-mw-ctx with. Null
|
|
209
|
+
* outside `vite dev`, so a forwarded middleware context is never honored.
|
|
210
|
+
*/
|
|
211
|
+
devForwardedMiddlewareContextKey?: string | null;
|
|
207
212
|
dispatchMatchedPage: (options: DispatchMatchedPageOptions<TRoute>) => Promise<Response>;
|
|
208
213
|
dispatchMatchedRouteHandler: (options: DispatchMatchedRouteHandlerOptions<TRoute>) => Promise<Response>;
|
|
209
214
|
/**
|
|
@@ -246,6 +251,8 @@ export type CreateAppRscHandlerOptions<TRoute extends AppRscHandlerRoute> = {
|
|
|
246
251
|
renderPagesFallback?: (options: RenderPagesFallbackOptions) => Promise<Response | null>;
|
|
247
252
|
rootParamNamesByPattern?: RootParamNamesMap;
|
|
248
253
|
setNavigationContext: (context: NavigationContextValue) => void;
|
|
254
|
+
/** next.config `skipTrailingSlashRedirect`: serve both slash forms without a 308. */
|
|
255
|
+
skipTrailingSlashRedirect?: boolean;
|
|
249
256
|
staticParamsMap: StaticParamsMap;
|
|
250
257
|
trailingSlash: boolean;
|
|
251
258
|
validateDevRequestOrigin?: (request: Request) => Response | null;
|