vinext 0.1.2 → 0.1.4
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/build/client-build-config.d.ts +11 -2
- package/dist/build/client-build-config.js +17 -6
- package/dist/build/prerender.d.ts +9 -1
- package/dist/build/prerender.js +42 -12
- package/dist/build/run-prerender.d.ts +10 -2
- package/dist/build/run-prerender.js +15 -1
- package/dist/client/app-nav-failure-handler.d.ts +8 -0
- package/dist/client/app-nav-failure-handler.js +44 -0
- package/dist/client/pages-router-link-navigation.d.ts +33 -7
- package/dist/client/pages-router-link-navigation.js +32 -2
- package/dist/client/vinext-next-data.d.ts +18 -1
- package/dist/client/vinext-next-data.js +2 -0
- package/dist/client/window-next.d.ts +2 -1
- package/dist/client/window-next.js +12 -1
- package/dist/cloudflare/src/cache/cdn-adapter.runtime.js +6 -1
- package/dist/config/config-matchers.d.ts +11 -1
- package/dist/config/config-matchers.js +87 -16
- package/dist/config/next-config.d.ts +46 -4
- package/dist/config/next-config.js +147 -48
- package/dist/config/tsconfig-paths.js +14 -1
- package/dist/deploy.d.ts +30 -11
- package/dist/deploy.js +200 -112
- package/dist/entries/app-browser-entry.d.ts +9 -3
- package/dist/entries/app-browser-entry.js +21 -3
- package/dist/entries/app-rsc-entry.d.ts +2 -0
- package/dist/entries/app-rsc-entry.js +65 -5
- package/dist/entries/app-rsc-manifest.js +2 -0
- package/dist/entries/app-ssr-entry.js +1 -1
- package/dist/entries/pages-client-entry.js +66 -20
- package/dist/entries/pages-server-entry.js +47 -31
- package/dist/index.js +417 -102
- package/dist/plugins/dynamic-preload-metadata.js +2 -4
- package/dist/plugins/extensionless-dynamic-import.d.ts +6 -0
- package/dist/plugins/extensionless-dynamic-import.js +152 -0
- package/dist/plugins/fonts.js +5 -4
- package/dist/plugins/optimize-imports.d.ts +2 -1
- package/dist/plugins/optimize-imports.js +11 -9
- package/dist/plugins/postcss.js +7 -7
- package/dist/plugins/strip-server-exports.d.ts +9 -7
- package/dist/plugins/strip-server-exports.js +493 -46
- package/dist/plugins/typeof-window.d.ts +14 -0
- package/dist/plugins/typeof-window.js +150 -0
- package/dist/routing/app-route-graph.d.ts +2 -1
- package/dist/routing/app-route-graph.js +46 -16
- package/dist/routing/file-matcher.d.ts +10 -1
- package/dist/routing/file-matcher.js +22 -1
- package/dist/routing/pages-router.js +3 -3
- package/dist/routing/utils.d.ts +35 -6
- package/dist/routing/utils.js +59 -7
- package/dist/server/api-handler.d.ts +6 -1
- package/dist/server/api-handler.js +21 -15
- package/dist/server/app-browser-action-result.d.ts +19 -6
- package/dist/server/app-browser-action-result.js +20 -11
- package/dist/server/app-browser-entry.js +175 -91
- package/dist/server/app-browser-error.d.ts +10 -6
- package/dist/server/app-browser-error.js +43 -8
- package/dist/server/app-browser-hydration.d.ts +2 -0
- package/dist/server/app-browser-hydration.js +1 -0
- package/dist/server/app-browser-navigation-controller.d.ts +5 -3
- package/dist/server/app-browser-navigation-controller.js +23 -2
- package/dist/server/app-browser-server-action-navigation.d.ts +6 -0
- package/dist/server/app-browser-server-action-navigation.js +9 -0
- package/dist/server/app-browser-state.d.ts +1 -1
- package/dist/server/app-browser-state.js +19 -11
- package/dist/server/app-browser-stream.js +86 -43
- package/dist/server/app-browser-visible-commit.d.ts +1 -1
- package/dist/server/app-elements-wire.d.ts +6 -1
- package/dist/server/app-elements-wire.js +14 -4
- package/dist/server/app-elements.d.ts +2 -2
- package/dist/server/app-elements.js +2 -2
- package/dist/server/app-fallback-renderer.d.ts +1 -0
- package/dist/server/app-fallback-renderer.js +3 -1
- package/dist/server/app-optimistic-routing.js +2 -2
- package/dist/server/app-page-boundary-render.d.ts +1 -0
- package/dist/server/app-page-boundary-render.js +27 -14
- package/dist/server/app-page-cache-render.d.ts +53 -0
- package/dist/server/app-page-cache-render.js +91 -0
- package/dist/server/app-page-cache.d.ts +16 -2
- package/dist/server/app-page-cache.js +62 -1
- package/dist/server/app-page-dispatch.d.ts +26 -0
- package/dist/server/app-page-dispatch.js +149 -92
- package/dist/server/app-page-element-builder.d.ts +1 -0
- package/dist/server/app-page-element-builder.js +5 -2
- package/dist/server/app-page-execution.d.ts +6 -1
- package/dist/server/app-page-execution.js +21 -1
- package/dist/server/app-page-probe.d.ts +1 -0
- package/dist/server/app-page-probe.js +4 -0
- package/dist/server/app-page-render-observation.d.ts +3 -1
- package/dist/server/app-page-render-observation.js +17 -1
- package/dist/server/app-page-render.d.ts +12 -1
- package/dist/server/app-page-render.js +42 -4
- package/dist/server/app-page-request.d.ts +2 -0
- package/dist/server/app-page-request.js +2 -1
- package/dist/server/app-page-route-wiring.d.ts +3 -1
- package/dist/server/app-page-route-wiring.js +14 -5
- package/dist/server/app-page-stream.d.ts +15 -3
- package/dist/server/app-page-stream.js +11 -5
- package/dist/server/app-pages-bridge.d.ts +23 -1
- package/dist/server/app-pages-bridge.js +26 -17
- package/dist/server/app-ppr-fallback-shell-render.d.ts +17 -0
- package/dist/server/app-ppr-fallback-shell-render.js +26 -0
- package/dist/server/app-ppr-fallback-shell.d.ts +13 -1
- package/dist/server/app-ppr-fallback-shell.js +8 -1
- package/dist/server/app-route-handler-dispatch.js +9 -2
- package/dist/server/app-route-handler-policy.d.ts +1 -0
- package/dist/server/app-router-entry.js +5 -0
- package/dist/server/app-rsc-cache-busting.js +2 -0
- package/dist/server/app-rsc-handler.d.ts +28 -0
- package/dist/server/app-rsc-handler.js +195 -59
- package/dist/server/app-rsc-route-matching.d.ts +3 -0
- package/dist/server/app-rsc-route-matching.js +8 -2
- package/dist/server/app-segment-config.d.ts +9 -1
- package/dist/server/app-segment-config.js +12 -3
- package/dist/server/app-server-action-execution.d.ts +1 -0
- package/dist/server/app-server-action-execution.js +47 -15
- package/dist/server/app-ssr-entry.d.ts +2 -0
- package/dist/server/app-ssr-entry.js +84 -39
- package/dist/server/before-interactive-head.d.ts +17 -0
- package/dist/server/before-interactive-head.js +35 -0
- package/dist/server/cache-control.js +4 -0
- package/dist/server/csp.js +1 -4
- package/dist/server/dev-server.d.ts +2 -2
- package/dist/server/dev-server.js +321 -83
- package/dist/server/hybrid-route-priority.d.ts +22 -0
- package/dist/server/hybrid-route-priority.js +33 -0
- package/dist/server/image-optimization.d.ts +18 -9
- package/dist/server/image-optimization.js +37 -23
- package/dist/server/implicit-tags.d.ts +2 -1
- package/dist/server/implicit-tags.js +4 -1
- package/dist/server/middleware-matcher.js +12 -3
- package/dist/server/middleware-runtime.d.ts +3 -4
- package/dist/server/middleware-runtime.js +2 -0
- package/dist/server/navigation-planner.d.ts +135 -41
- package/dist/server/navigation-planner.js +138 -0
- package/dist/server/navigation-trace.d.ts +9 -1
- package/dist/server/navigation-trace.js +9 -1
- package/dist/server/operation-token.d.ts +40 -0
- package/dist/server/operation-token.js +85 -0
- package/dist/server/pages-api-route.d.ts +6 -0
- package/dist/server/pages-api-route.js +13 -2
- package/dist/server/pages-asset-tags.d.ts +2 -1
- package/dist/server/pages-asset-tags.js +6 -2
- package/dist/server/pages-data-route.d.ts +9 -2
- package/dist/server/pages-data-route.js +18 -6
- package/dist/server/pages-dev-module-url.d.ts +4 -0
- package/dist/server/pages-dev-module-url.js +15 -0
- package/dist/server/pages-document-initial-props.d.ts +4 -15
- package/dist/server/pages-document-initial-props.js +27 -56
- package/dist/server/pages-get-initial-props.d.ts +54 -4
- package/dist/server/pages-get-initial-props.js +43 -1
- package/dist/server/pages-i18n.js +2 -2
- package/dist/server/pages-node-compat.js +2 -2
- package/dist/server/pages-page-data.d.ts +11 -2
- package/dist/server/pages-page-data.js +207 -34
- package/dist/server/pages-page-handler.d.ts +4 -2
- package/dist/server/pages-page-handler.js +62 -23
- package/dist/server/pages-page-response.d.ts +4 -1
- package/dist/server/pages-page-response.js +11 -8
- package/dist/server/pages-readiness.js +1 -1
- package/dist/server/pages-request-pipeline.d.ts +8 -7
- package/dist/server/pages-request-pipeline.js +126 -47
- package/dist/server/pregenerated-concrete-paths.d.ts +1 -17
- package/dist/server/pregenerated-concrete-paths.js +2 -19
- package/dist/server/prerender-manifest.d.ts +33 -0
- package/dist/server/prerender-manifest.js +54 -0
- package/dist/server/prerender-route-params.d.ts +1 -2
- package/dist/server/prod-server.d.ts +3 -1
- package/dist/server/prod-server.js +50 -13
- package/dist/server/request-pipeline.d.ts +3 -15
- package/dist/server/request-pipeline.js +58 -47
- package/dist/server/rsc-stream-hints.d.ts +5 -1
- package/dist/server/rsc-stream-hints.js +6 -1
- package/dist/server/seed-cache.js +10 -18
- package/dist/server/static-file-cache.js +16 -4
- package/dist/shims/app-router-scroll-state.d.ts +3 -1
- package/dist/shims/app-router-scroll-state.js +14 -2
- package/dist/shims/app-router-scroll.d.ts +3 -0
- package/dist/shims/app-router-scroll.js +28 -18
- package/dist/shims/before-interactive-context.d.ts +14 -3
- package/dist/shims/cache-runtime.js +3 -2
- package/dist/shims/cache.d.ts +1 -0
- package/dist/shims/cache.js +1 -1
- package/dist/shims/cdn-cache.d.ts +5 -5
- package/dist/shims/document.d.ts +15 -20
- package/dist/shims/document.js +5 -8
- package/dist/shims/dynamic-preload-chunks.js +6 -4
- package/dist/shims/error-boundary.d.ts +2 -0
- package/dist/shims/error-boundary.js +7 -0
- package/dist/shims/error.js +3 -2
- package/dist/shims/error.react-server.d.ts +9 -0
- package/dist/shims/error.react-server.js +6 -0
- package/dist/shims/fetch-cache.d.ts +3 -1
- package/dist/shims/fetch-cache.js +45 -20
- package/dist/shims/hash-scroll.js +6 -1
- package/dist/shims/headers.js +29 -4
- package/dist/shims/image.js +9 -2
- package/dist/shims/internal/als-registry.js +28 -1
- package/dist/shims/internal/app-route-detection.js +8 -17
- package/dist/shims/internal/hybrid-client-route-owner.d.ts +31 -0
- package/dist/shims/internal/hybrid-client-route-owner.js +143 -0
- package/dist/shims/internal/navigation-untracked.d.ts +35 -0
- package/dist/shims/internal/navigation-untracked.js +55 -0
- package/dist/shims/internal/pages-data-fetch-dedup.d.ts +6 -7
- package/dist/shims/internal/pages-data-fetch-dedup.js +67 -14
- package/dist/shims/internal/pages-data-target.d.ts +7 -2
- package/dist/shims/internal/pages-data-target.js +17 -8
- package/dist/shims/internal/pages-router-accessor.d.ts +19 -0
- package/dist/shims/internal/pages-router-accessor.js +13 -0
- package/dist/shims/internal/router-context.d.ts +2 -1
- package/dist/shims/internal/router-context.js +3 -1
- package/dist/shims/link.js +47 -19
- package/dist/shims/metadata.js +4 -4
- package/dist/shims/navigation.d.ts +8 -2
- package/dist/shims/navigation.js +63 -31
- package/dist/shims/ppr-fallback-shell.d.ts +5 -1
- package/dist/shims/ppr-fallback-shell.js +28 -7
- package/dist/shims/router.d.ts +18 -3
- package/dist/shims/router.js +512 -142
- package/dist/shims/script.js +8 -4
- package/dist/shims/server.d.ts +16 -1
- package/dist/shims/server.js +44 -12
- package/dist/shims/unified-request-context.js +1 -0
- package/dist/utils/built-asset-url.d.ts +4 -0
- package/dist/utils/built-asset-url.js +11 -0
- package/dist/utils/commonjs-loader.d.ts +16 -0
- package/dist/utils/commonjs-loader.js +100 -0
- package/dist/utils/deployment-id.d.ts +8 -0
- package/dist/utils/deployment-id.js +22 -0
- package/dist/utils/has-trailing-comma.d.ts +24 -0
- package/dist/utils/has-trailing-comma.js +62 -0
- package/dist/utils/html-limited-bots.d.ts +18 -1
- package/dist/utils/html-limited-bots.js +23 -1
- package/dist/utils/parse-cookie.d.ts +13 -0
- package/dist/utils/parse-cookie.js +52 -0
- package/dist/utils/path.d.ts +7 -1
- package/dist/utils/path.js +9 -1
- package/dist/utils/text-stream.d.ts +1 -1
- package/dist/utils/text-stream.js +2 -2
- package/dist/utils/vite-version.d.ts +12 -1
- package/dist/utils/vite-version.js +9 -1
- package/package.json +2 -2
- package/dist/shims/internal/parse-cookie-header.d.ts +0 -14
- package/dist/shims/internal/parse-cookie-header.js +0 -30
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { VINEXT_MW_CTX_HEADER, VINEXT_PRERENDER_ROUTE_PARAMS_HEADER, VINEXT_PRERENDER_SECRET_HEADER } from "../server/headers.js";
|
|
2
2
|
import { buildRequestHeadersFromMiddlewareResponse } from "../server/middleware-request-headers.js";
|
|
3
|
+
import { parseCookieHeader } from "../utils/parse-cookie.js";
|
|
3
4
|
//#region src/config/config-matchers.ts
|
|
4
5
|
/**
|
|
5
6
|
* Cache for compiled regex patterns in matchConfigPattern.
|
|
@@ -267,7 +268,7 @@ function isSafeRegex(pattern) {
|
|
|
267
268
|
*/
|
|
268
269
|
function safeRegExp(pattern, flags) {
|
|
269
270
|
if (!isSafeRegex(pattern)) {
|
|
270
|
-
console.warn(`[vinext]
|
|
271
|
+
console.warn(`[vinext] Rejecting potentially unsafe regex pattern (ReDoS risk): ${pattern}\n Patterns with nested quantifiers (e.g. (a+)+) can cause catastrophic backtracking.\n Simplify the pattern to avoid nested repetition.`);
|
|
271
272
|
return null;
|
|
272
273
|
}
|
|
273
274
|
try {
|
|
@@ -343,16 +344,7 @@ function shouldEvaluateRule(ruleBasePath, state) {
|
|
|
343
344
|
* Parse a Cookie header string into a key-value record.
|
|
344
345
|
*/
|
|
345
346
|
function parseCookies(cookieHeader) {
|
|
346
|
-
|
|
347
|
-
const cookies = {};
|
|
348
|
-
for (const part of cookieHeader.split(";")) {
|
|
349
|
-
const eq = part.indexOf("=");
|
|
350
|
-
if (eq === -1) continue;
|
|
351
|
-
const key = part.slice(0, eq).trim();
|
|
352
|
-
const value = part.slice(eq + 1).trim();
|
|
353
|
-
if (key) cookies[key] = value;
|
|
354
|
-
}
|
|
355
|
-
return cookies;
|
|
347
|
+
return parseCookieHeader(cookieHeader);
|
|
356
348
|
}
|
|
357
349
|
/**
|
|
358
350
|
* Build a RequestContext from a Web Request object.
|
|
@@ -442,8 +434,8 @@ function matchSingleCondition(condition, ctx) {
|
|
|
442
434
|
return _matchConditionValue(headerValue, condition.value);
|
|
443
435
|
}
|
|
444
436
|
case "cookie": {
|
|
437
|
+
if (!Object.hasOwn(ctx.cookies, condition.key)) return null;
|
|
445
438
|
const cookieValue = ctx.cookies[condition.key];
|
|
446
|
-
if (cookieValue === void 0) return null;
|
|
447
439
|
return _matchConditionValue(cookieValue, condition.value);
|
|
448
440
|
}
|
|
449
441
|
case "query": {
|
|
@@ -541,7 +533,7 @@ function matchConfigPattern(pathname, pattern) {
|
|
|
541
533
|
pathname = stripTrailingSlashForConfigMatch(pathname);
|
|
542
534
|
const catchAllAnchor = /:[\w-]+[*+]/.test(pattern);
|
|
543
535
|
const namedParamCount = (pattern.match(/:[\w-]+/g) || []).length;
|
|
544
|
-
if (pattern.includes("(") || pattern.includes("\\") || /:[\w-]+[*+][^/]/.test(pattern) || /:[\w-]+\./.test(pattern) || catchAllAnchor && namedParamCount > 1) try {
|
|
536
|
+
if (pattern.includes("(") || pattern.includes("\\") || /:[\w-]+[*+][^/]/.test(pattern) || /:[\w-]+\./.test(pattern) || /[^/]:[\w-]+/.test(pattern) || catchAllAnchor && namedParamCount > 1) try {
|
|
545
537
|
const compiled = getCachedRegex(_compiledPatternCache, pattern, () => {
|
|
546
538
|
const paramNames = [];
|
|
547
539
|
let regexStr = "";
|
|
@@ -716,15 +708,28 @@ function matchRewrite(pathname, rewrites, ctx, basePathState = _BASEPATH_DEFAULT
|
|
|
716
708
|
if (params) {
|
|
717
709
|
const conditionParams = rewrite.has || rewrite.missing ? collectConditionParams(rewrite.has, rewrite.missing, ctx) : _emptyParams();
|
|
718
710
|
if (!conditionParams) continue;
|
|
719
|
-
|
|
711
|
+
const rewriteParams = {
|
|
720
712
|
...params,
|
|
721
713
|
...conditionParams
|
|
722
|
-
}
|
|
714
|
+
};
|
|
715
|
+
return substituteAndSanitizeRewriteDestination(rewrite.destination, rewriteParams);
|
|
723
716
|
}
|
|
724
717
|
}
|
|
725
718
|
return null;
|
|
726
719
|
}
|
|
727
720
|
/**
|
|
721
|
+
* Check whether a rewrite source can match a pathname without evaluating its
|
|
722
|
+
* request-dependent `has` / `missing` conditions.
|
|
723
|
+
*
|
|
724
|
+
* Dev uses this only as a conservative preflight before middleware runs. The
|
|
725
|
+
* conditions may become true after middleware overrides request headers, so
|
|
726
|
+
* evaluating them against the original request would incorrectly skip the
|
|
727
|
+
* Pages request pipeline for file-looking paths.
|
|
728
|
+
*/
|
|
729
|
+
function matchesRewriteSource(pathname, rewrite, basePathState = _BASEPATH_DEFAULT) {
|
|
730
|
+
return shouldEvaluateRule(rewrite.basePath, basePathState) && matchConfigPattern(pathname, rewrite.source) !== null;
|
|
731
|
+
}
|
|
732
|
+
/**
|
|
728
733
|
* Substitute all matched route params into a redirect/rewrite destination.
|
|
729
734
|
*
|
|
730
735
|
* Handles repeated params (e.g. `/api/:id/:id`) and catch-all suffix forms
|
|
@@ -753,6 +758,72 @@ function substituteAndSanitizeDestination(destination, params) {
|
|
|
753
758
|
return sanitizeDestination(substituteDestinationParams(destination, params));
|
|
754
759
|
}
|
|
755
760
|
/**
|
|
761
|
+
* Match Next.js's rewrite-specific prepareDestination behavior: source params
|
|
762
|
+
* that are not consumed by the destination path/host are exposed to the target
|
|
763
|
+
* page through query.
|
|
764
|
+
*
|
|
765
|
+
* https://github.com/vercel/next.js/blob/canary/packages/next/src/shared/lib/router/utils/prepare-destination.ts
|
|
766
|
+
*/
|
|
767
|
+
function substituteAndSanitizeRewriteDestination(destination, params) {
|
|
768
|
+
const rewritten = substituteAndSanitizeDestination(destination, params);
|
|
769
|
+
if (!shouldAppendRewriteParamsToQuery(destination, params)) return rewritten;
|
|
770
|
+
const existingQueryKeys = getDestinationQueryKeys(destination);
|
|
771
|
+
const paramsToAppend = [];
|
|
772
|
+
for (const [key, value] of Object.entries(params)) {
|
|
773
|
+
if (key === "nextInternalLocale" || existingQueryKeys.has(key)) continue;
|
|
774
|
+
paramsToAppend.push([key, value]);
|
|
775
|
+
}
|
|
776
|
+
if (paramsToAppend.length === 0) return rewritten;
|
|
777
|
+
return appendQueryParams(rewritten, paramsToAppend);
|
|
778
|
+
}
|
|
779
|
+
function shouldAppendRewriteParamsToQuery(destination, params) {
|
|
780
|
+
const keys = Object.keys(params).filter((key) => key !== "nextInternalLocale");
|
|
781
|
+
if (keys.length === 0) return false;
|
|
782
|
+
return !destinationPathOrHostUsesParam(destination, keys);
|
|
783
|
+
}
|
|
784
|
+
function destinationPathOrHostUsesParam(destination, keys) {
|
|
785
|
+
const pathAndHost = getDestinationPathAndHost(destination);
|
|
786
|
+
if (!pathAndHost) return false;
|
|
787
|
+
for (const key of keys) {
|
|
788
|
+
const escapedKey = key.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
789
|
+
if (new RegExp(`:${escapedKey}([+*])?(?![A-Za-z0-9_])`).test(pathAndHost)) return true;
|
|
790
|
+
}
|
|
791
|
+
return false;
|
|
792
|
+
}
|
|
793
|
+
function getDestinationPathAndHost(destination) {
|
|
794
|
+
const hashIndex = destination.indexOf("#");
|
|
795
|
+
const beforeHash = hashIndex === -1 ? destination : destination.slice(0, hashIndex);
|
|
796
|
+
const hash = hashIndex === -1 ? "" : destination.slice(hashIndex);
|
|
797
|
+
const queryIndex = beforeHash.indexOf("?");
|
|
798
|
+
const beforeQuery = queryIndex === -1 ? beforeHash : beforeHash.slice(0, queryIndex);
|
|
799
|
+
const schemeMatch = /^[a-z][a-z0-9+.-]*:\/\//i.exec(beforeQuery);
|
|
800
|
+
if (!schemeMatch) return `${beforeQuery}${hash}`;
|
|
801
|
+
const withoutScheme = beforeQuery.slice(schemeMatch[0].length);
|
|
802
|
+
const slashIndex = withoutScheme.indexOf("/");
|
|
803
|
+
if (slashIndex === -1) return `${withoutScheme}${hash}`;
|
|
804
|
+
return `${withoutScheme.slice(0, slashIndex)}${withoutScheme.slice(slashIndex)}${hash}`;
|
|
805
|
+
}
|
|
806
|
+
function getDestinationQueryKeys(destination) {
|
|
807
|
+
const hashIndex = destination.indexOf("#");
|
|
808
|
+
const beforeHash = hashIndex === -1 ? destination : destination.slice(0, hashIndex);
|
|
809
|
+
const queryIndex = beforeHash.indexOf("?");
|
|
810
|
+
if (queryIndex === -1) return /* @__PURE__ */ new Set();
|
|
811
|
+
const query = beforeHash.slice(queryIndex + 1);
|
|
812
|
+
return new Set(new URLSearchParams(query).keys());
|
|
813
|
+
}
|
|
814
|
+
function appendQueryParams(url, params) {
|
|
815
|
+
const hashIndex = url.indexOf("#");
|
|
816
|
+
const beforeHash = hashIndex === -1 ? url : url.slice(0, hashIndex);
|
|
817
|
+
const hash = hashIndex === -1 ? "" : url.slice(hashIndex);
|
|
818
|
+
const queryIndex = beforeHash.indexOf("?");
|
|
819
|
+
const base = queryIndex === -1 ? beforeHash : beforeHash.slice(0, queryIndex);
|
|
820
|
+
const query = queryIndex === -1 ? "" : beforeHash.slice(queryIndex + 1);
|
|
821
|
+
const merged = new URLSearchParams(query);
|
|
822
|
+
for (const [key, value] of params) merged.append(key, value);
|
|
823
|
+
const search = merged.toString();
|
|
824
|
+
return `${base}${search ? `?${search}` : ""}${hash}`;
|
|
825
|
+
}
|
|
826
|
+
/**
|
|
756
827
|
* Sanitize a redirect/rewrite destination to collapse protocol-relative URLs.
|
|
757
828
|
*
|
|
758
829
|
* After parameter substitution, a destination like `/:path*` can become
|
|
@@ -972,4 +1043,4 @@ function applyLocaleToRoutes(routes, i18n, type, options = {}) {
|
|
|
972
1043
|
return out;
|
|
973
1044
|
}
|
|
974
1045
|
//#endregion
|
|
975
|
-
export { applyLocaleToRoutes, applyMiddlewareRequestHeaders, checkHasConditions, escapeHeaderSource, isExternalUrl, isSafeRegex, matchConfigPattern, matchHeaders, matchRedirect, matchRewrite, normalizeHost, parseCookies, preserveRedirectDestinationQuery, proxyExternalRequest, requestContextFromRequest, safeRegExp, sanitizeDestination };
|
|
1046
|
+
export { applyLocaleToRoutes, applyMiddlewareRequestHeaders, checkHasConditions, escapeHeaderSource, isExternalUrl, isSafeRegex, matchConfigPattern, matchHeaders, matchRedirect, matchRewrite, matchesRewriteSource, normalizeHost, parseCookies, preserveRedirectDestinationQuery, proxyExternalRequest, requestContextFromRequest, safeRegExp, sanitizeDestination };
|
|
@@ -117,14 +117,20 @@ type NextConfig = {
|
|
|
117
117
|
domains?: string[];
|
|
118
118
|
unoptimized?: boolean; /** Allowed device widths for image optimization. Defaults to Next.js defaults: [640, 750, 828, 1080, 1200, 1920, 2048, 3840] */
|
|
119
119
|
deviceSizes?: number[]; /** Allowed image sizes for fixed-width images. Defaults to Next.js defaults: [16, 32, 48, 64, 96, 128, 256, 384] */
|
|
120
|
-
imageSizes?: number[]; /**
|
|
120
|
+
imageSizes?: number[]; /** Allowed image qualities. When unset, any quality from 1-100 is permitted (matches Next.js). */
|
|
121
|
+
qualities?: number[]; /** Allow SVG images through the image optimization endpoint. SVG can contain scripts, so only enable if you trust all image sources. */
|
|
121
122
|
dangerouslyAllowSVG?: boolean; /** Allow image optimization for hostnames that resolve to private IP addresses. This is a security risk (SSRF) — only enable for private networks when you understand the risk. */
|
|
122
123
|
dangerouslyAllowLocalIP?: boolean; /** Content-Disposition header for image responses. Defaults to "inline". */
|
|
123
124
|
contentDispositionType?: "inline" | "attachment"; /** Content-Security-Policy header for image responses. Defaults to "script-src 'none'; frame-src 'none'; sandbox;" */
|
|
124
125
|
contentSecurityPolicy?: string;
|
|
125
126
|
}; /** Build output mode: 'export' for full static export, 'standalone' for single server */
|
|
126
127
|
output?: "export" | "standalone"; /** File extensions treated as routable pages/routes (Next.js pageExtensions) */
|
|
127
|
-
pageExtensions?: string[];
|
|
128
|
+
pageExtensions?: string[]; /** Turbopack-compatible module resolution options. */
|
|
129
|
+
turbopack?: {
|
|
130
|
+
resolveAlias?: Record<string, unknown>;
|
|
131
|
+
resolveExtensions?: string[];
|
|
132
|
+
[key: string]: unknown;
|
|
133
|
+
};
|
|
128
134
|
/**
|
|
129
135
|
* Module specifiers that are required for side effects on the client before
|
|
130
136
|
* hydration, in array order, ahead of the user's `instrumentation-client.{ts,js}`.
|
|
@@ -182,6 +188,7 @@ type NextConfig = {
|
|
|
182
188
|
defineServer?: Record<string, string | number | boolean>;
|
|
183
189
|
};
|
|
184
190
|
experimental?: {
|
|
191
|
+
/** Enables hard-navigation recovery when App Router navigation rendering fails. */appNavFailHandling?: boolean;
|
|
185
192
|
/**
|
|
186
193
|
* Enables the experimental App Router gesture transition API:
|
|
187
194
|
* `useRouter().experimental_gesturePush()`.
|
|
@@ -236,8 +243,11 @@ type ResolvedNextConfig = {
|
|
|
236
243
|
trailingSlash: boolean;
|
|
237
244
|
output: "" | "export" | "standalone";
|
|
238
245
|
pageExtensions: string[];
|
|
246
|
+
resolveExtensions: string[] | null;
|
|
247
|
+
serverResolveExtensions: string[] | null;
|
|
239
248
|
instrumentationClientInject: string[];
|
|
240
249
|
cacheComponents: boolean;
|
|
250
|
+
appNavFailHandling: boolean;
|
|
241
251
|
/**
|
|
242
252
|
* Enables the experimental App Router gesture transition API:
|
|
243
253
|
* `useRouter().experimental_gesturePush()`.
|
|
@@ -337,6 +347,13 @@ type ResolvedNextConfig = {
|
|
|
337
347
|
* `test/e2e/optimized-loading` test fixture.
|
|
338
348
|
*/
|
|
339
349
|
disableOptimizedLoading: boolean;
|
|
350
|
+
/**
|
|
351
|
+
* Mirrors Next.js `experimental.scrollRestoration`. When true, the Pages
|
|
352
|
+
* Router client takes ownership of browser history scroll restoration by
|
|
353
|
+
* setting `window.history.scrollRestoration = "manual"` and snapshotting
|
|
354
|
+
* scroll positions per history entry.
|
|
355
|
+
*/
|
|
356
|
+
scrollRestoration: boolean;
|
|
340
357
|
/**
|
|
341
358
|
* Build-time constant replacement map applied to BOTH client and server
|
|
342
359
|
* bundles. Sourced from `compiler.define` in next.config. Values are
|
|
@@ -378,6 +395,28 @@ type ResolvedNextConfig = {
|
|
|
378
395
|
dynamic: number;
|
|
379
396
|
static: number;
|
|
380
397
|
};
|
|
398
|
+
/**
|
|
399
|
+
* Mirrors Next.js `experimental.useLightningcss`. When `true`, switch
|
|
400
|
+
* Vite's CSS pipeline from PostCSS to lightningcss for both transforms
|
|
401
|
+
* and minification, so the user's `lightningCssFeatures` config takes
|
|
402
|
+
* effect (without this flag set, Next.js's own
|
|
403
|
+
* `lightningCssFeatures` option is also a no-op).
|
|
404
|
+
*
|
|
405
|
+
* @see https://nextjs.org/docs/app/api-reference/config/next-config-js/useLightningcss
|
|
406
|
+
*/
|
|
407
|
+
useLightningcss: boolean;
|
|
408
|
+
/**
|
|
409
|
+
* Resolved `experimental.lightningCssFeatures` from next.config, converted
|
|
410
|
+
* from dash-case feature names into the numeric bitmask form expected by
|
|
411
|
+
* the lightningcss `transform()` API (`include` / `exclude` options). When
|
|
412
|
+
* the user did not supply the option, both masks are `0` (a no-op).
|
|
413
|
+
*
|
|
414
|
+
* @see https://nextjs.org/docs/app/api-reference/config/next-config-js/lightningCssFeatures
|
|
415
|
+
*/
|
|
416
|
+
lightningCssFeatures: {
|
|
417
|
+
include: number;
|
|
418
|
+
exclude: number;
|
|
419
|
+
};
|
|
381
420
|
};
|
|
382
421
|
/**
|
|
383
422
|
* Whole-word substring check for any of the CJS-style globals that the
|
|
@@ -457,11 +496,14 @@ declare function normalizeAssetPrefix(value: unknown): string;
|
|
|
457
496
|
* resolve it once and share it — see `__VINEXT_SHARED_RSC_COMPATIBILITY_ID`.
|
|
458
497
|
*/
|
|
459
498
|
declare function createRscCompatibilityId(nextConfig: Pick<ResolvedNextConfig, "deploymentId">): string;
|
|
499
|
+
declare function lightningCssFeatureNamesToMask(names: readonly string[]): number;
|
|
460
500
|
/**
|
|
461
501
|
* Resolve a NextConfig into a fully-resolved ResolvedNextConfig.
|
|
462
502
|
* Awaits async functions for redirects/rewrites/headers.
|
|
463
503
|
*/
|
|
464
|
-
declare function resolveNextConfig(config: NextConfig | null, root?: string
|
|
504
|
+
declare function resolveNextConfig(config: NextConfig | null, root?: string, options?: {
|
|
505
|
+
dev?: boolean;
|
|
506
|
+
}): Promise<ResolvedNextConfig>;
|
|
465
507
|
/**
|
|
466
508
|
* Extract MDX compilation options (remark/rehype/recma plugins) from
|
|
467
509
|
* a Next.js config that uses @next/mdx.
|
|
@@ -489,4 +531,4 @@ declare function extractMdxOptions(config: NextConfig, root?: string): Promise<M
|
|
|
489
531
|
*/
|
|
490
532
|
declare function detectNextIntlConfig(root: string, resolved: ResolvedNextConfig): void;
|
|
491
533
|
//#endregion
|
|
492
|
-
export { HasCondition, MdxOptions, NextConfig, NextConfigInput, NextHeader, NextI18nConfig, NextRedirect, NextRewrite, PHASE_PRODUCTION_BUILD, ResolvedNextConfig, createRscCompatibilityId, detectNextIntlConfig, extractMdxOptions, findNextConfigPath, loadNextConfig, normalizeAssetPrefix, parseBodySizeLimit, reassignsModuleExports, referencesCjsGlobals, resolveNextConfig, resolveNextConfigInput };
|
|
534
|
+
export { HasCondition, MdxOptions, NextConfig, NextConfigInput, NextHeader, NextI18nConfig, NextRedirect, NextRewrite, PHASE_PRODUCTION_BUILD, ResolvedNextConfig, createRscCompatibilityId, detectNextIntlConfig, extractMdxOptions, findNextConfigPath, lightningCssFeatureNamesToMask, loadNextConfig, normalizeAssetPrefix, parseBodySizeLimit, reassignsModuleExports, referencesCjsGlobals, resolveNextConfig, resolveNextConfigInput };
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { normalizePageExtensions } from "../routing/file-matcher.js";
|
|
2
2
|
import { applyLocaleToRoutes, isExternalUrl } from "./config-matchers.js";
|
|
3
3
|
import { isUnknownRecord } from "../utils/record.js";
|
|
4
|
-
import { PHASE_DEVELOPMENT_SERVER, PHASE_PRODUCTION_BUILD } from "../shims/constants.js";
|
|
5
4
|
import { getHtmlLimitedBotRegex } from "../utils/html-limited-bots.js";
|
|
5
|
+
import { PHASE_DEVELOPMENT_SERVER, PHASE_PRODUCTION_BUILD } from "../shims/constants.js";
|
|
6
6
|
import { loadTsconfigResolutionForRoot } from "./tsconfig-paths.js";
|
|
7
7
|
import { getViteMajorVersion } from "../utils/vite-version.js";
|
|
8
|
+
import { loadCommonJsModule, shouldRetryAsCommonJs } from "../utils/commonjs-loader.js";
|
|
8
9
|
import { createRequire } from "node:module";
|
|
9
10
|
import fs from "node:fs";
|
|
10
11
|
import path from "node:path";
|
|
@@ -259,31 +260,16 @@ async function resolveNextConfigInput(config, phase = PHASE_DEVELOPMENT_SERVER)
|
|
|
259
260
|
*
|
|
260
261
|
* For `.cjs` (or `.js` in a non-type-module package) Node's loader picks the
|
|
261
262
|
* right format automatically and `require()` just works. For `.js` in a
|
|
262
|
-
* `"type": "module"` package,
|
|
263
|
-
*
|
|
264
|
-
* sibling temp `.cjs` (where the explicit extension forces CJS regardless of
|
|
265
|
-
* the parent type field) and require *that*. Relative imports inside the
|
|
266
|
-
* config still resolve against the original directory.
|
|
263
|
+
* `"type": "module"` package, retry through the shared in-memory CommonJS
|
|
264
|
+
* loader so nested local `.js` dependencies retain CommonJS semantics too.
|
|
267
265
|
*/
|
|
268
266
|
async function loadConfigViaRequire(configPath, root, phase) {
|
|
269
267
|
const require = createRequire(path.join(root, "package.json"));
|
|
270
268
|
try {
|
|
271
269
|
return await unwrapConfig(require(configPath), phase);
|
|
272
270
|
} catch (e) {
|
|
273
|
-
if (!
|
|
274
|
-
return await
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
async function loadConfigViaCjsTempCopy(configPath, root, phase) {
|
|
278
|
-
const dir = path.dirname(configPath);
|
|
279
|
-
const tmpPath = path.join(dir, `.vinext-next-config.${process.pid}.${Date.now()}.cjs`);
|
|
280
|
-
fs.copyFileSync(configPath, tmpPath);
|
|
281
|
-
try {
|
|
282
|
-
return await unwrapConfig(createRequire(path.join(root, "package.json"))(tmpPath), phase);
|
|
283
|
-
} finally {
|
|
284
|
-
try {
|
|
285
|
-
fs.unlinkSync(tmpPath);
|
|
286
|
-
} catch {}
|
|
271
|
+
if (!shouldRetryAsCommonJs(e, configPath)) throw e;
|
|
272
|
+
return await unwrapConfig(loadCommonJsModule(configPath), phase);
|
|
287
273
|
}
|
|
288
274
|
}
|
|
289
275
|
/**
|
|
@@ -454,6 +440,58 @@ function readStringArray(value) {
|
|
|
454
440
|
return Array.isArray(value) ? value.filter((item) => typeof item === "string") : [];
|
|
455
441
|
}
|
|
456
442
|
/**
|
|
443
|
+
* Convert lightningcss feature names from `experimental.lightningCssFeatures`
|
|
444
|
+
* into a numeric bitmask consumable by the `lightningcss` `transform()` /
|
|
445
|
+
* `bundle()` API (the `include` / `exclude` options).
|
|
446
|
+
*
|
|
447
|
+
* The mapping mirrors Next.js exactly so the same dash-case feature names
|
|
448
|
+
* accepted by `next.config` produce the same bits on both sides. See:
|
|
449
|
+
* - `.nextjs-ref/packages/next/src/server/config-shared.ts` (`LIGHTNINGCSS_FEATURE_NAMES`)
|
|
450
|
+
* - `.nextjs-ref/crates/next-core/src/next_config.rs` (`lightningcss_feature_names_to_mask`)
|
|
451
|
+
* - `lightningcss/node/targets.d.ts` (`Features` enum bits)
|
|
452
|
+
*
|
|
453
|
+
* Unknown names emit a warning (matching the Next.js Rust path, which errors;
|
|
454
|
+
* we warn instead so a stray name doesn't break the whole build).
|
|
455
|
+
*/
|
|
456
|
+
const LIGHTNINGCSS_FEATURE_BITS = {
|
|
457
|
+
nesting: 1,
|
|
458
|
+
"not-selector-list": 2,
|
|
459
|
+
"dir-selector": 4,
|
|
460
|
+
"lang-selector-list": 8,
|
|
461
|
+
"is-selector": 16,
|
|
462
|
+
"text-decoration-thickness-percent": 32,
|
|
463
|
+
"media-interval-syntax": 64,
|
|
464
|
+
"media-range-syntax": 128,
|
|
465
|
+
"custom-media-queries": 256,
|
|
466
|
+
"clamp-function": 512,
|
|
467
|
+
"color-function": 1024,
|
|
468
|
+
"oklab-colors": 2048,
|
|
469
|
+
"lab-colors": 4096,
|
|
470
|
+
"p3-colors": 8192,
|
|
471
|
+
"hex-alpha-colors": 16384,
|
|
472
|
+
"space-separated-color-notation": 32768,
|
|
473
|
+
"font-family-system-ui": 65536,
|
|
474
|
+
"double-position-gradients": 131072,
|
|
475
|
+
"vendor-prefixes": 262144,
|
|
476
|
+
"logical-properties": 524288,
|
|
477
|
+
"light-dark": 1048576,
|
|
478
|
+
selectors: 31,
|
|
479
|
+
"media-queries": 448,
|
|
480
|
+
colors: 1113088
|
|
481
|
+
};
|
|
482
|
+
function lightningCssFeatureNamesToMask(names) {
|
|
483
|
+
let mask = 0;
|
|
484
|
+
for (const name of names) {
|
|
485
|
+
const bit = LIGHTNINGCSS_FEATURE_BITS[name];
|
|
486
|
+
if (bit === void 0) {
|
|
487
|
+
console.warn(`[vinext] Unknown lightningcss feature name "${name}" in experimental.lightningCssFeatures — ignoring.`);
|
|
488
|
+
continue;
|
|
489
|
+
}
|
|
490
|
+
mask |= bit;
|
|
491
|
+
}
|
|
492
|
+
return mask;
|
|
493
|
+
}
|
|
494
|
+
/**
|
|
457
495
|
* Serialize a `compiler.define` / `compiler.defineServer` map into the
|
|
458
496
|
* Vite-friendly `Record<string, string>` shape where each value is already
|
|
459
497
|
* a JSON-encoded literal of source code. Entries whose values are not a
|
|
@@ -500,7 +538,7 @@ function resolveStaleTimes(experimental) {
|
|
|
500
538
|
* Resolve a NextConfig into a fully-resolved ResolvedNextConfig.
|
|
501
539
|
* Awaits async functions for redirects/rewrites/headers.
|
|
502
540
|
*/
|
|
503
|
-
async function resolveNextConfig(config, root = process.cwd()) {
|
|
541
|
+
async function resolveNextConfig(config, root = process.cwd(), options = {}) {
|
|
504
542
|
if (!config) {
|
|
505
543
|
const buildId = await resolveBuildId(void 0);
|
|
506
544
|
const deploymentId = resolveDeploymentId(void 0);
|
|
@@ -511,7 +549,10 @@ async function resolveNextConfig(config, root = process.cwd()) {
|
|
|
511
549
|
trailingSlash: false,
|
|
512
550
|
output: "",
|
|
513
551
|
pageExtensions: normalizePageExtensions(),
|
|
552
|
+
resolveExtensions: null,
|
|
553
|
+
serverResolveExtensions: null,
|
|
514
554
|
cacheComponents: false,
|
|
555
|
+
appNavFailHandling: false,
|
|
515
556
|
gestureTransition: false,
|
|
516
557
|
prefetchInlining: false,
|
|
517
558
|
redirects: [],
|
|
@@ -545,11 +586,17 @@ async function resolveNextConfig(config, root = process.cwd()) {
|
|
|
545
586
|
sassOptions: null,
|
|
546
587
|
removeConsole: false,
|
|
547
588
|
disableOptimizedLoading: false,
|
|
589
|
+
scrollRestoration: false,
|
|
548
590
|
compilerDefine: {},
|
|
549
591
|
compilerDefineServer: {},
|
|
550
592
|
instrumentationClientInject: [],
|
|
551
593
|
clientTraceMetadata: void 0,
|
|
552
|
-
staleTimes: { ...DEFAULT_STALE_TIMES }
|
|
594
|
+
staleTimes: { ...DEFAULT_STALE_TIMES },
|
|
595
|
+
useLightningcss: false,
|
|
596
|
+
lightningCssFeatures: {
|
|
597
|
+
include: 0,
|
|
598
|
+
exclude: 0
|
|
599
|
+
}
|
|
553
600
|
};
|
|
554
601
|
detectNextIntlConfig(root, resolved);
|
|
555
602
|
return resolved;
|
|
@@ -587,7 +634,7 @@ async function resolveNextConfig(config, root = process.cwd()) {
|
|
|
587
634
|
}
|
|
588
635
|
let headers = [];
|
|
589
636
|
if (config.headers) headers = await config.headers();
|
|
590
|
-
const webpackProbe = await probeWebpackConfig(config, root);
|
|
637
|
+
const webpackProbe = await probeWebpackConfig(config, root, options.dev ?? false);
|
|
591
638
|
const mdx = webpackProbe.mdx;
|
|
592
639
|
const aliases = {
|
|
593
640
|
...extractTurboAliases(config, root),
|
|
@@ -621,12 +668,22 @@ async function resolveNextConfig(config, root = process.cwd()) {
|
|
|
621
668
|
const serverExternalPackages = topLevelServerExternalPackages ?? legacyServerComponentsExternal;
|
|
622
669
|
if (experimental?.swcEnvOptions !== void 0) console.warn("[vinext] next.config option \"experimental.swcEnvOptions\" is not applicable and will be ignored (vinext uses Vite, not SWC). A Vite-compatible polyfill solution may be explored in the future.");
|
|
623
670
|
if (experimental?.rootParams !== void 0) console.warn("[vinext] `experimental.rootParams` is no longer needed, because `next/root-params` is available by default. You can remove it from next.config.(js|mjs|ts).");
|
|
671
|
+
const useLightningcss = experimental?.useLightningcss === true;
|
|
672
|
+
const rawLightningCssFeatures = readOptionalRecord(experimental?.lightningCssFeatures);
|
|
673
|
+
const lightningCssFeatures = {
|
|
674
|
+
include: lightningCssFeatureNamesToMask(readStringArray(rawLightningCssFeatures?.include)),
|
|
675
|
+
exclude: lightningCssFeatureNamesToMask(readStringArray(rawLightningCssFeatures?.exclude))
|
|
676
|
+
};
|
|
677
|
+
if (rawLightningCssFeatures && !useLightningcss) console.warn("[vinext] experimental.lightningCssFeatures is set but experimental.useLightningcss is not enabled. The lightningCssFeatures option has no effect without useLightningcss.");
|
|
624
678
|
if (experimental?.cachedNavigations === true && !config.cacheComponents) console.warn("[vinext] `experimental.cachedNavigations` requires `cacheComponents: true` to have any effect. Set `cacheComponents: true` in your next.config, or remove `experimental.cachedNavigations`.");
|
|
625
|
-
if (config.webpack !== void 0) if (mdx || Object.keys(webpackProbe.aliases).length > 0) console.warn("[vinext] next.config option \"webpack\" is only partially supported. vinext preserves resolve.alias
|
|
679
|
+
if (config.webpack !== void 0) if (mdx || Object.keys(webpackProbe.aliases).length > 0 || webpackProbe.resolveExtensionsCustomized) console.warn("[vinext] next.config option \"webpack\" is only partially supported. vinext preserves resolve.alias, resolve.extensions, and MDX loader settings, but other webpack customization is ignored");
|
|
626
680
|
else console.warn("[vinext] next.config option \"webpack\" is not yet supported and will be ignored");
|
|
627
681
|
const output = readOptionalString(config.output) ?? "";
|
|
628
682
|
if (output && output !== "export" && output !== "standalone") console.warn(`[vinext] Unknown output mode "${output}", ignoring`);
|
|
629
683
|
const pageExtensions = normalizePageExtensions(config.pageExtensions);
|
|
684
|
+
const experimentalTurbo = readOptionalRecord(experimental?.turbo);
|
|
685
|
+
const turbopack = readOptionalRecord(config.turbopack);
|
|
686
|
+
const resolveExtensions = Array.isArray(turbopack?.resolveExtensions) ? readStringArray(turbopack.resolveExtensions) : Array.isArray(experimentalTurbo?.resolveExtensions) ? readStringArray(experimentalTurbo.resolveExtensions) : null;
|
|
630
687
|
let i18n = null;
|
|
631
688
|
if (config.i18n) i18n = {
|
|
632
689
|
locales: config.i18n.locales,
|
|
@@ -654,8 +711,11 @@ async function resolveNextConfig(config, root = process.cwd()) {
|
|
|
654
711
|
trailingSlash: config.trailingSlash ?? false,
|
|
655
712
|
output: output === "export" || output === "standalone" ? output : "",
|
|
656
713
|
pageExtensions,
|
|
714
|
+
resolveExtensions: resolveExtensions ?? webpackProbe.resolveExtensions,
|
|
715
|
+
serverResolveExtensions: resolveExtensions ?? webpackProbe.serverResolveExtensions,
|
|
657
716
|
instrumentationClientInject: Array.isArray(config.instrumentationClientInject) ? config.instrumentationClientInject.filter((x) => typeof x === "string") : [],
|
|
658
717
|
cacheComponents: config.cacheComponents ?? false,
|
|
718
|
+
appNavFailHandling: experimental?.appNavFailHandling === true,
|
|
659
719
|
gestureTransition: experimental?.gestureTransition === true,
|
|
660
720
|
prefetchInlining,
|
|
661
721
|
redirects,
|
|
@@ -685,10 +745,13 @@ async function resolveNextConfig(config, root = process.cwd()) {
|
|
|
685
745
|
sassOptions: readOptionalRecord(config.sassOptions) ?? null,
|
|
686
746
|
removeConsole: config.compiler?.removeConsole === true ? true : isUnknownRecord(config.compiler?.removeConsole) ? { exclude: readStringArray(config.compiler.removeConsole.exclude) } : false,
|
|
687
747
|
disableOptimizedLoading: experimental?.disableOptimizedLoading === true,
|
|
748
|
+
scrollRestoration: experimental?.scrollRestoration === true,
|
|
688
749
|
compilerDefine: serializeCompilerDefine(config.compiler?.define),
|
|
689
750
|
compilerDefineServer: serializeCompilerDefine(config.compiler?.defineServer),
|
|
690
751
|
clientTraceMetadata: Array.isArray(experimental?.clientTraceMetadata) ? experimental.clientTraceMetadata.filter((value) => typeof value === "string") : void 0,
|
|
691
|
-
staleTimes: resolveStaleTimes(experimental)
|
|
752
|
+
staleTimes: resolveStaleTimes(experimental),
|
|
753
|
+
useLightningcss,
|
|
754
|
+
lightningCssFeatures
|
|
692
755
|
};
|
|
693
756
|
detectNextIntlConfig(root, resolved);
|
|
694
757
|
if (resolved.basePath !== "" && resolved.basePath !== "/" && resolved.assetPrefix === "") resolved.assetPrefix = resolved.basePath;
|
|
@@ -727,39 +790,75 @@ function extractTurboAliases(config, root) {
|
|
|
727
790
|
...normalizeAliasEntries(readOptionalRecord(topLevelTurbopack?.resolveAlias), root)
|
|
728
791
|
};
|
|
729
792
|
}
|
|
730
|
-
async function probeWebpackConfig(config, root) {
|
|
793
|
+
async function probeWebpackConfig(config, root, dev) {
|
|
731
794
|
if (typeof config.webpack !== "function") return {
|
|
732
795
|
aliases: {},
|
|
733
|
-
mdx: null
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
context: root,
|
|
738
|
-
resolve: { alias: {} },
|
|
739
|
-
module: { rules: mockModuleRules },
|
|
740
|
-
plugins: []
|
|
741
|
-
};
|
|
742
|
-
const mockOptions = {
|
|
743
|
-
defaultLoaders: { babel: { loader: "next-babel-loader" } },
|
|
744
|
-
isServer: false,
|
|
745
|
-
dev: false,
|
|
746
|
-
dir: root
|
|
796
|
+
mdx: null,
|
|
797
|
+
resolveExtensions: null,
|
|
798
|
+
serverResolveExtensions: null,
|
|
799
|
+
resolveExtensionsCustomized: false
|
|
747
800
|
};
|
|
748
801
|
try {
|
|
749
|
-
const
|
|
750
|
-
|
|
751
|
-
|
|
802
|
+
const clientProbe = await runWebpackConfigProbe(config, root, {
|
|
803
|
+
dev,
|
|
804
|
+
isServer: false
|
|
805
|
+
});
|
|
806
|
+
const serverProbe = await runWebpackConfigProbe(config, root, {
|
|
807
|
+
dev,
|
|
808
|
+
isServer: true,
|
|
809
|
+
nextRuntime: "nodejs"
|
|
810
|
+
});
|
|
811
|
+
invokeLoaderSideEffects(clientProbe.rules, root);
|
|
752
812
|
return {
|
|
753
|
-
aliases: normalizeAliasEntries(
|
|
754
|
-
mdx: extractMdxOptionsFromRules(rules)
|
|
813
|
+
aliases: normalizeAliasEntries(clientProbe.config.resolve?.alias, root),
|
|
814
|
+
mdx: extractMdxOptionsFromRules(clientProbe.rules),
|
|
815
|
+
resolveExtensions: clientProbe.resolveExtensions,
|
|
816
|
+
serverResolveExtensions: serverProbe.resolveExtensions,
|
|
817
|
+
resolveExtensionsCustomized: clientProbe.resolveExtensions !== null || serverProbe.resolveExtensions !== null
|
|
755
818
|
};
|
|
756
819
|
} catch {
|
|
757
820
|
return {
|
|
758
821
|
aliases: {},
|
|
759
|
-
mdx: null
|
|
822
|
+
mdx: null,
|
|
823
|
+
resolveExtensions: null,
|
|
824
|
+
serverResolveExtensions: null,
|
|
825
|
+
resolveExtensionsCustomized: false
|
|
760
826
|
};
|
|
761
827
|
}
|
|
762
828
|
}
|
|
829
|
+
const DEFAULT_WEBPACK_RESOLVE_EXTENSIONS = [
|
|
830
|
+
".js",
|
|
831
|
+
".mjs",
|
|
832
|
+
".tsx",
|
|
833
|
+
".ts",
|
|
834
|
+
".jsx",
|
|
835
|
+
".json",
|
|
836
|
+
".wasm"
|
|
837
|
+
];
|
|
838
|
+
async function runWebpackConfigProbe(config, root, options) {
|
|
839
|
+
const rules = [];
|
|
840
|
+
const mockConfig = {
|
|
841
|
+
context: root,
|
|
842
|
+
resolve: {
|
|
843
|
+
alias: {},
|
|
844
|
+
extensions: [...DEFAULT_WEBPACK_RESOLVE_EXTENSIONS]
|
|
845
|
+
},
|
|
846
|
+
module: { rules },
|
|
847
|
+
plugins: []
|
|
848
|
+
};
|
|
849
|
+
const finalConfig = await config.webpack(mockConfig, {
|
|
850
|
+
defaultLoaders: { babel: { loader: "next-babel-loader" } },
|
|
851
|
+
...options,
|
|
852
|
+
dir: root
|
|
853
|
+
}) ?? mockConfig;
|
|
854
|
+
const finalRules = finalConfig.module?.rules ?? rules;
|
|
855
|
+
const extensions = Array.isArray(finalConfig.resolve?.extensions) ? readStringArray(finalConfig.resolve.extensions) : null;
|
|
856
|
+
return {
|
|
857
|
+
config: finalConfig,
|
|
858
|
+
rules: finalRules,
|
|
859
|
+
resolveExtensions: extensions !== null && (extensions.length !== DEFAULT_WEBPACK_RESOLVE_EXTENSIONS.length || extensions.some((extension, index) => extension !== DEFAULT_WEBPACK_RESOLVE_EXTENSIONS[index])) ? extensions : null
|
|
860
|
+
};
|
|
861
|
+
}
|
|
763
862
|
/**
|
|
764
863
|
* Walk webpack module rules and invoke each referenced loader once with a
|
|
765
864
|
* dummy source string. Loaders that mutate `process.env` at compile time (a
|
|
@@ -839,7 +938,7 @@ function invokeLoaderSideEffects(rules, root) {
|
|
|
839
938
|
* We probe the webpack function with a mock config to extract them.
|
|
840
939
|
*/
|
|
841
940
|
async function extractMdxOptions(config, root = process.cwd()) {
|
|
842
|
-
return (await probeWebpackConfig(config, root)).mdx;
|
|
941
|
+
return (await probeWebpackConfig(config, root, false)).mdx;
|
|
843
942
|
}
|
|
844
943
|
/**
|
|
845
944
|
* Probe file candidates relative to root. Returns the first one that exists,
|
|
@@ -932,4 +1031,4 @@ function extractPluginsFromOptions(opts) {
|
|
|
932
1031
|
return null;
|
|
933
1032
|
}
|
|
934
1033
|
//#endregion
|
|
935
|
-
export { PHASE_PRODUCTION_BUILD, createRscCompatibilityId, detectNextIntlConfig, extractMdxOptions, findNextConfigPath, loadNextConfig, normalizeAssetPrefix, parseBodySizeLimit, reassignsModuleExports, referencesCjsGlobals, resolveNextConfig, resolveNextConfigInput };
|
|
1034
|
+
export { PHASE_PRODUCTION_BUILD, createRscCompatibilityId, detectNextIntlConfig, extractMdxOptions, findNextConfigPath, lightningCssFeatureNamesToMask, loadNextConfig, normalizeAssetPrefix, parseBodySizeLimit, reassignsModuleExports, referencesCjsGlobals, resolveNextConfig, resolveNextConfigInput };
|
|
@@ -38,6 +38,19 @@ function resolveTsconfigPathCandidate(candidate) {
|
|
|
38
38
|
for (const item of candidates) if (fs.existsSync(item) && fs.statSync(item).isFile()) return item;
|
|
39
39
|
return null;
|
|
40
40
|
}
|
|
41
|
+
/**
|
|
42
|
+
* Normalize a tsconfig `extends` field into a list of specifier strings.
|
|
43
|
+
*
|
|
44
|
+
* TypeScript 5.0+ allows `extends` to be either a string or an array of
|
|
45
|
+
* strings. Matches Next.js's handling in
|
|
46
|
+
* packages/next/src/build/next-config-ts/transpile-config.ts, where parents
|
|
47
|
+
* are iterated in order and later entries override earlier ones.
|
|
48
|
+
*/
|
|
49
|
+
function normalizeExtends(extendsField) {
|
|
50
|
+
if (typeof extendsField === "string") return [extendsField];
|
|
51
|
+
if (Array.isArray(extendsField)) return extendsField.filter((value) => typeof value === "string");
|
|
52
|
+
return [];
|
|
53
|
+
}
|
|
41
54
|
function resolveTsconfigExtends(configPath, specifier) {
|
|
42
55
|
const fromDir = path.dirname(configPath);
|
|
43
56
|
if (specifier.startsWith(".") || specifier.startsWith("/") || specifier.startsWith("\\")) return resolveTsconfigPathCandidate(path.resolve(fromDir, specifier));
|
|
@@ -87,7 +100,7 @@ function loadResolutionFromTsconfigFile(configPath, seen) {
|
|
|
87
100
|
}
|
|
88
101
|
if (!parsed) return emptyResolution();
|
|
89
102
|
let resolution = emptyResolution();
|
|
90
|
-
const extendsList =
|
|
103
|
+
const extendsList = normalizeExtends(parsed.extends);
|
|
91
104
|
for (const extendsSpecifier of extendsList) {
|
|
92
105
|
const extendedPath = resolveTsconfigExtends(configPath, extendsSpecifier);
|
|
93
106
|
if (extendedPath) {
|