vinext 1.0.1 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +72 -1
- package/dist/build/app-page-static-eligibility.d.ts +15 -0
- package/dist/build/app-page-static-eligibility.js +82 -0
- package/dist/build/prerender-paths.js +3 -78
- package/dist/build/prerender.js +33 -8
- package/dist/build/server-manifest.d.ts +7 -0
- package/dist/build/server-manifest.js +11 -1
- package/dist/cache/cache-adapters-virtual.d.ts +7 -1
- package/dist/cache/cache-adapters-virtual.js +3 -3
- package/dist/client/navigation-runtime.d.ts +11 -0
- package/dist/client/navigation-runtime.js +1 -1
- package/dist/config/config-matchers.js +3 -1
- package/dist/config/next-config.d.ts +7 -0
- package/dist/config/next-config.js +18 -3
- package/dist/entries/app-rsc-entry.d.ts +2 -0
- package/dist/entries/app-rsc-entry.js +64 -43
- package/dist/index.d.ts +4 -1
- package/dist/index.js +59 -30
- package/dist/plugins/cache-flight-codec.d.ts +19 -0
- package/dist/plugins/cache-flight-codec.js +68 -0
- package/dist/plugins/commonjs-esm-facade.d.ts +35 -0
- package/dist/plugins/commonjs-esm-facade.js +80 -0
- package/dist/plugins/fonts.d.ts +8 -11
- package/dist/plugins/fonts.js +71 -34
- package/dist/routing/file-matcher.d.ts +1 -0
- package/dist/routing/file-matcher.js +1 -1
- package/dist/server/api-handler.js +17 -7
- package/dist/server/app-browser-entry.js +11 -7
- package/dist/server/app-browser-history-controller.d.ts +2 -0
- package/dist/server/app-browser-history-controller.js +8 -0
- package/dist/server/app-browser-interception-context.js +26 -2
- package/dist/server/app-browser-navigation-controller.d.ts +7 -1
- package/dist/server/app-browser-navigation-controller.js +93 -10
- package/dist/server/app-fallback-renderer.d.ts +2 -0
- package/dist/server/app-fallback-renderer.js +1 -0
- package/dist/server/app-history-state.d.ts +3 -0
- package/dist/server/app-history-state.js +7 -0
- package/dist/server/app-middleware.js +2 -1
- package/dist/server/app-optimistic-routing.js +1 -1
- package/dist/server/app-page-boundary-render.d.ts +5 -0
- package/dist/server/app-page-boundary-render.js +6 -4
- package/dist/server/app-page-cache-finalizer.d.ts +11 -0
- package/dist/server/app-page-cache-finalizer.js +41 -7
- package/dist/server/app-page-cache-render.d.ts +18 -0
- package/dist/server/app-page-cache-render.js +63 -43
- package/dist/server/app-page-cache.d.ts +5 -0
- package/dist/server/app-page-cache.js +27 -7
- package/dist/server/app-page-dispatch.d.ts +9 -1
- package/dist/server/app-page-dispatch.js +47 -30
- package/dist/server/app-page-element-builder.d.ts +7 -0
- package/dist/server/app-page-element-builder.js +27 -42
- package/dist/server/app-page-execution.d.ts +15 -12
- package/dist/server/app-page-execution.js +30 -40
- package/dist/server/app-page-head.d.ts +5 -0
- package/dist/server/app-page-head.js +9 -3
- package/dist/server/app-page-probe.d.ts +0 -109
- package/dist/server/app-page-probe.js +3 -136
- package/dist/server/app-page-render-identity.d.ts +0 -1
- package/dist/server/app-page-render-identity.js +1 -1
- package/dist/server/app-page-render-observation.js +2 -2
- package/dist/server/app-page-render.d.ts +13 -5
- package/dist/server/app-page-render.js +219 -119
- package/dist/server/app-page-request.d.ts +0 -1
- package/dist/server/app-page-request.js +1 -2
- package/dist/server/app-page-response.d.ts +4 -3
- package/dist/server/app-page-response.js +4 -3
- package/dist/server/app-page-route-wiring.d.ts +17 -5
- package/dist/server/app-page-route-wiring.js +55 -33
- package/dist/server/app-page-rsc-render-status.d.ts +48 -0
- package/dist/server/app-page-rsc-render-status.js +54 -0
- package/dist/server/app-page-stream.d.ts +15 -8
- package/dist/server/app-page-stream.js +6 -0
- package/dist/server/app-request-stage-dispatch.js +1 -1
- package/dist/server/app-request-stage-independent-entry.js +4 -4
- package/dist/server/app-response-header-provenance.d.ts +2 -0
- package/dist/server/app-response-header-provenance.js +10 -4
- package/dist/server/app-route-handler-dispatch.js +1 -1
- package/dist/server/app-router-entry.js +3 -3
- package/dist/server/app-rsc-handler.d.ts +4 -0
- package/dist/server/app-rsc-handler.js +212 -96
- package/dist/server/app-rsc-request-normalization.d.ts +3 -1
- package/dist/server/app-rsc-request-normalization.js +4 -2
- package/dist/server/app-rsc-response-stage.d.ts +1 -1
- package/dist/server/app-rsc-response-stage.js +6 -4
- package/dist/server/app-rsc-route-matching.d.ts +9 -1
- package/dist/server/app-rsc-route-matching.js +36 -19
- package/dist/server/app-server-action-execution.js +1 -1
- package/dist/server/app-ssr-entry.d.ts +3 -2
- package/dist/server/app-ssr-entry.js +6 -4
- package/dist/server/app-ssr-stream.d.ts +6 -1
- package/dist/server/app-ssr-stream.js +34 -15
- package/dist/server/app-worker-stages.d.ts +2 -2
- package/dist/server/app-worker-stages.js +3 -3
- package/dist/server/cacheability-request.js +9 -5
- package/dist/server/config-headers.js +2 -0
- package/dist/server/dev-server.js +12 -2
- package/dist/server/headers.d.ts +14 -0
- package/dist/server/headers.js +15 -1
- package/dist/server/image-optimization.d.ts +16 -0
- package/dist/server/image-optimization.js +26 -6
- package/dist/server/isr-cache.js +2 -2
- package/dist/server/middleware-matcher-pattern.js +8 -4
- package/dist/server/middleware-response-headers.js +2 -0
- package/dist/server/multi-stage.d.ts +8 -0
- package/dist/server/navigation-planner.js +1 -1
- package/dist/server/node-response-signal.d.ts +16 -0
- package/dist/server/node-response-signal.js +26 -0
- package/dist/server/open-redirect.d.ts +47 -0
- package/dist/server/open-redirect.js +74 -1
- package/dist/server/pages-page-handler.js +21 -4
- package/dist/server/pages-request-stage-entry.js +8 -4
- package/dist/server/prod-server.d.ts +8 -7
- package/dist/server/prod-server.js +153 -69
- package/dist/server/request-pipeline.d.ts +20 -8
- package/dist/server/request-pipeline.js +21 -7
- package/dist/server/response-compression.d.ts +43 -0
- package/dist/server/response-compression.js +111 -0
- package/dist/server/seed-cache.js +10 -7
- package/dist/server/socket-error-backstop.d.ts +14 -0
- package/dist/server/socket-error-backstop.js +27 -4
- package/dist/shims/cache-adapter-instantiate.d.ts +50 -0
- package/dist/shims/cache-adapter-instantiate.js +118 -0
- package/dist/shims/cache-callable-runtime.d.ts +2 -40
- package/dist/shims/cache-callable-runtime.js +50 -168
- package/dist/shims/cache-flight-arguments.d.ts +22 -0
- package/dist/shims/cache-flight-arguments.js +56 -0
- package/dist/shims/cache-request-state.d.ts +15 -0
- package/dist/shims/cache-request-state.js +31 -8
- package/dist/shims/cache-runtime.d.ts +6 -19
- package/dist/shims/cache-runtime.js +165 -225
- package/dist/shims/cache.d.ts +2 -2
- package/dist/shims/cache.js +5 -4
- package/dist/shims/cacheability-classification.d.ts +7 -0
- package/dist/shims/error-boundary-navigation.d.ts +7 -0
- package/dist/shims/error-boundary-navigation.js +19 -1
- package/dist/shims/error-boundary.d.ts +10 -10
- package/dist/shims/error-boundary.js +26 -7
- package/dist/shims/fetch-cache.d.ts +6 -0
- package/dist/shims/fetch-cache.js +19 -1
- package/dist/shims/form.js +1 -1
- package/dist/shims/headers.d.ts +13 -0
- package/dist/shims/headers.js +47 -4
- package/dist/shims/internal/app-page-props-cache-key.d.ts +5 -2
- package/dist/shims/internal/app-page-props-cache-key.js +24 -15
- package/dist/shims/internal/headers-state.d.ts +0 -1
- package/dist/shims/metadata.js +3 -3
- package/dist/shims/navigation-errors.d.ts +6 -0
- package/dist/shims/navigation-errors.js +11 -1
- package/dist/shims/navigation.d.ts +7 -0
- package/dist/shims/navigation.js +14 -4
- package/dist/shims/request-context.d.ts +9 -0
- package/dist/shims/thenable-params.d.ts +4 -0
- package/dist/shims/thenable-params.js +25 -3
- package/dist/shims/unified-request-context.js +1 -0
- package/dist/utils/mdx-scan.d.ts +5 -0
- package/dist/utils/mdx-scan.js +8 -1
- package/dist/utils/regex-safety.d.ts +10 -0
- package/dist/utils/regex-safety.js +70 -18
- package/package.json +3 -3
|
@@ -2,11 +2,12 @@ import { toSlash } from "../deps/.pnpm/pathslash@0.1.0/deps/pathslash/dist/index
|
|
|
2
2
|
import { appRouteHasMainTreeLoadingBoundary } from "../routing/app-router.js";
|
|
3
3
|
import { resolveEntryPath } from "./runtime-entry-module.js";
|
|
4
4
|
import { isProxyFile } from "../server/middleware.js";
|
|
5
|
-
import { extractExportConstString } from "../build/report.js";
|
|
5
|
+
import { extractExportConstString, getAppRouteRenderEntryPath } from "../build/report.js";
|
|
6
6
|
import { routePatternParts } from "../routing/route-pattern.js";
|
|
7
7
|
import { safeJsonStringify } from "../server/html.js";
|
|
8
8
|
import { DEFAULT_DEVICE_SIZES, DEFAULT_IMAGE_SIZES } from "../server/image-optimization.js";
|
|
9
9
|
import { buildAppRscManifestCode } from "./app-rsc-manifest.js";
|
|
10
|
+
import { classifyAppPageRouteStaticEligibility } from "../build/app-page-static-eligibility.js";
|
|
10
11
|
import { generateDevOriginCheckCode } from "../server/dev-origin-check.js";
|
|
11
12
|
import { ACTION_OWNER_MANIFEST_ID } from "../plugins/action-owner-manifest.js";
|
|
12
13
|
import fs from "node:fs";
|
|
@@ -38,7 +39,6 @@ const appPageExecutionPath = resolveEntryPath("../server/app-page-execution.js",
|
|
|
38
39
|
const appFallbackRendererPath = resolveEntryPath("../server/app-fallback-renderer.js", import.meta.url);
|
|
39
40
|
const appElementsPath = resolveEntryPath("../server/app-elements.js", import.meta.url);
|
|
40
41
|
const appPageRouteWiringPath = resolveEntryPath("../server/app-page-route-wiring.js", import.meta.url);
|
|
41
|
-
const appPageProbePath = resolveEntryPath("../server/app-page-probe.js", import.meta.url);
|
|
42
42
|
const appPageDispatchPath = resolveEntryPath("../server/app-page-dispatch.js", import.meta.url);
|
|
43
43
|
const appPagePprRuntimePath = resolveEntryPath("../server/app-page-ppr-runtime.js", import.meta.url);
|
|
44
44
|
const fileBasedMetadataPath = resolveEntryPath("../server/file-based-metadata.js", import.meta.url);
|
|
@@ -63,10 +63,10 @@ const appHookWarningSuppressionPath = resolveEntryPath("../server/app-hook-warni
|
|
|
63
63
|
const serverGlobalsPath = resolveEntryPath("../server/server-globals.js", import.meta.url);
|
|
64
64
|
const appPagesBridgePath = resolveEntryPath("../server/app-pages-bridge.js", import.meta.url);
|
|
65
65
|
const routePatternPath = resolveEntryPath("../routing/route-pattern.js", import.meta.url);
|
|
66
|
-
function
|
|
66
|
+
function createSegmentSourceReader() {
|
|
67
67
|
const sourceCache = /* @__PURE__ */ new Map();
|
|
68
|
-
|
|
69
|
-
if (!filePath) return
|
|
68
|
+
return (filePath) => {
|
|
69
|
+
if (!filePath) return null;
|
|
70
70
|
let source = sourceCache.get(filePath);
|
|
71
71
|
if (source === void 0) {
|
|
72
72
|
try {
|
|
@@ -76,19 +76,57 @@ function buildAppRequestRouteMetadata(routes) {
|
|
|
76
76
|
}
|
|
77
77
|
sourceCache.set(filePath, source);
|
|
78
78
|
}
|
|
79
|
+
return source;
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
/** Segment config files of the tree a direct request to a page route renders. */
|
|
83
|
+
function appPageSegmentConfigPaths(route) {
|
|
84
|
+
return [
|
|
85
|
+
...route.layouts,
|
|
86
|
+
route.pagePath,
|
|
87
|
+
...route.parallelSlots.flatMap((slot) => [
|
|
88
|
+
slot.layoutPath,
|
|
89
|
+
...slot.configLayoutPaths ?? [],
|
|
90
|
+
slot.pagePath ?? slot.defaultPath
|
|
91
|
+
])
|
|
92
|
+
];
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Patterns of the static App pages that answer a request whose raw pathname
|
|
96
|
+
* reaches a dynamic sibling but whose segment-decoded pathname names them, so
|
|
97
|
+
* `/%61` and `/caf%C3%A9` render `/a` and `/café` rather than `/[slug]`.
|
|
98
|
+
*
|
|
99
|
+
* Next.js serves those requests from the response cached under the decoded
|
|
100
|
+
* pathname, which exists only for a page it prerendered. The prerender listing
|
|
101
|
+
* classifies those: a page whose effective segment config renders it
|
|
102
|
+
* dynamically (`dynamic = "force-dynamic"`, `revalidate = 0` or the edge
|
|
103
|
+
* runtime on any segment) and a Route Handler have no such entry, so the
|
|
104
|
+
* dynamic sibling renders. So does a page whose sources can't be read here;
|
|
105
|
+
* its sibling's render stays out of the shared caches. A cacheComponents
|
|
106
|
+
* build lists every page route, as the prerender listing does.
|
|
107
|
+
*/
|
|
108
|
+
function buildAppDecodedPathnamePatterns(routes, config) {
|
|
109
|
+
const isPrerenderedPage = (route) => {
|
|
110
|
+
if (config?.cacheComponents) return true;
|
|
111
|
+
try {
|
|
112
|
+
return classifyAppPageRouteStaticEligibility(route, config?.readMdxEsm ?? null) === "eligible";
|
|
113
|
+
} catch {
|
|
114
|
+
return false;
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
return routes.filter((route) => !route.isDynamic && !route.routePath && getAppRouteRenderEntryPath(route) !== null && isPrerenderedPage(route)).map((route) => route.pattern);
|
|
118
|
+
}
|
|
119
|
+
function buildAppRequestRouteMetadata(routes) {
|
|
120
|
+
const readSource = createSegmentSourceReader();
|
|
121
|
+
const forcesDynamic = (filePath) => {
|
|
122
|
+
const source = readSource(filePath);
|
|
79
123
|
return source !== null && extractExportConstString(source, "dynamic") === "force-dynamic";
|
|
80
124
|
};
|
|
81
125
|
return routes.map((route) => ({
|
|
82
126
|
canUseCanonicalLoadingShell: appRouteHasMainTreeLoadingBoundary(route),
|
|
83
127
|
forceDynamic: route.routePath ? forcesDynamic(route.routePath) : [
|
|
84
|
-
...route
|
|
85
|
-
route.pagePath,
|
|
86
|
-
...route.parallelSlots.flatMap((slot) => [
|
|
87
|
-
slot.layoutPath,
|
|
88
|
-
...slot.configLayoutPaths ?? [],
|
|
89
|
-
slot.pagePath ?? slot.defaultPath,
|
|
90
|
-
...slot.interceptingRoutes.flatMap((intercept) => [...intercept.layoutPaths, intercept.pagePath])
|
|
91
|
-
]),
|
|
128
|
+
...appPageSegmentConfigPaths(route),
|
|
129
|
+
...route.parallelSlots.flatMap((slot) => slot.interceptingRoutes.flatMap((intercept) => [...intercept.layoutPaths, intercept.pagePath])),
|
|
92
130
|
...route.siblingIntercepts.flatMap((intercept) => [...intercept.layoutPaths, intercept.pagePath])
|
|
93
131
|
].some(forcesDynamic),
|
|
94
132
|
ids: route.ids ?? null,
|
|
@@ -201,11 +239,12 @@ export const __imageConfig = ${JSON.stringify({
|
|
|
201
239
|
contentSecurityPolicy: config?.imageConfig?.contentSecurityPolicy
|
|
202
240
|
})};
|
|
203
241
|
const __routes = ${JSON.stringify(requestRoutes)};
|
|
204
|
-
const __routeMatcher = __createAppRscRouteMatcher(__routes);
|
|
242
|
+
const __routeMatcher = __createAppRscRouteMatcher(__routes, ${JSON.stringify(buildAppDecodedPathnamePatterns(routes, config))});
|
|
205
243
|
const __metadataRouteMatchers = ${JSON.stringify(metadataRouteMatchers)};
|
|
206
244
|
|
|
207
245
|
function matchRoute(pathname) { return __routeMatcher.matchRoute(pathname); }
|
|
208
246
|
function matchRequestRoute(pathname) { return __routeMatcher.matchRequestRoute(pathname); }
|
|
247
|
+
function matchRawRequestRoute(pathname) { return __routeMatcher.matchRawRequestRoute(pathname); }
|
|
209
248
|
function hasInterceptionId(interceptionId) { return __routeMatcher.hasInterceptionId(interceptionId); }
|
|
210
249
|
function __isMetadataPath(pathname) {
|
|
211
250
|
const parts = pathname.split("/").filter(Boolean);
|
|
@@ -262,6 +301,7 @@ const __requestHandler = createAppRscRequestHandler({
|
|
|
262
301
|
hasInterceptionId,
|
|
263
302
|
matchRoute,
|
|
264
303
|
matchRequestRoute,
|
|
304
|
+
matchRawRequestRoute,
|
|
265
305
|
matchInterceptRoute(pathname, sourcePathname, interceptionId) {
|
|
266
306
|
const intercept = __routeMatcher.findIntercept(pathname, sourcePathname, interceptionId);
|
|
267
307
|
if (!intercept) return null;
|
|
@@ -513,7 +553,6 @@ import {
|
|
|
513
553
|
resolveAppPageChildSegments as __resolveAppPageChildSegments,
|
|
514
554
|
} from ${JSON.stringify(appPageRouteWiringPath)};
|
|
515
555
|
import { buildPageElements as __buildPageElements } from ${JSON.stringify(appPageElementBuilderPath)};
|
|
516
|
-
import { buildAppPageProbes as __buildAppPageProbes } from ${JSON.stringify(appPageProbePath)};
|
|
517
556
|
import {
|
|
518
557
|
dispatchAppPage as __dispatchAppPage,
|
|
519
558
|
} from ${JSON.stringify(appPageDispatchPath)};
|
|
@@ -566,7 +605,7 @@ import { suppressHookWarningAls } from ${JSON.stringify(appHookWarningSuppressio
|
|
|
566
605
|
import { clearAppRequestContext as __clearRequestContext, setAppNavigationContext as setNavigationContext } from ${JSON.stringify(appRequestContextPath)};
|
|
567
606
|
__configureMemoryCacheHandler({ cacheMaxMemorySize: ${JSON.stringify(cacheMaxMemorySize)} });
|
|
568
607
|
import { createAppPrerenderStaticParamsResolver as __createAppPrerenderStaticParamsResolver } from ${JSON.stringify(appPrerenderStaticParamsPath)};
|
|
569
|
-
import { ensureAppRouteModulesLoaded as __ensureRouteLoaded
|
|
608
|
+
import { ensureAppRouteModulesLoaded as __ensureRouteLoaded } from ${JSON.stringify(appRouteModuleLoaderPath)};
|
|
570
609
|
import {
|
|
571
610
|
getRenderedConcreteUrlPathsForRoute as __getRenderedConcreteUrlPathsForRoute,
|
|
572
611
|
initPregeneratedPathsFromGlobals as __initPregeneratedPathsFromGlobals,
|
|
@@ -744,7 +783,7 @@ function __VINEXT_CLASS_REASONS(routeIdx) {
|
|
|
744
783
|
const routes = [
|
|
745
784
|
${routeEntries.join(",\n")}
|
|
746
785
|
];
|
|
747
|
-
const __routeMatcher = __createAppRscRouteMatcher(routes);
|
|
786
|
+
const __routeMatcher = __createAppRscRouteMatcher(routes, ${JSON.stringify(buildAppDecodedPathnamePatterns(routes, config))});
|
|
748
787
|
|
|
749
788
|
${instrumentationPath ? "let metadataRoutes;" : `const metadataRoutes = [
|
|
750
789
|
${metaRouteEntries.join(",\n")}
|
|
@@ -841,6 +880,10 @@ function matchRequestRoute(url) {
|
|
|
841
880
|
return __routeMatcher.matchRequestRoute(url);
|
|
842
881
|
}
|
|
843
882
|
|
|
883
|
+
function matchRawRequestRoute(url) {
|
|
884
|
+
return __routeMatcher.matchRawRequestRoute(url);
|
|
885
|
+
}
|
|
886
|
+
|
|
844
887
|
/**
|
|
845
888
|
* Check if a pathname matches any intercepting route.
|
|
846
889
|
* Returns the match info or null.
|
|
@@ -1000,6 +1043,7 @@ ${responseStageOnly ? "const __responseStageOptions = {" : "const __appRscHandle
|
|
|
1000
1043
|
scriptNonce,
|
|
1001
1044
|
searchParams,
|
|
1002
1045
|
renderMode,
|
|
1046
|
+
renderWholeDocument,
|
|
1003
1047
|
}) {
|
|
1004
1048
|
const PageComponent = route.page?.default;
|
|
1005
1049
|
const __segmentConfigBranches = __resolveRouteSegmentConfigBranches(route);
|
|
@@ -1021,7 +1065,6 @@ ${responseStageOnly ? "const __responseStageOptions = {" : "const __appRscHandle
|
|
|
1021
1065
|
routePatternParts: route.patternParts,
|
|
1022
1066
|
routeSegments: route.routeSegments,
|
|
1023
1067
|
});
|
|
1024
|
-
const _asyncRouteParams = makeThenableParams(params);
|
|
1025
1068
|
return __dispatchAppPage({
|
|
1026
1069
|
basePath: __basePath,
|
|
1027
1070
|
bypassInterceptionContextCache,
|
|
@@ -1040,6 +1083,7 @@ ${responseStageOnly ? "const __responseStageOptions = {" : "const __appRscHandle
|
|
|
1040
1083
|
observePageSearchParamsAccess: buildOptions?.observePageSearchParamsAccess === true,
|
|
1041
1084
|
isForceStatic: buildOptions?.isForceStatic === true,
|
|
1042
1085
|
serveStreamingMetadata: buildOptions?.serveStreamingMetadata,
|
|
1086
|
+
placeStreamedMetadataInHead: buildOptions?.placeStreamedMetadataInHead === true,
|
|
1043
1087
|
isProduction: process.env.NODE_ENV === "production",
|
|
1044
1088
|
}, layoutParamAccess, displayPathname, scriptNonce);
|
|
1045
1089
|
},
|
|
@@ -1127,31 +1171,6 @@ ${responseStageOnly ? "const __responseStageOptions = {" : "const __appRscHandle
|
|
|
1127
1171
|
route,
|
|
1128
1172
|
});
|
|
1129
1173
|
},
|
|
1130
|
-
async probePage(probeSearchParams = searchParams) {
|
|
1131
|
-
const __probeIntercept = findIntercept(
|
|
1132
|
-
interceptionPathname,
|
|
1133
|
-
interceptionContext,
|
|
1134
|
-
interceptionId,
|
|
1135
|
-
);
|
|
1136
|
-
// The intercepting-route page module is lazy (page: null + __pageLoader).
|
|
1137
|
-
// Resolve it before probing so buildAppPageProbes inspects the real page
|
|
1138
|
-
// component for dynamic bailout — matching the render path, which also
|
|
1139
|
-
// hydrates it (resolveAppPageInterceptState). Without this the intercept
|
|
1140
|
-
// probe branch silently inspects an undefined component and never
|
|
1141
|
-
// observes the page's searchParams/headers access. Shared loader, so
|
|
1142
|
-
// the import is isolated from the request context here too.
|
|
1143
|
-
if (__probeIntercept) await __loadAppInterceptPage(__probeIntercept);
|
|
1144
|
-
return Promise.all(__buildAppPageProbes({
|
|
1145
|
-
route,
|
|
1146
|
-
pageComponent: PageComponent,
|
|
1147
|
-
asyncRouteParams: _asyncRouteParams,
|
|
1148
|
-
searchParams: probeSearchParams,
|
|
1149
|
-
intercept: __probeIntercept,
|
|
1150
|
-
isRscRequest,
|
|
1151
|
-
matchedParams: params,
|
|
1152
|
-
makeThenableParams,
|
|
1153
|
-
}));
|
|
1154
|
-
},
|
|
1155
1174
|
renderErrorBoundaryPage(renderErr, errorOrigin) {
|
|
1156
1175
|
const __activeIntercept = findIntercept(
|
|
1157
1176
|
interceptionPathname,
|
|
@@ -1210,6 +1229,7 @@ ${responseStageOnly ? "const __responseStageOptions = {" : "const __appRscHandle
|
|
|
1210
1229
|
searchParams,
|
|
1211
1230
|
setNavigationContext,
|
|
1212
1231
|
renderMode,
|
|
1232
|
+
renderWholeDocument,
|
|
1213
1233
|
});
|
|
1214
1234
|
},
|
|
1215
1235
|
async dispatchMatchedRouteHandler({
|
|
@@ -1564,6 +1584,7 @@ ${responseStageOnly ? "const __responseStageOptions = {" : "const __appRscHandle
|
|
|
1564
1584
|
},` : ""}
|
|
1565
1585
|
matchRoute,
|
|
1566
1586
|
matchRequestRoute,
|
|
1587
|
+
matchRawRequestRoute,
|
|
1567
1588
|
hasInterceptionId,
|
|
1568
1589
|
matchInterceptRoute(pathname, sourcePathname, interceptionId) {
|
|
1569
1590
|
const intercept = findIntercept(pathname, sourcePathname, interceptionId);
|
package/dist/index.d.ts
CHANGED
|
@@ -106,7 +106,10 @@ export type VinextOptions = {
|
|
|
106
106
|
* Configure cache handlers declaratively, so you don't need a custom worker
|
|
107
107
|
* entry that calls `setDataCacheHandler()` / `setCdnCacheAdapter()`. Each slot
|
|
108
108
|
* is a `{ adapter, options }` descriptor pointing at an adapter module whose
|
|
109
|
-
* default export is a factory
|
|
109
|
+
* default export is a factory function or a class; either receives one
|
|
110
|
+
* `{ env, options }` argument (classes are invoked with `new`, other
|
|
111
|
+
* functions are called; see `CacheAdapterDescriptor.adapter` for how
|
|
112
|
+
* classes are recognised). The plugin registers them automatically on the
|
|
110
113
|
* first request, passing the host `env` (Worker bindings) so adapters that
|
|
111
114
|
* need a binding — e.g. a KV namespace — can read it.
|
|
112
115
|
*
|
package/dist/index.js
CHANGED
|
@@ -14,7 +14,7 @@ import { matchesRewriteSource, proxyExternalRequest } from "./config/config-matc
|
|
|
14
14
|
import { omitUnusedBuildSourcemap } from "./plugins/transform-result.js";
|
|
15
15
|
import { assetPrefixPathname, isNextStaticPath, resolveAssetsDir } from "./utils/asset-prefix.js";
|
|
16
16
|
import { RESOLVED_VIRTUAL_GOOGLE_FONTS, VIRTUAL_GOOGLE_FONTS, createGoogleFontsPlugin, createLocalFontsPlugin, generateGoogleFontsVirtualModule, parseStaticObjectLiteral } from "./plugins/fonts.js";
|
|
17
|
-
import { VINEXT_NEXT_CONFIG_PLUGIN_PROPERTY, createRscCompatibilityId, findNextConfigPath, loadNextConfig, resolveNextConfig, resolveNextConfigInput } from "./config/next-config.js";
|
|
17
|
+
import { VINEXT_NEXT_CONFIG_PLUGIN_PROPERTY, createRscCompatibilityId, findNextConfigPath, lightningCssFeatureNamesToMask, loadNextConfig, resolveNextConfig, resolveNextConfigInput } from "./config/next-config.js";
|
|
18
18
|
import { normalizePathnameForRouteMatchStrict } from "./routing/utils.js";
|
|
19
19
|
import { hasBasePath, stripBasePath } from "./utils/base-path.js";
|
|
20
20
|
import { appRouteGraph, appRouter, invalidateAppRouteCache, matchAppRoute } from "./routing/app-router.js";
|
|
@@ -25,7 +25,7 @@ import { INTERNAL_HEADERS, NEXTJS_DEPLOYMENT_ID_HEADER, VINEXT_INTERNAL_HEADERS,
|
|
|
25
25
|
import { normalizePath as normalizePath$1 } from "./server/normalize-path.js";
|
|
26
26
|
import { validateMiddlewareMatcherPatterns } from "./server/middleware-matcher-pattern.js";
|
|
27
27
|
import { methodNotAllowedResponse, notFoundStaticAssetResponse } from "./server/http-error-responses.js";
|
|
28
|
-
import { isOpenRedirectShaped } from "./server/open-redirect.js";
|
|
28
|
+
import { isOpenRedirectShaped, sendRepeatedSlashRedirect } from "./server/open-redirect.js";
|
|
29
29
|
import { canonicalizeRequestUrlPathname, filterInternalHeaders, normalizeTrailingSlash } from "./server/request-pipeline.js";
|
|
30
30
|
import { resolvePagesI18nRequest, stripI18nLocaleForApiRoute } from "./server/pages-i18n.js";
|
|
31
31
|
import { findInstrumentationClientFile, findInstrumentationFile, runInstrumentation } from "./server/instrumentation.js";
|
|
@@ -33,16 +33,17 @@ import { findMiddlewareFile, isProxyFile, runMiddleware } from "./server/middlew
|
|
|
33
33
|
import { extractMiddlewareMatcherConfig, extractMiddlewareMatcherConfigValue, hasExportedName } from "./build/report.js";
|
|
34
34
|
import { generatePagesRequestEntry, generatePagesResponseEntry, generateServerEntry } from "./entries/pages-server-entry.js";
|
|
35
35
|
import { compileClientMiddlewareMatchers, generateClientEntry } from "./entries/pages-client-entry.js";
|
|
36
|
+
import { isPathInside, isPathInsideOrEqual, stripJsExtension, stripViteModuleQuery } from "./utils/path.js";
|
|
36
37
|
import { logRequest, now } from "./server/request-log.js";
|
|
37
38
|
import { encodeUrlParserIgnoredCharacters, isNextDataPathname, normalizeNextDataPagePathname, parseNextDataPathname, shouldAddTrailingSlashToPagesDataPath, urlParserCreatesPagesDataPath } from "./server/pages-data-route.js";
|
|
38
39
|
import { getPagesPreviewModeId } from "./server/pages-preview.js";
|
|
39
40
|
import { createSSRHandler } from "./server/dev-server.js";
|
|
41
|
+
import { signalFromNodeResponse } from "./server/node-response-signal.js";
|
|
40
42
|
import { handleApiRoute } from "./server/api-handler.js";
|
|
41
43
|
import { DEFAULT_DEVICE_SIZES, DEFAULT_IMAGE_SIZES, isImageOptimizationPath, resolveDevImageRedirect } from "./server/image-optimization.js";
|
|
42
44
|
import { CACHEABILITY_MANIFEST_MODULE, CACHEABILITY_REQUEST_PROJECTION_MODULE } from "./server/cacheability-manifest.js";
|
|
43
45
|
import { PREGENERATED_CONCRETE_PATHS_MODULE } from "./server/pregenerated-concrete-paths.js";
|
|
44
46
|
import { installSocketErrorBackstop } from "./server/socket-error-backstop.js";
|
|
45
|
-
import { isPathInside, isPathInsideOrEqual, stripJsExtension, stripViteModuleQuery } from "./utils/path.js";
|
|
46
47
|
import { invalidateMetadataFileCache, scanMetadataFiles } from "./server/metadata-routes.js";
|
|
47
48
|
import { shouldInvalidateAppRouteFile } from "./server/dev-route-files.js";
|
|
48
49
|
import { createDirectRunner } from "./server/dev-module-runner.js";
|
|
@@ -94,6 +95,7 @@ import { createTransformCache } from "./plugins/transform-cache.js";
|
|
|
94
95
|
import { createOgHarfbuzzPlugin } from "./plugins/og-harfbuzz.js";
|
|
95
96
|
import { createOgAssetsPlugin, createOgInlineFetchAssetsPlugin } from "./plugins/og-assets.js";
|
|
96
97
|
import { createUseCacheCallablePlugin } from "./plugins/use-cache-callable.js";
|
|
98
|
+
import { cacheFlightCodecPlugin } from "./plugins/cache-flight-codec.js";
|
|
97
99
|
import { SSR_EXTERNAL_REACT_ENTRIES, VINEXT_OPTIMIZE_DEPS_EXCLUDE, mergeOptimizeDepsExclude } from "./plugins/rsc-client-shim-excludes.js";
|
|
98
100
|
import { createServerExternalsManifestPlugin } from "./plugins/server-externals-manifest.js";
|
|
99
101
|
import { createTransitiveExternalsPlugin } from "./plugins/transitive-externals.js";
|
|
@@ -110,12 +112,13 @@ import { removeConsoleCalls } from "./plugins/remove-console.js";
|
|
|
110
112
|
import { createImportMetaUrlPlugin } from "./plugins/import-meta-url.js";
|
|
111
113
|
import { createWorkerImageImportsPlugin } from "./plugins/worker-image-imports.js";
|
|
112
114
|
import { createRequireContextPlugin } from "./plugins/require-context.js";
|
|
115
|
+
import { commonJsEsmFacadeOptimizeDepsPlugin, stripEsmCommonJsExportFacade } from "./plugins/commonjs-esm-facade.js";
|
|
113
116
|
import { COMMONJS_SYNTAX_CODE_FILTER } from "./plugins/commonjs-syntax.js";
|
|
114
117
|
import { createRequireConditionResolutionPlugin, isConditionalRequireScriptModuleId } from "./plugins/require-condition-resolution.js";
|
|
115
118
|
import { createExtensionlessDynamicImportPlugin } from "./plugins/extensionless-dynamic-import.js";
|
|
116
119
|
import { createWasmModuleImportPlugin } from "./plugins/wasm-module-import.js";
|
|
117
120
|
import { consumerEnvironmentConditionFilter, getTypeofWindowReplacement, mayFoldChangeScannedImports, replaceConsumerEnvironmentConditions } from "./plugins/typeof-window.js";
|
|
118
|
-
import { hasMdxFiles } from "./utils/mdx-scan.js";
|
|
121
|
+
import { hasMdxFiles, loadMdxEsmReader, pageExtensionsIncludeMdx } from "./utils/mdx-scan.js";
|
|
119
122
|
import { publicFilePathVariants } from "./utils/public-file-path.js";
|
|
120
123
|
import { scanPublicFileRoutes } from "./utils/public-routes.js";
|
|
121
124
|
import { createIgnoreDynamicRequestsPlugin } from "./plugins/ignore-dynamic-requests.js";
|
|
@@ -1015,7 +1018,7 @@ function vinext(options = {}) {
|
|
|
1015
1018
|
});
|
|
1016
1019
|
const useServerIndex = plugins.findIndex((plugin) => plugin.name === "rsc:use-server");
|
|
1017
1020
|
if (useServerIndex === -1) throw new Error("vinext: Failed to locate @vitejs/plugin-rsc use-server plugin.");
|
|
1018
|
-
plugins.splice(useServerIndex, 0, useCachePlugin);
|
|
1021
|
+
plugins.splice(useServerIndex, 0, cacheFlightCodecPlugin(), useCachePlugin);
|
|
1019
1022
|
return plugins.map(scopeRscPlugin);
|
|
1020
1023
|
}).catch((cause) => {
|
|
1021
1024
|
throw new Error("vinext: Failed to load @vitejs/plugin-rsc.", { cause });
|
|
@@ -1160,12 +1163,21 @@ function vinext(options = {}) {
|
|
|
1160
1163
|
const previous = transformBundledCommonJsDependencies;
|
|
1161
1164
|
transformProjectLocalCommonJs = projectLocal && isDev;
|
|
1162
1165
|
transformBundledCommonJsDependencies = bundledDependency;
|
|
1166
|
+
let result;
|
|
1163
1167
|
try {
|
|
1164
|
-
|
|
1168
|
+
result = commonJsTransform.call(this, code, id, ...args);
|
|
1165
1169
|
} finally {
|
|
1166
1170
|
transformProjectLocalCommonJs = previousProjectLocal;
|
|
1167
1171
|
transformBundledCommonJsDependencies = previous;
|
|
1168
1172
|
}
|
|
1173
|
+
return Promise.resolve(result).then((transformed) => {
|
|
1174
|
+
if (typeof transformed !== "object" || typeof transformed?.code !== "string") return transformed;
|
|
1175
|
+
const stripped = stripEsmCommonJsExportFacade(transformed.code);
|
|
1176
|
+
return stripped === void 0 ? transformed : {
|
|
1177
|
+
...transformed,
|
|
1178
|
+
code: stripped
|
|
1179
|
+
};
|
|
1180
|
+
});
|
|
1169
1181
|
};
|
|
1170
1182
|
commonJsPlugin.transform = {
|
|
1171
1183
|
filter: { code: { include: COMMONJS_SYNTAX_CODE_FILTER } },
|
|
@@ -1643,7 +1655,8 @@ function vinext(options = {}) {
|
|
|
1643
1655
|
transformer: "lightningcss",
|
|
1644
1656
|
lightningcss: {
|
|
1645
1657
|
...nextConfig.lightningCssFeatures.include ? { include: nextConfig.lightningCssFeatures.include } : {},
|
|
1646
|
-
...nextConfig.lightningCssFeatures.exclude ? { exclude: nextConfig.lightningCssFeatures.exclude } : {}
|
|
1658
|
+
...nextConfig.lightningCssFeatures.exclude ? { exclude: nextConfig.lightningCssFeatures.exclude } : {},
|
|
1659
|
+
...(nextConfig.lightningCssFeatures.include & ~nextConfig.lightningCssFeatures.exclude & lightningCssFeatureNamesToMask(["custom-media-queries"])) !== 0 ? { drafts: { customMedia: true } } : {}
|
|
1647
1660
|
}
|
|
1648
1661
|
} : {},
|
|
1649
1662
|
...postcssOverride ? { postcss: postcssOverride } : {},
|
|
@@ -1693,7 +1706,7 @@ function vinext(options = {}) {
|
|
|
1693
1706
|
...depOptimizeNodeEnvOptions,
|
|
1694
1707
|
rolldownOptions: {
|
|
1695
1708
|
...depOptimizeNodeEnvOptions.rolldownOptions,
|
|
1696
|
-
plugins: [depOptimizeAliasPlugin]
|
|
1709
|
+
plugins: [depOptimizeAliasPlugin, commonJsEsmFacadeOptimizeDepsPlugin]
|
|
1697
1710
|
}
|
|
1698
1711
|
};
|
|
1699
1712
|
pagesOptimizeEntries = !hasAppDir ? [...hasPagesDir ? [toRelativeFileEntry(root, pagesDir) + "/**/*.{tsx,ts,jsx,js}"] : [], ...[instrumentationPath, instrumentationClientPath].flatMap((entry) => entry ? [toRelativeFileEntry(root, entry)] : [])] : [];
|
|
@@ -2199,6 +2212,7 @@ function vinext(options = {}) {
|
|
|
2199
2212
|
inlineCss: nextConfig?.inlineCss,
|
|
2200
2213
|
globalNotFound: nextConfig?.globalNotFound,
|
|
2201
2214
|
cacheComponents: nextConfig?.cacheComponents,
|
|
2215
|
+
readMdxEsm: !nextConfig?.cacheComponents && pageExtensionsIncludeMdx(nextConfig?.pageExtensions ?? []) ? await loadMdxEsmReader(root) : null,
|
|
2202
2216
|
prefetchInlining: nextConfig?.prefetchInlining,
|
|
2203
2217
|
hasServerActions,
|
|
2204
2218
|
actionOwners: this.environment.config.command === "build" ? void 0 : null,
|
|
@@ -2587,19 +2601,6 @@ export const loadServerActionClient = ${hasServerActions ? `() => import(${JSON.
|
|
|
2587
2601
|
delete req.headers[VINEXT_MW_CTX_HEADER];
|
|
2588
2602
|
next();
|
|
2589
2603
|
});
|
|
2590
|
-
server.middlewares.use((req, _res, next) => {
|
|
2591
|
-
try {
|
|
2592
|
-
assertNoPublicNextRequestConflict({
|
|
2593
|
-
root: server.config.root,
|
|
2594
|
-
publicDir: server.config.publicDir === "" ? null : server.config.publicDir,
|
|
2595
|
-
basePath: nextConfig.basePath ?? "",
|
|
2596
|
-
requestUrl: req.url ?? "/"
|
|
2597
|
-
});
|
|
2598
|
-
next();
|
|
2599
|
-
} catch (error) {
|
|
2600
|
-
next(error);
|
|
2601
|
-
}
|
|
2602
|
-
});
|
|
2603
2604
|
const pageExtensions = fileMatcher.extensionRegex;
|
|
2604
2605
|
let pagesRunner = null;
|
|
2605
2606
|
const getTrustedDevRevalidateOrigin = () => {
|
|
@@ -2896,6 +2897,22 @@ export const loadServerActionClient = ${hasServerActions ? `() => import(${JSON.
|
|
|
2896
2897
|
}
|
|
2897
2898
|
next();
|
|
2898
2899
|
});
|
|
2900
|
+
server.middlewares.use((req, res, next) => {
|
|
2901
|
+
if (!sendRepeatedSlashRedirect(req.url ?? "/", res)) next();
|
|
2902
|
+
});
|
|
2903
|
+
server.middlewares.use((req, _res, next) => {
|
|
2904
|
+
try {
|
|
2905
|
+
assertNoPublicNextRequestConflict({
|
|
2906
|
+
root: server.config.root,
|
|
2907
|
+
publicDir: server.config.publicDir === "" ? null : server.config.publicDir,
|
|
2908
|
+
basePath: nextConfig.basePath ?? "",
|
|
2909
|
+
requestUrl: req.url ?? "/"
|
|
2910
|
+
});
|
|
2911
|
+
next();
|
|
2912
|
+
} catch (error) {
|
|
2913
|
+
next(error);
|
|
2914
|
+
}
|
|
2915
|
+
});
|
|
2899
2916
|
server.middlewares.use((req, res, next) => {
|
|
2900
2917
|
if (!hasPagesDir || !handlePagesMiddleware || !isUnsupportedDevPublicRequest(req)) return next();
|
|
2901
2918
|
handlePagesMiddleware(req, res, next).catch(next);
|
|
@@ -3181,7 +3198,8 @@ export const loadServerActionClient = ${hasServerActions ? `() => import(${JSON.
|
|
|
3181
3198
|
const method = req.method ?? "GET";
|
|
3182
3199
|
const webRequest = new Request(new URL(routeUrl, requestOrigin), {
|
|
3183
3200
|
method,
|
|
3184
|
-
headers: nodeRequestHeaders
|
|
3201
|
+
headers: nodeRequestHeaders,
|
|
3202
|
+
signal: signalFromNodeResponse(res)
|
|
3185
3203
|
});
|
|
3186
3204
|
const applyRequestHeadersToNodeRequest = (nextRequestHeaders) => {
|
|
3187
3205
|
for (const key of Object.keys(req.headers)) delete req.headers[key];
|
|
@@ -3192,7 +3210,8 @@ export const loadServerActionClient = ${hasServerActions ? `() => import(${JSON.
|
|
|
3192
3210
|
const mwOrigin = `${rawProto === "https" || rawProto === "http" ? rawProto : "http"}://${requestHost}`;
|
|
3193
3211
|
const middlewareRequest = new Request(new URL(middlewareUrl, mwOrigin), {
|
|
3194
3212
|
method: req.method,
|
|
3195
|
-
headers: nodeRequestHeaders
|
|
3213
|
+
headers: nodeRequestHeaders,
|
|
3214
|
+
signal: webRequest.signal
|
|
3196
3215
|
});
|
|
3197
3216
|
const result = await runMiddleware(getPagesRunner(), capturedMiddlewarePath, middlewareRequest, nextConfig?.i18n, nextConfig?.basePath, nextConfig?.trailingSlash, opts.isDataRequest, pathname);
|
|
3198
3217
|
if (hasAppDir && result.continue) {
|
|
@@ -3256,7 +3275,8 @@ export const loadServerActionClient = ${hasServerActions ? `() => import(${JSON.
|
|
|
3256
3275
|
const hasBody = externalMethod !== "GET" && externalMethod !== "HEAD";
|
|
3257
3276
|
const externalInit = {
|
|
3258
3277
|
method: externalMethod,
|
|
3259
|
-
headers: currentRequest.headers
|
|
3278
|
+
headers: currentRequest.headers,
|
|
3279
|
+
signal: currentRequest.signal
|
|
3260
3280
|
};
|
|
3261
3281
|
if (hasBody) {
|
|
3262
3282
|
const { Readable } = await import("node:stream");
|
|
@@ -3774,6 +3794,7 @@ export const loadServerActionClient = ${hasServerActions ? `() => import(${JSON.
|
|
|
3774
3794
|
}
|
|
3775
3795
|
const manifest = {
|
|
3776
3796
|
prerenderSecret,
|
|
3797
|
+
compress: nextConfig?.compress !== false,
|
|
3777
3798
|
...serverRuntimeOutputDirs.size === 0 ? {} : { runtimeOutputDirs: [...serverRuntimeOutputDirs].map((runtimeOutputDir) => path.relative(root, runtimeOutputDir) || ".").sort() }
|
|
3778
3799
|
};
|
|
3779
3800
|
const source = JSON.stringify(manifest);
|
|
@@ -4124,7 +4145,7 @@ export const loadServerActionClient = ${hasServerActions ? `() => import(${JSON.
|
|
|
4124
4145
|
if (rscPluginPromise) {
|
|
4125
4146
|
plugins.push(createRscReferenceValidationNormalizerPlugin());
|
|
4126
4147
|
plugins.push(createRscClientReferenceLoadersPlugin());
|
|
4127
|
-
} else if (manualUseCachePluginPromise) plugins.push(manualUseCachePluginPromise);
|
|
4148
|
+
} else if (manualUseCachePluginPromise) plugins.push(cacheFlightCodecPlugin(), manualUseCachePluginPromise);
|
|
4128
4149
|
plugins.push({
|
|
4129
4150
|
name: "vinext:plain-pages-build-config",
|
|
4130
4151
|
apply: "build",
|
|
@@ -4162,6 +4183,10 @@ function getNextPublicEnvDefines() {
|
|
|
4162
4183
|
* Handles multi-value headers (Set-Cookie) correctly.
|
|
4163
4184
|
*/
|
|
4164
4185
|
async function writeWebResponseToNodeRes(res, response) {
|
|
4186
|
+
if (res.destroyed) {
|
|
4187
|
+
response.body?.cancel().catch(() => {});
|
|
4188
|
+
return;
|
|
4189
|
+
}
|
|
4165
4190
|
const nodeHeaders = {};
|
|
4166
4191
|
response.headers.forEach((value, key) => {
|
|
4167
4192
|
if (key === "set-cookie") return;
|
|
@@ -4174,13 +4199,17 @@ async function writeWebResponseToNodeRes(res, response) {
|
|
|
4174
4199
|
if (response.statusText) res.writeHead(response.status, response.statusText, nodeHeaders);
|
|
4175
4200
|
else res.writeHead(response.status, nodeHeaders);
|
|
4176
4201
|
if (response.body) {
|
|
4177
|
-
const { Readable } = await import("node:stream");
|
|
4202
|
+
const { Readable, pipeline } = await import("node:stream");
|
|
4178
4203
|
const nodeStream = Readable.fromWeb(response.body);
|
|
4204
|
+
let clientDisconnected = false;
|
|
4205
|
+
res.once("close", () => {
|
|
4206
|
+
clientDisconnected = !res.writableFinished && !nodeStream.errored;
|
|
4207
|
+
});
|
|
4179
4208
|
await new Promise((resolve, reject) => {
|
|
4180
|
-
nodeStream
|
|
4181
|
-
|
|
4182
|
-
|
|
4183
|
-
|
|
4209
|
+
pipeline(nodeStream, res, (error) => {
|
|
4210
|
+
if (error && !(clientDisconnected && error.code === "ERR_STREAM_PREMATURE_CLOSE")) reject(error);
|
|
4211
|
+
else resolve();
|
|
4212
|
+
});
|
|
4184
4213
|
});
|
|
4185
4214
|
} else res.end();
|
|
4186
4215
|
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { MagicStringTransformResult } from "./transform-result.js";
|
|
2
|
+
import { Plugin } from "vite";
|
|
3
|
+
//#region src/plugins/cache-flight-codec.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Version of the Flight codec package that owns `id`. plugin-rsc resolves the
|
|
6
|
+
* app's own react-server-dom-webpack when installed and its vendored copy
|
|
7
|
+
* otherwise; reading the codec file's own package.json follows that choice.
|
|
8
|
+
*/
|
|
9
|
+
export declare function readFlightCodecVersion(id: string): string;
|
|
10
|
+
/**
|
|
11
|
+
* Backport React 19.3's root-element temporary reference branch to older Flight
|
|
12
|
+
* codecs, so a "use cache" argument like `Promise<ReactElement>` encodes as a
|
|
13
|
+
* temporary reference instead of throwing. Remove it once React 19.3 is the
|
|
14
|
+
* minimum supported version.
|
|
15
|
+
* https://github.com/facebook/react/blob/v19.3.0/packages/react-client/src/ReactFlightReplyClient.js#L486
|
|
16
|
+
*/
|
|
17
|
+
export declare function patchCacheFlightCodec(code: string, id: string, version?: string): MagicStringTransformResult | null;
|
|
18
|
+
export declare function cacheFlightCodecPlugin(): Plugin;
|
|
19
|
+
//#endregion
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import path from "../deps/.pnpm/pathslash@0.1.0/deps/pathslash/dist/index.js";
|
|
2
|
+
import { magicStringTransformResult } from "./transform-result.js";
|
|
3
|
+
import fs from "node:fs";
|
|
4
|
+
import MagicString from "magic-string";
|
|
5
|
+
//#region src/plugins/cache-flight-codec.ts
|
|
6
|
+
const CLIENT_CODEC = /\/react-server-dom-(?:webpack|turbopack)-client\.edge\.(?:development|production)\.js$/;
|
|
7
|
+
const ELEMENT_CASE = /case REACT_ELEMENT_TYPE:[\s\S]*?throw Error\(\s*"React Element cannot be passed/;
|
|
8
|
+
/**
|
|
9
|
+
* Version of the Flight codec package that owns `id`. plugin-rsc resolves the
|
|
10
|
+
* app's own react-server-dom-webpack when installed and its vendored copy
|
|
11
|
+
* otherwise; reading the codec file's own package.json follows that choice.
|
|
12
|
+
*/
|
|
13
|
+
function readFlightCodecVersion(id) {
|
|
14
|
+
for (let dir = path.dirname(id);; dir = path.dirname(dir)) {
|
|
15
|
+
const manifest = path.join(dir, "package.json");
|
|
16
|
+
if (fs.existsSync(manifest)) {
|
|
17
|
+
const pkg = JSON.parse(fs.readFileSync(manifest, "utf8"));
|
|
18
|
+
if (/^react-server-dom-(?:webpack|turbopack)$/.test(pkg.name ?? "") && pkg.version) return pkg.version;
|
|
19
|
+
}
|
|
20
|
+
if (path.dirname(dir) === dir) throw new Error(`vinext: cannot find the react-server-dom package version for ${id}`);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
/** React 19.3 ships the branch; 0.0.0-* experimental builds track main. */
|
|
24
|
+
function needsElementTemporaryReferenceBackport(version) {
|
|
25
|
+
const match = /^(\d+)\.(\d+)\./.exec(version);
|
|
26
|
+
if (!match || version.startsWith("0.0.0-")) return false;
|
|
27
|
+
const [major, minor] = [Number(match[1]), Number(match[2])];
|
|
28
|
+
return major < 19 || major === 19 && minor < 3;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Backport React 19.3's root-element temporary reference branch to older Flight
|
|
32
|
+
* codecs, so a "use cache" argument like `Promise<ReactElement>` encodes as a
|
|
33
|
+
* temporary reference instead of throwing. Remove it once React 19.3 is the
|
|
34
|
+
* minimum supported version.
|
|
35
|
+
* https://github.com/facebook/react/blob/v19.3.0/packages/react-client/src/ReactFlightReplyClient.js#L486
|
|
36
|
+
*/
|
|
37
|
+
function patchCacheFlightCodec(code, id, version = readFlightCodecVersion(id)) {
|
|
38
|
+
if (!needsElementTemporaryReferenceBackport(version)) return null;
|
|
39
|
+
const elementCase = ELEMENT_CASE.exec(code);
|
|
40
|
+
if (!elementCase) throw new Error(`vinext: react-server-dom-webpack ${version} (${id}) is not supported. Upgrade react, react-dom, and react-server-dom-webpack to 19.3 or later. If your app does not depend on react-server-dom-webpack directly, upgrade @vitejs/plugin-rsc to 0.5.35 or later instead.`);
|
|
41
|
+
const output = new MagicString(code);
|
|
42
|
+
output.appendLeft(elementCase.index + elementCase[0].lastIndexOf("throw Error("), "if (void 0 !== temporaryReferences && modelRoot === value) return (modelRoot = null), \"$T\";\n");
|
|
43
|
+
return magicStringTransformResult(output, {
|
|
44
|
+
hires: "boundary",
|
|
45
|
+
source: id
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
function cacheFlightCodecPlugin() {
|
|
49
|
+
const transform = {
|
|
50
|
+
filter: { id: CLIENT_CODEC },
|
|
51
|
+
handler: (code, id) => patchCacheFlightCodec(code, id)
|
|
52
|
+
};
|
|
53
|
+
return {
|
|
54
|
+
name: "vinext:cache-flight-codec",
|
|
55
|
+
enforce: "pre",
|
|
56
|
+
applyToEnvironment: (environment) => environment.name === "rsc",
|
|
57
|
+
configEnvironment(name) {
|
|
58
|
+
if (name !== "rsc") return;
|
|
59
|
+
return { optimizeDeps: { rolldownOptions: { plugins: [{
|
|
60
|
+
name: "vinext:cache-flight-codec-optimizer",
|
|
61
|
+
transform
|
|
62
|
+
}] } } };
|
|
63
|
+
},
|
|
64
|
+
transform
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
//#endregion
|
|
68
|
+
export { cacheFlightCodecPlugin, patchCacheFlightCodec, readFlightCodecVersion };
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { Plugin } from "vite";
|
|
2
|
+
//#region src/plugins/commonjs-esm-facade.d.ts
|
|
3
|
+
/**
|
|
4
|
+
* Removes the export facade vite-plugin-commonjs appended to `output` when the
|
|
5
|
+
* module it transformed is ESM. Returns `undefined` when there is nothing to
|
|
6
|
+
* remove.
|
|
7
|
+
*
|
|
8
|
+
* Next.js treats a module with ESM syntax as ESM: `require()` still works, but
|
|
9
|
+
* `module` / `exports` never become its exports. The plugin's analyzer is not
|
|
10
|
+
* scope-aware, so for bundled ESM that inlines CommonJS wrappers
|
|
11
|
+
* (`__commonJS((exports, module) => …)`) it exports the wrappers' assignments
|
|
12
|
+
* too, which duplicates the module's own exports. Its `require()` rewrite and
|
|
13
|
+
* its local `module` / `exports` polyfill stay, so free CommonJS assignments
|
|
14
|
+
* still run without becoming exports.
|
|
15
|
+
*
|
|
16
|
+
* Besides the facade, the plugin only prepends imports and its polyfill and
|
|
17
|
+
* rewrites `require()` calls, so the module's own top-level exports are still
|
|
18
|
+
* in `output`. Classifying the output rather than rereading the source keeps
|
|
19
|
+
* the decision tied to the exact code the plugin transformed.
|
|
20
|
+
*
|
|
21
|
+
* The facade is appended after the module's code (only dynamic-require
|
|
22
|
+
* runtimes, which have no source mappings, may follow it), so removing it
|
|
23
|
+
* leaves the plugin's source map valid.
|
|
24
|
+
*/
|
|
25
|
+
export declare function stripEsmCommonJsExportFacade(output: string): string | undefined;
|
|
26
|
+
/**
|
|
27
|
+
* Applies {@link stripEsmCommonJsExportFacade} in the client dependency
|
|
28
|
+
* optimizer's Rolldown builds (scan and pre-bundle). vite-plugin-commonjs's
|
|
29
|
+
* pre-bundle plugin loads and converts files there without vinext's transform
|
|
30
|
+
* wrapper, so its output reaches this hook as the loaded code. That code is
|
|
31
|
+
* the optimizer's source, so the removal needs its own map for anything the
|
|
32
|
+
* plugin appended after the facade.
|
|
33
|
+
*/
|
|
34
|
+
export declare const commonJsEsmFacadeOptimizeDepsPlugin: Plugin;
|
|
35
|
+
//#endregion
|