vinext 0.1.7 → 0.1.8
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/dist/check.d.ts +18 -0
- package/dist/check.js +37 -17
- package/dist/cli.js +2 -2
- package/dist/config/next-config.d.ts +2 -1
- package/dist/config/next-config.js +3 -0
- package/dist/config/server-external-packages.d.ts +4 -0
- package/dist/config/server-external-packages.js +91 -0
- package/dist/deploy.d.ts +7 -0
- package/dist/deploy.js +25 -18
- package/dist/entries/app-rsc-entry.js +54 -10
- package/dist/entries/app-rsc-manifest.js +8 -0
- package/dist/entries/pages-client-entry.js +1 -0
- package/dist/entries/pages-server-entry.js +1 -0
- package/dist/index.js +46 -20
- package/dist/init.js +2 -1
- package/dist/plugins/middleware-server-only.d.ts +8 -6
- package/dist/plugins/middleware-server-only.js +8 -7
- package/dist/plugins/optimize-imports.js +1 -1
- package/dist/routing/app-route-graph.d.ts +6 -2
- package/dist/routing/app-route-graph.js +61 -13
- package/dist/routing/app-router.d.ts +5 -0
- package/dist/routing/app-router.js +5 -0
- package/dist/routing/file-matcher.d.ts +5 -0
- package/dist/routing/file-matcher.js +7 -1
- package/dist/server/app-browser-entry.js +42 -147
- package/dist/server/app-browser-history-controller.d.ts +2 -1
- package/dist/server/app-browser-history-controller.js +6 -2
- package/dist/server/app-browser-server-action-client.d.ts +32 -0
- package/dist/server/app-browser-server-action-client.js +128 -0
- package/dist/server/app-fallback-renderer.d.ts +3 -1
- package/dist/server/app-fallback-renderer.js +6 -2
- package/dist/server/app-page-boundary-render.d.ts +3 -0
- package/dist/server/app-page-boundary-render.js +14 -3
- package/dist/server/app-page-cache-finalizer.d.ts +1 -0
- package/dist/server/app-page-cache-finalizer.js +8 -2
- package/dist/server/app-page-dispatch.d.ts +33 -4
- package/dist/server/app-page-dispatch.js +62 -90
- package/dist/server/app-page-element-builder.d.ts +7 -1
- package/dist/server/app-page-element-builder.js +56 -19
- package/dist/server/app-page-head.d.ts +16 -1
- package/dist/server/app-page-head.js +44 -22
- package/dist/server/app-page-params.d.ts +2 -1
- package/dist/server/app-page-params.js +8 -1
- package/dist/server/app-page-ppr-runtime.d.ts +7 -0
- package/dist/server/app-page-ppr-runtime.js +70 -0
- package/dist/server/app-page-probe.d.ts +1 -0
- package/dist/server/app-page-probe.js +1 -1
- package/dist/server/app-page-render.d.ts +4 -1
- package/dist/server/app-page-render.js +8 -3
- package/dist/server/app-page-request.d.ts +8 -1
- package/dist/server/app-page-request.js +23 -11
- package/dist/server/app-page-route-wiring.d.ts +6 -1
- package/dist/server/app-page-route-wiring.js +30 -8
- package/dist/server/app-page-search-params-observation.d.ts +4 -2
- package/dist/server/app-page-search-params-observation.js +11 -7
- package/dist/server/app-ppr-fallback-shell-render.d.ts +4 -3
- package/dist/server/app-route-handler-dispatch.js +1 -0
- package/dist/server/app-route-handler-execution.js +2 -1
- package/dist/server/app-route-module-loader.d.ts +2 -0
- package/dist/server/app-route-module-loader.js +1 -0
- package/dist/server/app-router-entry.js +7 -6
- package/dist/server/app-rsc-errors.js +7 -1
- package/dist/server/app-rsc-handler.d.ts +2 -1
- package/dist/server/app-rsc-handler.js +6 -9
- package/dist/server/app-rsc-route-matching.d.ts +7 -0
- package/dist/server/app-rsc-route-matching.js +36 -3
- package/dist/server/app-segment-config.d.ts +1 -0
- package/dist/server/app-segment-config.js +32 -2
- package/dist/server/app-server-action-execution.d.ts +4 -0
- package/dist/server/app-server-action-execution.js +41 -10
- package/dist/server/app-ssr-entry.js +4 -1
- package/dist/server/app-static-generation.d.ts +1 -0
- package/dist/server/app-static-generation.js +1 -0
- package/dist/server/headers.d.ts +3 -1
- package/dist/server/headers.js +3 -1
- package/dist/server/prod-server.js +15 -6
- package/dist/server/worker-utils.d.ts +2 -1
- package/dist/server/worker-utils.js +7 -1
- package/dist/shims/error-boundary.d.ts +19 -1
- package/dist/shims/error-boundary.js +11 -1
- package/dist/shims/headers.d.ts +3 -1
- package/dist/shims/headers.js +16 -5
- package/dist/shims/link.js +16 -12
- package/dist/shims/metadata.d.ts +3 -2
- package/dist/shims/metadata.js +8 -4
- package/dist/shims/router.js +13 -2
- package/dist/typegen.js +6 -5
- package/dist/utils/path.d.ts +2 -1
- package/dist/utils/path.js +1 -1
- package/dist/utils/project.d.ts +4 -0
- package/dist/utils/project.js +5 -1
- package/package.json +7 -3
|
@@ -30,6 +30,8 @@ const appElementsPath = resolveEntryPath("../server/app-elements.js", import.met
|
|
|
30
30
|
const appPageRouteWiringPath = resolveEntryPath("../server/app-page-route-wiring.js", import.meta.url);
|
|
31
31
|
const appPageProbePath = resolveEntryPath("../server/app-page-probe.js", import.meta.url);
|
|
32
32
|
const appPageDispatchPath = resolveEntryPath("../server/app-page-dispatch.js", import.meta.url);
|
|
33
|
+
const appPagePprRuntimePath = resolveEntryPath("../server/app-page-ppr-runtime.js", import.meta.url);
|
|
34
|
+
const fileBasedMetadataPath = resolveEntryPath("../server/file-based-metadata.js", import.meta.url);
|
|
33
35
|
const appPageRequestPath = resolveEntryPath("../server/app-page-request.js", import.meta.url);
|
|
34
36
|
const appSegmentConfigPath = resolveEntryPath("../server/app-segment-config.js", import.meta.url);
|
|
35
37
|
const appRscRouteMatchingPath = resolveEntryPath("../server/app-rsc-route-matching.js", import.meta.url);
|
|
@@ -129,6 +131,11 @@ ${hasPagesDir ? `import {
|
|
|
129
131
|
const __loadAppRouteHandlerDispatch = () => import(${JSON.stringify(appRouteHandlerDispatchPath)});
|
|
130
132
|
${hasServerActions ? `const __loadAppServerActionExecution = () => import(${JSON.stringify(appServerActionExecutionPath)});` : ""}
|
|
131
133
|
${(metadataRoutes?.length ?? 0) > 0 ? `const __loadMetadataRouteResponse = () => import(${JSON.stringify(metadataRouteResponsePath)});` : ""}
|
|
134
|
+
${(metadataRoutes?.length ?? 0) > 0 ? `const __loadFileBasedMetadata = () => import(${JSON.stringify(fileBasedMetadataPath)});
|
|
135
|
+
async function __applyFileBasedMetadata(...args) {
|
|
136
|
+
const { applyFileBasedMetadata } = await __loadFileBasedMetadata();
|
|
137
|
+
return applyFileBasedMetadata(...args);
|
|
138
|
+
}` : ""}
|
|
132
139
|
import {
|
|
133
140
|
sanitizeErrorForClient as __sanitizeErrorForClient,
|
|
134
141
|
} from ${JSON.stringify(appRscErrorsPath)};
|
|
@@ -152,6 +159,10 @@ import { buildAppPageProbes as __buildAppPageProbes } from ${JSON.stringify(appP
|
|
|
152
159
|
import {
|
|
153
160
|
dispatchAppPage as __dispatchAppPage,
|
|
154
161
|
} from ${JSON.stringify(appPageDispatchPath)};
|
|
162
|
+
${cacheComponents ? `import {
|
|
163
|
+
appPagePprRuntime as __appPagePprRuntime,
|
|
164
|
+
createAppPprFallbackShells as __createAppPprFallbackShells,
|
|
165
|
+
} from ${JSON.stringify(appPagePprRuntimePath)};` : ""}
|
|
155
166
|
import {
|
|
156
167
|
resolveAppPageGenerateStaticParamsSources as __resolveAppPageGenerateStaticParamsSources,
|
|
157
168
|
} from ${JSON.stringify(appPageRequestPath)};
|
|
@@ -234,6 +245,11 @@ function __resolveRouteFetchCacheMode(route) {
|
|
|
234
245
|
return __resolveAppPageFetchCacheMode({
|
|
235
246
|
layouts: route.layouts,
|
|
236
247
|
page: route.page,
|
|
248
|
+
parallelSegments: Object.values(route.slots ?? {}).flatMap((slot) => [
|
|
249
|
+
slot.layout,
|
|
250
|
+
...(slot.configLayouts ?? []),
|
|
251
|
+
slot.page ?? slot.default,
|
|
252
|
+
]),
|
|
237
253
|
});
|
|
238
254
|
}
|
|
239
255
|
|
|
@@ -241,6 +257,11 @@ function __resolveRouteDynamicConfig(route) {
|
|
|
241
257
|
return __resolveAppPageSegmentConfig({
|
|
242
258
|
layouts: route.layouts,
|
|
243
259
|
page: route.page,
|
|
260
|
+
parallelSegments: Object.values(route.slots ?? {}).flatMap((slot) => [
|
|
261
|
+
slot.layout,
|
|
262
|
+
...(slot.configLayouts ?? []),
|
|
263
|
+
slot.page ?? slot.default,
|
|
264
|
+
]),
|
|
244
265
|
}).dynamicConfig ?? null;
|
|
245
266
|
}
|
|
246
267
|
|
|
@@ -248,6 +269,11 @@ function __resolveRouteRuntime(route) {
|
|
|
248
269
|
return __resolveAppPageSegmentConfig({
|
|
249
270
|
layouts: route.layouts,
|
|
250
271
|
page: route.page,
|
|
272
|
+
parallelSegments: Object.values(route.slots ?? {}).flatMap((slot) => [
|
|
273
|
+
slot.layout,
|
|
274
|
+
...(slot.configLayouts ?? []),
|
|
275
|
+
slot.page ?? slot.default,
|
|
276
|
+
]),
|
|
251
277
|
}).runtime ?? null;
|
|
252
278
|
}
|
|
253
279
|
|
|
@@ -317,6 +343,7 @@ const createRscOnErrorHandler = (request, pathname, routePath) =>
|
|
|
317
343
|
createAppRscOnErrorHandler(_reportRequestError, request, pathname, routePath);
|
|
318
344
|
|
|
319
345
|
const __fallbackRenderer = __createAppFallbackRenderer({
|
|
346
|
+
${(metadataRoutes?.length ?? 0) > 0 ? "applyFileBasedMetadata: __applyFileBasedMetadata," : ""}
|
|
320
347
|
basePath: __basePath,
|
|
321
348
|
trailingSlash: __trailingSlash,
|
|
322
349
|
rootBoundaries: {
|
|
@@ -366,6 +393,7 @@ async function buildPageElements(route, params, routePath, pageRequest, layoutPa
|
|
|
366
393
|
// Hydrate lazy page/route-handler modules before any synchronous read.
|
|
367
394
|
await __ensureRouteLoaded(route);
|
|
368
395
|
return __buildPageElements({
|
|
396
|
+
${(metadataRoutes?.length ?? 0) > 0 ? "applyFileBasedMetadata: __applyFileBasedMetadata," : ""}
|
|
369
397
|
route,
|
|
370
398
|
params,
|
|
371
399
|
routePath,
|
|
@@ -401,7 +429,6 @@ export const __assetPrefix = ${JSON.stringify(assetPrefix)};
|
|
|
401
429
|
export const __inlineCss = ${JSON.stringify(inlineCss)};
|
|
402
430
|
export const __hasPagesDir = ${JSON.stringify(hasPagesDir)};
|
|
403
431
|
export const getRenderedConcreteUrlPathsForRoute = __getRenderedConcreteUrlPathsForRoute;
|
|
404
|
-
const __cacheComponents = ${JSON.stringify(cacheComponents)};
|
|
405
432
|
|
|
406
433
|
export async function seedMemoryCacheFromPrerender(serverDir) {
|
|
407
434
|
const { seedMemoryCacheFromPrerender: __seedMemoryCacheFromPrerender } =
|
|
@@ -456,7 +483,9 @@ export default createAppRscHandler({
|
|
|
456
483
|
},
|
|
457
484
|
registerCacheAdapters: __registerConfiguredCacheAdapters,
|
|
458
485
|
configHeaders: __configHeaders,
|
|
459
|
-
cacheComponents
|
|
486
|
+
${cacheComponents ? `createPprFallbackShells(route, params) {
|
|
487
|
+
return __createAppPprFallbackShells(route, params);
|
|
488
|
+
},` : ""}
|
|
460
489
|
configRedirects: __configRedirects,
|
|
461
490
|
configRewrites: __configRewrites,
|
|
462
491
|
imageConfig: __imageConfig,
|
|
@@ -492,7 +521,12 @@ export default createAppRscHandler({
|
|
|
492
521
|
const __segmentConfig = __resolveAppPageSegmentConfig({
|
|
493
522
|
layouts: route.layouts,
|
|
494
523
|
page: route.page,
|
|
495
|
-
parallelPages: Object.values(route.slots ?? {}).map((slot) => slot.page),
|
|
524
|
+
parallelPages: Object.values(route.slots ?? {}).map((slot) => slot.page ?? slot.default),
|
|
525
|
+
parallelSegments: Object.values(route.slots ?? {}).flatMap((slot) => [
|
|
526
|
+
slot.layout,
|
|
527
|
+
...(slot.configLayouts ?? []),
|
|
528
|
+
slot.page ?? slot.default,
|
|
529
|
+
]),
|
|
496
530
|
});
|
|
497
531
|
const __generateStaticParams = __resolveAppPageGenerateStaticParamsSources({
|
|
498
532
|
layouts: route.layouts,
|
|
@@ -506,7 +540,7 @@ export default createAppRscHandler({
|
|
|
506
540
|
ensureRouteLoaded: __ensureRouteLoaded,
|
|
507
541
|
clientTraceMetadata: __clientTraceMetadata,
|
|
508
542
|
reactMaxHeadersLength: __reactMaxHeadersLength,
|
|
509
|
-
buildPageElement(targetRoute, targetParams, targetOpts, targetSearchParams, layoutParamAccess) {
|
|
543
|
+
buildPageElement(targetRoute, targetParams, targetOpts, targetSearchParams, layoutParamAccess, buildOptions) {
|
|
510
544
|
return buildPageElements(targetRoute, targetParams, cleanPathname, {
|
|
511
545
|
opts: targetOpts,
|
|
512
546
|
searchParams: targetSearchParams,
|
|
@@ -514,6 +548,8 @@ export default createAppRscHandler({
|
|
|
514
548
|
request,
|
|
515
549
|
mountedSlotsHeader,
|
|
516
550
|
renderMode,
|
|
551
|
+
observeMetadataSearchParamsAccess: buildOptions?.observeMetadataSearchParamsAccess === true,
|
|
552
|
+
observePageSearchParamsAccess: buildOptions?.observePageSearchParamsAccess === true,
|
|
517
553
|
}, layoutParamAccess, displayPathname);
|
|
518
554
|
},
|
|
519
555
|
clientReuseManifest,
|
|
@@ -570,6 +606,7 @@ export default createAppRscHandler({
|
|
|
570
606
|
params,
|
|
571
607
|
pprFallbackCacheShells,
|
|
572
608
|
pprFallbackShell,
|
|
609
|
+
pprRuntime: ${cacheComponents ? "__appPagePprRuntime" : "undefined"},
|
|
573
610
|
renderedConcreteUrlPaths,
|
|
574
611
|
skipStaticParamsValidation,
|
|
575
612
|
staticParamsValidationParams,
|
|
@@ -583,7 +620,7 @@ export default createAppRscHandler({
|
|
|
583
620
|
route,
|
|
584
621
|
});
|
|
585
622
|
},
|
|
586
|
-
async probePage() {
|
|
623
|
+
async probePage(probeSearchParams = searchParams) {
|
|
587
624
|
const __probeIntercept = findIntercept(cleanPathname, interceptionContext);
|
|
588
625
|
// The intercepting-route page module is lazy (page: null + __pageLoader).
|
|
589
626
|
// Resolve it before probing so buildAppPageProbes inspects the real page
|
|
@@ -598,21 +635,21 @@ export default createAppRscHandler({
|
|
|
598
635
|
route,
|
|
599
636
|
pageComponent: PageComponent,
|
|
600
637
|
asyncRouteParams: _asyncRouteParams,
|
|
601
|
-
searchParams,
|
|
638
|
+
searchParams: probeSearchParams,
|
|
602
639
|
intercept: __probeIntercept,
|
|
603
640
|
isRscRequest,
|
|
604
641
|
matchedParams: params,
|
|
605
642
|
makeThenableParams,
|
|
606
643
|
}));
|
|
607
644
|
},
|
|
608
|
-
renderErrorBoundaryPage(renderErr) {
|
|
645
|
+
renderErrorBoundaryPage(renderErr, errorOrigin) {
|
|
609
646
|
const __activeIntercept = findIntercept(cleanPathname, interceptionContext);
|
|
610
647
|
return __fallbackRenderer.renderErrorBoundary(route, renderErr, isRscRequest, request, params, scriptNonce, middlewareContext, {
|
|
611
648
|
isEdgeRuntime: __isEdgeRuntime(__segmentConfig.runtime),
|
|
612
649
|
sourcePageSegments: __activeIntercept?.slotKey === __SIBLING_PAGE_INTERCEPT_SLOT_KEY
|
|
613
650
|
? __activeIntercept.sourcePageSegments
|
|
614
651
|
: null,
|
|
615
|
-
});
|
|
652
|
+
}, errorOrigin);
|
|
616
653
|
},
|
|
617
654
|
renderHttpAccessFallbackPage(statusCode, opts, currentMiddlewareContext) {
|
|
618
655
|
const __activeIntercept = findIntercept(cleanPathname, interceptionContext);
|
|
@@ -762,7 +799,7 @@ export default createAppRscHandler({
|
|
|
762
799
|
const __actionMatch = matchRoute(cleanPathname);
|
|
763
800
|
if (__actionMatch) await __ensureRouteLoaded(__actionMatch.route);
|
|
764
801
|
const __actionIsEdgeRuntime = __actionMatch
|
|
765
|
-
? __isEdgeRuntime(
|
|
802
|
+
? __isEdgeRuntime(__resolveRouteRuntime(__actionMatch.route))
|
|
766
803
|
: false;
|
|
767
804
|
return __handleServerActionRscRequest({
|
|
768
805
|
actionId,
|
|
@@ -780,6 +817,8 @@ export default createAppRscHandler({
|
|
|
780
817
|
request: actionRequest,
|
|
781
818
|
mountedSlotsHeader: actionMountedSlotsHeader,
|
|
782
819
|
renderMode: actionRenderMode,
|
|
820
|
+
observeMetadataSearchParamsAccess,
|
|
821
|
+
observePageSearchParamsAccess,
|
|
783
822
|
}) {
|
|
784
823
|
return buildPageElements(actionRoute, actionParams, actionCleanPathname, {
|
|
785
824
|
opts: interceptOpts,
|
|
@@ -788,6 +827,8 @@ export default createAppRscHandler({
|
|
|
788
827
|
request: actionRequest,
|
|
789
828
|
mountedSlotsHeader: actionMountedSlotsHeader,
|
|
790
829
|
renderMode: actionRenderMode,
|
|
830
|
+
observeMetadataSearchParamsAccess: observeMetadataSearchParamsAccess === true,
|
|
831
|
+
observePageSearchParamsAccess: observePageSearchParamsAccess === true,
|
|
791
832
|
});
|
|
792
833
|
},
|
|
793
834
|
cleanPathname,
|
|
@@ -813,6 +854,7 @@ export default createAppRscHandler({
|
|
|
813
854
|
},
|
|
814
855
|
createTemporaryReferenceSet,
|
|
815
856
|
decodeReply,
|
|
857
|
+
draftModeSecret: __draftModeSecret,
|
|
816
858
|
findIntercept(pathnameToMatch) {
|
|
817
859
|
return findIntercept(pathnameToMatch, interceptionContext);
|
|
818
860
|
},
|
|
@@ -856,6 +898,8 @@ export default createAppRscHandler({
|
|
|
856
898
|
return {
|
|
857
899
|
interceptionContext,
|
|
858
900
|
interceptLayouts: intercept.interceptLayouts,
|
|
901
|
+
interceptLayoutSegments: intercept.interceptLayoutSegments,
|
|
902
|
+
interceptBranchSegments: intercept.interceptBranchSegments,
|
|
859
903
|
interceptSlotId: intercept.slotId,
|
|
860
904
|
interceptSlotKey: intercept.slotKey,
|
|
861
905
|
interceptSourceMatchedUrl: interceptionContext,
|
|
@@ -895,7 +939,7 @@ export default createAppRscHandler({
|
|
|
895
939
|
},` : ""}
|
|
896
940
|
publicFiles: __publicFiles,
|
|
897
941
|
renderNotFound({ isRscRequest, matchedParams, middlewareContext, request, route, scriptNonce }) {
|
|
898
|
-
const __isEdge = route ? __isEdgeRuntime(
|
|
942
|
+
const __isEdge = route ? __isEdgeRuntime(__resolveRouteRuntime(route)) : false;
|
|
899
943
|
return __fallbackRenderer.renderNotFound(route, isRscRequest, request, matchedParams, scriptNonce, middlewareContext, { isEdgeRuntime: __isEdge });
|
|
900
944
|
},
|
|
901
945
|
${hasPagesDir ? `async renderPagesFallback({ allowRscDocumentFallback, appRouteMatch, isDataRequest, isRscRequest, matchKind, middlewareContext, pathname, pagesDataRequest, request, url }) {
|
|
@@ -74,6 +74,7 @@ function registerRouteModules(routes, imports) {
|
|
|
74
74
|
if (slot.pagePath) imports.getLazyLoaderVar(slot.pagePath);
|
|
75
75
|
if (slot.defaultPath) imports.getLazyLoaderVar(slot.defaultPath);
|
|
76
76
|
if (slot.layoutPath) imports.getLazyLoaderVar(slot.layoutPath);
|
|
77
|
+
for (const layoutPath of slot.configLayoutPaths ?? []) imports.getLazyLoaderVar(layoutPath);
|
|
77
78
|
if (slot.loadingPath) imports.getLazyLoaderVar(slot.loadingPath);
|
|
78
79
|
if (slot.errorPath) imports.getLazyLoaderVar(slot.errorPath);
|
|
79
80
|
for (const ir of slot.interceptingRoutes) {
|
|
@@ -112,6 +113,8 @@ function buildRouteEntries(routes, imports) {
|
|
|
112
113
|
slotId: ${JSON.stringify(ir.slotId ?? null)},
|
|
113
114
|
interceptLayouts: ${moduleArray(ir.layoutPaths.length)},
|
|
114
115
|
__loadInterceptLayouts: ${lazyLoaderArray(ir.layoutPaths, imports)},
|
|
116
|
+
interceptLayoutSegments: ${JSON.stringify(ir.layoutSegments ?? [])},
|
|
117
|
+
interceptBranchSegments: ${JSON.stringify(ir.branchSegments ?? [])},
|
|
115
118
|
page: null,
|
|
116
119
|
__pageLoader: ${imports.getLazyLoaderVar(ir.pagePath)},
|
|
117
120
|
params: ${JSON.stringify(ir.params)},
|
|
@@ -124,6 +127,8 @@ function buildRouteEntries(routes, imports) {
|
|
|
124
127
|
sourcePageSegments: ${JSON.stringify(ir.sourcePageSegments)},
|
|
125
128
|
interceptLayouts: ${moduleArray(ir.layoutPaths.length)},
|
|
126
129
|
__loadInterceptLayouts: ${lazyLoaderArray(ir.layoutPaths, imports)},
|
|
130
|
+
interceptLayoutSegments: ${JSON.stringify(ir.layoutSegments ?? [])},
|
|
131
|
+
interceptBranchSegments: ${JSON.stringify(ir.branchSegments ?? [])},
|
|
127
132
|
page: null,
|
|
128
133
|
__pageLoader: ${imports.getLazyLoaderVar(ir.pagePath)},
|
|
129
134
|
params: ${JSON.stringify(ir.params)},
|
|
@@ -137,6 +142,9 @@ function buildRouteEntries(routes, imports) {
|
|
|
137
142
|
__loadDefault: ${slot.defaultPath ? imports.getLazyLoaderVar(slot.defaultPath) : "null"},
|
|
138
143
|
layout: null,
|
|
139
144
|
__loadLayout: ${slot.layoutPath ? imports.getLazyLoaderVar(slot.layoutPath) : "null"},
|
|
145
|
+
configLayouts: ${moduleArray(slot.configLayoutPaths?.length ?? 0)},
|
|
146
|
+
__loadConfigLayouts: ${lazyLoaderArray(slot.configLayoutPaths ?? [], imports)},
|
|
147
|
+
configLayoutTreePositions: ${JSON.stringify(slot.configLayoutTreePositions ?? [])},
|
|
140
148
|
loading: null,
|
|
141
149
|
__loadLoading: ${slot.loadingPath ? imports.getLazyLoaderVar(slot.loadingPath) : "null"},
|
|
142
150
|
error: null,
|
|
@@ -2,6 +2,7 @@ import { normalizePathSeparators } from "../utils/path.js";
|
|
|
2
2
|
import { findFileWithExts } from "../routing/file-matcher.js";
|
|
3
3
|
import { patternToNextFormat } from "../routing/route-validation.js";
|
|
4
4
|
import { apiRouter, pagesRouter } from "../routing/pages-router.js";
|
|
5
|
+
import "./pages-entry-helpers.js";
|
|
5
6
|
//#region src/entries/pages-client-entry.ts
|
|
6
7
|
/**
|
|
7
8
|
* Pages Router client hydration entry generator.
|
|
@@ -3,6 +3,7 @@ import { findFileWithExts } from "../routing/file-matcher.js";
|
|
|
3
3
|
import { apiRouter, pagesRouter } from "../routing/pages-router.js";
|
|
4
4
|
import { resolveEntryPath } from "./runtime-entry-module.js";
|
|
5
5
|
import { isProxyFile } from "../server/middleware.js";
|
|
6
|
+
import "./pages-entry-helpers.js";
|
|
6
7
|
//#region src/entries/pages-server-entry.ts
|
|
7
8
|
/**
|
|
8
9
|
* Pages Router server entry generator.
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { detectPackageManager } from "./utils/project.js";
|
|
2
|
-
import { normalizePathSeparators, stripJsExtension, stripViteModuleQuery } from "./utils/path.js";
|
|
3
2
|
import { normalizePathnameForRouteMatchStrict } from "./routing/utils.js";
|
|
4
3
|
import { escapeRegExp } from "./utils/regex.js";
|
|
4
|
+
import { normalizePathSeparators, stripJsExtension, stripViteModuleQuery } from "./utils/path.js";
|
|
5
5
|
import { buildViteResolveExtensions, createValidFileMatcher, findFileWithExts, normalizeViteResolveExtensions } from "./routing/file-matcher.js";
|
|
6
6
|
import { apiRouter, invalidateRouteCache, matchRoute, pagesRouter } from "./routing/pages-router.js";
|
|
7
7
|
import { INTERNAL_HEADERS, NEXTJS_DEPLOYMENT_ID_HEADER, VINEXT_INTERNAL_HEADERS, VINEXT_MW_CTX_HEADER, VINEXT_TIMING_HEADER } from "./server/headers.js";
|
|
@@ -35,6 +35,7 @@ import { resolveAssetsDir } from "./utils/asset-prefix.js";
|
|
|
35
35
|
import { RESOLVED_VIRTUAL_GOOGLE_FONTS, VIRTUAL_GOOGLE_FONTS, createGoogleFontsPlugin, createLocalFontsPlugin, generateGoogleFontsVirtualModule, parseStaticObjectLiteral } from "./plugins/fonts.js";
|
|
36
36
|
import { getDepOptimizeNodeEnvOptions, getViteMajorVersion, serializeViteDefine } from "./utils/vite-version.js";
|
|
37
37
|
import { createRscCompatibilityId, findNextConfigPath, loadNextConfig, resolveNextConfig, resolveNextConfigInput } from "./config/next-config.js";
|
|
38
|
+
import { mergeServerExternalPackages } from "./config/server-external-packages.js";
|
|
38
39
|
import { isNextDataPathname, parseNextDataPathname } from "./server/pages-data-route.js";
|
|
39
40
|
import { precompressAssets } from "./build/precompress.js";
|
|
40
41
|
import { ensureAssetsIgnore } from "./build/assets-ignore.js";
|
|
@@ -85,7 +86,6 @@ import { pathToFileURL } from "node:url";
|
|
|
85
86
|
import { createHash, randomBytes, randomUUID } from "node:crypto";
|
|
86
87
|
import commonjs from "vite-plugin-commonjs";
|
|
87
88
|
import MagicString from "magic-string";
|
|
88
|
-
import tsconfigPaths from "vite-tsconfig-paths";
|
|
89
89
|
//#region src/index.ts
|
|
90
90
|
installSocketErrorBackstop();
|
|
91
91
|
function getCacheDirPrefix(cacheDir) {
|
|
@@ -138,6 +138,11 @@ function resolveOptionalDependency(projectRoot, specifier) {
|
|
|
138
138
|
} catch {}
|
|
139
139
|
return null;
|
|
140
140
|
}
|
|
141
|
+
async function loadVite7TsconfigPathsPlugin(projectRoot) {
|
|
142
|
+
const resolvedPath = resolveOptionalDependency(projectRoot, "vite-tsconfig-paths");
|
|
143
|
+
if (!resolvedPath) throw new Error("[vinext] Vite 7 requires the optional peer dependency vite-tsconfig-paths for tsconfig path alias support. Install vite-tsconfig-paths or upgrade to Vite 8.");
|
|
144
|
+
return (await import(pathToFileURL(resolvedPath).href)).default();
|
|
145
|
+
}
|
|
141
146
|
function resolveShimModulePath(shimsDir, moduleName) {
|
|
142
147
|
for (const ext of [
|
|
143
148
|
".ts",
|
|
@@ -303,6 +308,8 @@ const VIRTUAL_APP_SSR_ENTRY = "virtual:vinext-app-ssr-entry";
|
|
|
303
308
|
const RESOLVED_APP_SSR_ENTRY = "\0virtual:vinext-app-ssr-entry";
|
|
304
309
|
const VIRTUAL_APP_BROWSER_ENTRY = "virtual:vinext-app-browser-entry";
|
|
305
310
|
const RESOLVED_APP_BROWSER_ENTRY = "\0virtual:vinext-app-browser-entry";
|
|
311
|
+
const VIRTUAL_APP_CAPABILITIES = "virtual:vinext-app-capabilities";
|
|
312
|
+
const RESOLVED_APP_CAPABILITIES = "\0virtual:vinext-app-capabilities";
|
|
306
313
|
const RESOLVED_ROOT_PARAMS = "\0virtual:vinext-root-params";
|
|
307
314
|
/** Virtual module that registers config-driven cache adapters (see VinextOptions.cache). */
|
|
308
315
|
const RESOLVED_CACHE_ADAPTERS = "\0" + VIRTUAL_CACHE_ADAPTERS;
|
|
@@ -332,6 +339,7 @@ function createStaticImageAsset(imagePath) {
|
|
|
332
339
|
*/
|
|
333
340
|
const _shimsDir = normalizePathSeparators(path.resolve(__dirname, "shims")) + "/";
|
|
334
341
|
const _fontGoogleShimPath = resolveShimModulePath(_shimsDir, "font-google");
|
|
342
|
+
const _appBrowserServerActionClientPath = resolveShimModulePath(normalizePathSeparators(path.resolve(__dirname, "server")), "app-browser-server-action-client");
|
|
335
343
|
const _appRscHandlerPath = resolveShimModulePath(normalizePathSeparators(path.resolve(__dirname, "server")), "app-rsc-handler");
|
|
336
344
|
const _canExternalizeAppRscHandler = _appRscHandlerPath.endsWith(".js");
|
|
337
345
|
function isValidExportIdentifier(name) {
|
|
@@ -531,6 +539,13 @@ function vinext(options = {}) {
|
|
|
531
539
|
throw new Error("vinext: Failed to load @vitejs/plugin-rsc.", { cause });
|
|
532
540
|
});
|
|
533
541
|
}
|
|
542
|
+
async function resolveHasServerActions(config) {
|
|
543
|
+
if (config.command !== "build" || !rscPluginModulePromise) return true;
|
|
544
|
+
const { getPluginApi } = await rscPluginModulePromise;
|
|
545
|
+
const pluginApi = getPluginApi(config);
|
|
546
|
+
if (!pluginApi || pluginApi.manager.isScanBuild) return true;
|
|
547
|
+
return Object.keys(pluginApi.manager.serverReferenceMetaMap).length > 0;
|
|
548
|
+
}
|
|
534
549
|
const reactOptions = options.react && options.react !== true ? options.react : void 0;
|
|
535
550
|
let reactPluginPromise = null;
|
|
536
551
|
if (options.react !== false) {
|
|
@@ -576,7 +591,7 @@ function vinext(options = {}) {
|
|
|
576
591
|
return mdxDelegatePromise;
|
|
577
592
|
}
|
|
578
593
|
const plugins = [
|
|
579
|
-
...viteMajorVersion >= 8 ? [] : [
|
|
594
|
+
...viteMajorVersion >= 8 ? [] : [loadVite7TsconfigPathsPlugin(earlyBaseDir)],
|
|
580
595
|
reactPluginPromise,
|
|
581
596
|
commonjs(),
|
|
582
597
|
...viteMajorVersion >= 8 ? [{
|
|
@@ -606,6 +621,10 @@ function vinext(options = {}) {
|
|
|
606
621
|
createMiddlewareServerOnlyPlugin({
|
|
607
622
|
getMiddlewarePath: () => middlewarePath,
|
|
608
623
|
getCanonicalMiddlewarePath: () => middlewarePath ? tryRealpathSync(middlewarePath) ?? middlewarePath : null,
|
|
624
|
+
isNeutralServerModule: (id) => {
|
|
625
|
+
const canonicalId = canonicalizePageTransformPath(id);
|
|
626
|
+
return isWithinPagesDirectory(canonicalId) && isApiPage(canonicalId);
|
|
627
|
+
},
|
|
609
628
|
serverOnlyShimPath: resolveShimModulePath(shimsDir, "server-only")
|
|
610
629
|
}),
|
|
611
630
|
dataUrlCssPlugin(),
|
|
@@ -681,6 +700,7 @@ function vinext(options = {}) {
|
|
|
681
700
|
defines[`process.env.${key}`] = JSON.stringify(value);
|
|
682
701
|
}
|
|
683
702
|
defines["process.env.__NEXT_ROUTER_BASEPATH"] = JSON.stringify(nextConfig.basePath);
|
|
703
|
+
defines["process.env.__VINEXT_HAS_PAGES_ROUTER"] = JSON.stringify(String(hasPagesDir));
|
|
684
704
|
defines["process.env.__NEXT_CLIENT_ROUTER_STATIC_STALETIME"] = JSON.stringify(String(nextConfig.staleTimes.static));
|
|
685
705
|
defines["process.env.__VINEXT_PREFETCH_INLINING"] = JSON.stringify(nextConfig.prefetchInlining ? "true" : "false");
|
|
686
706
|
defines["process.env.__NEXT_GESTURE_TRANSITION"] = JSON.stringify(nextConfig.gestureTransition);
|
|
@@ -800,6 +820,7 @@ function vinext(options = {}) {
|
|
|
800
820
|
hasUserMdxPlugin = pluginsFlat.some((p) => p && typeof p === "object" && "name" in p && typeof p.name === "string" && (p.name === "@mdx-js/rollup" || p.name === "mdx"));
|
|
801
821
|
if (!hasUserMdxPlugin && hasMdxFiles(root, hasAppDir ? appDir : null, hasPagesDir ? pagesDir : null)) await ensureMdxDelegate("detected");
|
|
802
822
|
const isSSR = !!config.build?.ssr;
|
|
823
|
+
const nextServerExternal = mergeServerExternalPackages(nextConfig?.serverExternalPackages, nextConfig?.transpilePackages);
|
|
803
824
|
const isMultiEnv = hasAppDir || hasCloudflarePlugin || hasNitroPlugin;
|
|
804
825
|
const hasBuildInput = getBuildBundlerOptions(config.build)?.input !== void 0;
|
|
805
826
|
const shouldInjectPlainPagesEnvironments = !hasAppDir && !hasCloudflarePlugin && !isSSR && !hasBuildInput;
|
|
@@ -850,7 +871,9 @@ function vinext(options = {}) {
|
|
|
850
871
|
"react",
|
|
851
872
|
"react-dom",
|
|
852
873
|
"react-dom/server",
|
|
853
|
-
"ipaddr.js"
|
|
874
|
+
"ipaddr.js",
|
|
875
|
+
...Array.isArray(config.ssr?.external) ? config.ssr.external : [],
|
|
876
|
+
...nextServerExternal
|
|
854
877
|
],
|
|
855
878
|
noExternal: true
|
|
856
879
|
} },
|
|
@@ -895,7 +918,6 @@ function vinext(options = {}) {
|
|
|
895
918
|
...cssModulesOverride
|
|
896
919
|
}
|
|
897
920
|
};
|
|
898
|
-
const nextServerExternal = nextConfig?.serverExternalPackages ?? [];
|
|
899
921
|
const userSsrExternal = Array.isArray(config.ssr?.external) ? [...config.ssr.external, ...nextServerExternal] : config.ssr?.external === true ? true : nextServerExternal;
|
|
900
922
|
const externalizeSsrReactInDev = env.command === "serve" && !hasCloudflarePlugin && !hasNitroPlugin;
|
|
901
923
|
const incomingExclude = config.optimizeDeps?.exclude ?? [];
|
|
@@ -1031,7 +1053,8 @@ function vinext(options = {}) {
|
|
|
1031
1053
|
"react",
|
|
1032
1054
|
"react-dom",
|
|
1033
1055
|
"react-dom/server",
|
|
1034
|
-
"ipaddr.js"
|
|
1056
|
+
"ipaddr.js",
|
|
1057
|
+
...nextServerExternal
|
|
1035
1058
|
],
|
|
1036
1059
|
noExternal: true
|
|
1037
1060
|
},
|
|
@@ -1102,7 +1125,7 @@ function vinext(options = {}) {
|
|
|
1102
1125
|
resolveId: {
|
|
1103
1126
|
filter: { id: /(?:next\/|vinext\/(?:shims\/|server\/app-rsc-handler)|virtual:vinext-|@vercel\/og(?:\.js)?$)/ },
|
|
1104
1127
|
handler(id, importer) {
|
|
1105
|
-
const cleanId = id.startsWith("\0") ? id.slice(1) : id;
|
|
1128
|
+
const cleanId = normalizePathSeparators(id.startsWith("\0") ? id.slice(1) : id);
|
|
1106
1129
|
if (cleanId === "vinext/server/app-rsc-handler") {
|
|
1107
1130
|
if (_canExternalizeAppRscHandler && this.environment?.name === "rsc" && this.environment.config?.command === "serve") return {
|
|
1108
1131
|
id: _appRscHandlerPath,
|
|
@@ -1114,18 +1137,19 @@ function vinext(options = {}) {
|
|
|
1114
1137
|
if (cleanId.startsWith("vinext/shims/")) return resolveShimModulePath(_shimsDir, stripJsExtension(stripViteModuleQuery(cleanId.slice(13))));
|
|
1115
1138
|
if (cleanId === VIRTUAL_SERVER_ENTRY) return RESOLVED_SERVER_ENTRY;
|
|
1116
1139
|
if (cleanId === VIRTUAL_CLIENT_ENTRY) return RESOLVED_CLIENT_ENTRY;
|
|
1117
|
-
if (cleanId.endsWith("/virtual:vinext-server-entry")
|
|
1118
|
-
if (cleanId.endsWith("/virtual:vinext-client-entry")
|
|
1140
|
+
if (cleanId.endsWith("/virtual:vinext-server-entry")) return RESOLVED_SERVER_ENTRY;
|
|
1141
|
+
if (cleanId.endsWith("/virtual:vinext-client-entry")) return RESOLVED_CLIENT_ENTRY;
|
|
1119
1142
|
if (cleanId === VIRTUAL_RSC_ENTRY) return RESOLVED_RSC_ENTRY;
|
|
1120
1143
|
if (cleanId === VIRTUAL_APP_SSR_ENTRY) return RESOLVED_APP_SSR_ENTRY;
|
|
1121
1144
|
if (cleanId === VIRTUAL_APP_BROWSER_ENTRY) return RESOLVED_APP_BROWSER_ENTRY;
|
|
1145
|
+
if (cleanId === VIRTUAL_APP_CAPABILITIES) return RESOLVED_APP_CAPABILITIES;
|
|
1122
1146
|
if (cleanId === "next/root-params" || cleanId === "next/root-params.js") return RESOLVED_ROOT_PARAMS;
|
|
1123
|
-
if (cleanId === "virtual:vinext-cache-adapters" || cleanId.endsWith("/virtual:vinext-cache-adapters")
|
|
1147
|
+
if (cleanId === "virtual:vinext-cache-adapters" || cleanId.endsWith("/virtual:vinext-cache-adapters")) return RESOLVED_CACHE_ADAPTERS;
|
|
1124
1148
|
if (cleanId.startsWith("virtual:vinext-google-fonts?")) return RESOLVED_VIRTUAL_GOOGLE_FONTS + cleanId.slice(VIRTUAL_GOOGLE_FONTS.length);
|
|
1125
|
-
if (cleanId.endsWith("/virtual:vinext-rsc-entry")
|
|
1126
|
-
if (cleanId.endsWith("/virtual:vinext-app-ssr-entry")
|
|
1127
|
-
if (cleanId.endsWith("/virtual:vinext-app-browser-entry")
|
|
1128
|
-
if (cleanId.includes("/virtual:vinext-google-fonts?")
|
|
1149
|
+
if (cleanId.endsWith("/virtual:vinext-rsc-entry")) return RESOLVED_RSC_ENTRY;
|
|
1150
|
+
if (cleanId.endsWith("/virtual:vinext-app-ssr-entry")) return RESOLVED_APP_SSR_ENTRY;
|
|
1151
|
+
if (cleanId.endsWith("/virtual:vinext-app-browser-entry")) return RESOLVED_APP_BROWSER_ENTRY;
|
|
1152
|
+
if (cleanId.includes("/virtual:vinext-google-fonts?")) {
|
|
1129
1153
|
const queryIndex = cleanId.indexOf(VIRTUAL_GOOGLE_FONTS + "?");
|
|
1130
1154
|
return RESOLVED_VIRTUAL_GOOGLE_FONTS + cleanId.slice(queryIndex + VIRTUAL_GOOGLE_FONTS.length);
|
|
1131
1155
|
}
|
|
@@ -1139,12 +1163,7 @@ function vinext(options = {}) {
|
|
|
1139
1163
|
if (id === RESOLVED_RSC_ENTRY && hasAppDir) {
|
|
1140
1164
|
const routes = await appRouter(appDir, nextConfig?.pageExtensions, fileMatcher);
|
|
1141
1165
|
const metaRoutes = scanMetadataFiles(appDir);
|
|
1142
|
-
|
|
1143
|
-
if (this.environment?.config.command === "build" && rscPluginModulePromise) {
|
|
1144
|
-
const { getPluginApi } = await rscPluginModulePromise;
|
|
1145
|
-
const pluginApi = getPluginApi(this.environment.config);
|
|
1146
|
-
if (pluginApi && !pluginApi.manager.isScanBuild) hasServerActions = Object.keys(pluginApi.manager.serverReferenceMetaMap).length > 0;
|
|
1147
|
-
}
|
|
1166
|
+
const hasServerActions = await resolveHasServerActions(this.environment.config);
|
|
1148
1167
|
const globalErrorPath = findFileWithExts(appDir, "global-error", fileMatcher);
|
|
1149
1168
|
const globalNotFoundPath = findFileWithExts(appDir, "global-not-found", fileMatcher);
|
|
1150
1169
|
rscClassificationManifest = collectRouteClassificationManifest(routes);
|
|
@@ -1194,6 +1213,13 @@ function vinext(options = {}) {
|
|
|
1194
1213
|
}))] : [];
|
|
1195
1214
|
return generateBrowserEntry(graph.routes, graph.routeManifest, pagesPrefetchRoutes, nextConfig.rewrites);
|
|
1196
1215
|
}
|
|
1216
|
+
if (id === RESOLVED_APP_CAPABILITIES && hasAppDir) {
|
|
1217
|
+
const hasServerActions = await resolveHasServerActions(this.environment.config);
|
|
1218
|
+
return `
|
|
1219
|
+
export const hasServerActions = ${JSON.stringify(hasServerActions)};
|
|
1220
|
+
export const loadServerActionClient = ${hasServerActions ? `() => import(${JSON.stringify(_appBrowserServerActionClientPath)})` : "null"};
|
|
1221
|
+
`;
|
|
1222
|
+
}
|
|
1197
1223
|
if (id.startsWith("\0virtual:vinext-google-fonts?")) return generateGoogleFontsVirtualModule(id, _fontGoogleShimPath);
|
|
1198
1224
|
},
|
|
1199
1225
|
// @vitejs/plugin-rsc runs the RSC environment build in two phases:
|
package/dist/init.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { detectPackageManager, detectPackageManagerName, ensureESModule, hasAppDir, hasViteConfig, renameCJSConfigs } from "./utils/project.js";
|
|
2
2
|
import { formatReport, runCheck } from "./check.js";
|
|
3
|
+
import { normalizePathSeparators } from "./utils/path.js";
|
|
3
4
|
import { createRequire } from "node:module";
|
|
4
5
|
import fs from "node:fs";
|
|
5
6
|
import path from "node:path";
|
|
@@ -176,7 +177,7 @@ function updateGitignore(root) {
|
|
|
176
177
|
return true;
|
|
177
178
|
}
|
|
178
179
|
async function init(options) {
|
|
179
|
-
const root = path.resolve(options.root);
|
|
180
|
+
const root = normalizePathSeparators(path.resolve(options.root));
|
|
180
181
|
const port = options.port ?? 3001;
|
|
181
182
|
const exec = options._exec ?? ((cmd, opts) => {
|
|
182
183
|
const [program, ...args] = cmd.split(" ");
|
|
@@ -2,8 +2,8 @@ import { Plugin } from "vite";
|
|
|
2
2
|
|
|
3
3
|
//#region src/plugins/middleware-server-only.d.ts
|
|
4
4
|
/**
|
|
5
|
-
* Allow `import 'server-only'` from
|
|
6
|
-
* from
|
|
5
|
+
* Allow `import 'server-only'` from neutral server targets (and any module
|
|
6
|
+
* reachable from them) in the SSR environment.
|
|
7
7
|
*
|
|
8
8
|
* Background: middleware runs server-side, so importing `server-only` is
|
|
9
9
|
* semantically correct. However, vinext bundles middleware into the SSR
|
|
@@ -13,9 +13,9 @@ import { Plugin } from "vite";
|
|
|
13
13
|
*
|
|
14
14
|
* 'server-only' cannot be imported in client build ('ssr' environment)
|
|
15
15
|
*
|
|
16
|
-
* Next.js solves this with webpack `issuerLayer` rules: middleware
|
|
17
|
-
*
|
|
18
|
-
* is aliased to a no-op while `client-only` still errors. See
|
|
16
|
+
* Next.js solves this with webpack `issuerLayer` rules: middleware,
|
|
17
|
+
* instrumentation, and Pages API routes sit in server-only or neutral layers
|
|
18
|
+
* where `server-only` is aliased to a no-op while `client-only` still errors. See
|
|
19
19
|
* packages/next/src/build/webpack-config.ts ("Alias server-only and
|
|
20
20
|
* client-only to proper exports based on bundling layers")
|
|
21
21
|
*
|
|
@@ -23,7 +23,8 @@ import { Plugin } from "vite";
|
|
|
23
23
|
* the behavior with import-chain taint tracking:
|
|
24
24
|
*
|
|
25
25
|
* 1. Seed a `tainted` set with the middleware entry path (and its
|
|
26
|
-
* canonical realpath)
|
|
26
|
+
* canonical realpath), and recognize other neutral server entry modules
|
|
27
|
+
* such as Pages API routes through `isNeutralServerModule`.
|
|
27
28
|
* 2. For every resolveId call from a tainted importer, resolve the import
|
|
28
29
|
* via `this.resolve(..., { skipSelf: true })` and add the resolved id
|
|
29
30
|
* to the tainted set. This propagates the taint along the import graph
|
|
@@ -47,6 +48,7 @@ import { Plugin } from "vite";
|
|
|
47
48
|
declare function createMiddlewareServerOnlyPlugin(options: {
|
|
48
49
|
getMiddlewarePath: () => string | null;
|
|
49
50
|
getCanonicalMiddlewarePath: () => string | null;
|
|
51
|
+
isNeutralServerModule?: (id: string) => boolean;
|
|
50
52
|
serverOnlyShimPath: string;
|
|
51
53
|
}): Plugin;
|
|
52
54
|
//#endregion
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { normalizePathSeparators } from "../utils/path.js";
|
|
2
2
|
//#region src/plugins/middleware-server-only.ts
|
|
3
3
|
/**
|
|
4
|
-
* Allow `import 'server-only'` from
|
|
5
|
-
* from
|
|
4
|
+
* Allow `import 'server-only'` from neutral server targets (and any module
|
|
5
|
+
* reachable from them) in the SSR environment.
|
|
6
6
|
*
|
|
7
7
|
* Background: middleware runs server-side, so importing `server-only` is
|
|
8
8
|
* semantically correct. However, vinext bundles middleware into the SSR
|
|
@@ -12,9 +12,9 @@ import { normalizePathSeparators } from "../utils/path.js";
|
|
|
12
12
|
*
|
|
13
13
|
* 'server-only' cannot be imported in client build ('ssr' environment)
|
|
14
14
|
*
|
|
15
|
-
* Next.js solves this with webpack `issuerLayer` rules: middleware
|
|
16
|
-
*
|
|
17
|
-
* is aliased to a no-op while `client-only` still errors. See
|
|
15
|
+
* Next.js solves this with webpack `issuerLayer` rules: middleware,
|
|
16
|
+
* instrumentation, and Pages API routes sit in server-only or neutral layers
|
|
17
|
+
* where `server-only` is aliased to a no-op while `client-only` still errors. See
|
|
18
18
|
* packages/next/src/build/webpack-config.ts ("Alias server-only and
|
|
19
19
|
* client-only to proper exports based on bundling layers")
|
|
20
20
|
*
|
|
@@ -22,7 +22,8 @@ import { normalizePathSeparators } from "../utils/path.js";
|
|
|
22
22
|
* the behavior with import-chain taint tracking:
|
|
23
23
|
*
|
|
24
24
|
* 1. Seed a `tainted` set with the middleware entry path (and its
|
|
25
|
-
* canonical realpath)
|
|
25
|
+
* canonical realpath), and recognize other neutral server entry modules
|
|
26
|
+
* such as Pages API routes through `isNeutralServerModule`.
|
|
26
27
|
* 2. For every resolveId call from a tainted importer, resolve the import
|
|
27
28
|
* via `this.resolve(..., { skipSelf: true })` and add the resolved id
|
|
28
29
|
* to the tainted set. This propagates the taint along the import graph
|
|
@@ -72,7 +73,7 @@ function createMiddlewareServerOnlyPlugin(options) {
|
|
|
72
73
|
async handler(id, importer, opts) {
|
|
73
74
|
if (this.environment?.name === "rsc") return;
|
|
74
75
|
if (!importer) return;
|
|
75
|
-
if (!isTainted(importer)) return;
|
|
76
|
+
if (!isTainted(importer) && !options.isNeutralServerModule?.(canonicalizeId(importer))) return;
|
|
76
77
|
if (id === "server-only") return {
|
|
77
78
|
id: options.serverOnlyShimPath,
|
|
78
79
|
moduleSideEffects: false
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { normalizePathSeparators } from "../utils/path.js";
|
|
2
1
|
import { escapeRegExp } from "../utils/regex.js";
|
|
2
|
+
import { normalizePathSeparators } from "../utils/path.js";
|
|
3
3
|
import { VIRTUAL_MODULE_ID_RE } from "../utils/virtual-module.js";
|
|
4
4
|
import { getAstName } from "./ast-utils.js";
|
|
5
5
|
import { createRequire } from "node:module";
|
|
@@ -23,7 +23,9 @@ type InterceptingRoute = {
|
|
|
23
23
|
sourceMatchPattern: string; /** Absolute path to the intercepting page component */
|
|
24
24
|
pagePath: string; /** Filesystem segments from app/ root to the intercepting page directory. */
|
|
25
25
|
sourcePageSegments?: string[]; /** Absolute layout paths inside the intercepting route tree, outermost to innermost */
|
|
26
|
-
layoutPaths: string[]; /**
|
|
26
|
+
layoutPaths: string[]; /** Normalized branch segments accumulated at each intercept layout. */
|
|
27
|
+
layoutSegments?: string[][]; /** Full normalized interception branch segments through the page. */
|
|
28
|
+
branchSegments?: string[]; /** Parameter names for dynamic segments */
|
|
27
29
|
params: string[];
|
|
28
30
|
/**
|
|
29
31
|
* Synthetic page-carrier slot id for sibling (slot-less) interception.
|
|
@@ -40,7 +42,9 @@ type ParallelSlot = {
|
|
|
40
42
|
hasPage: boolean; /** Absolute path to the slot's page component */
|
|
41
43
|
pagePath: string | null; /** Absolute path to the slot's default.tsx fallback */
|
|
42
44
|
defaultPath: string | null; /** Absolute path to the slot's layout component (wraps slot content) */
|
|
43
|
-
layoutPath: string | null; /**
|
|
45
|
+
layoutPath: string | null; /** Nested active-branch layouts whose exports contribute route config. */
|
|
46
|
+
configLayoutPaths?: string[]; /** Tree positions of configLayoutPaths relative to the slot root. */
|
|
47
|
+
configLayoutTreePositions?: number[]; /** Absolute path to the slot's loading component */
|
|
44
48
|
loadingPath: string | null; /** Absolute path to the slot's error component */
|
|
45
49
|
errorPath: string | null; /** Intercepting routes within this slot */
|
|
46
50
|
interceptingRoutes: InterceptingRoute[];
|