vinext 0.1.3 → 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.js +1 -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.js +2 -0
- package/dist/config/config-matchers.d.ts +11 -1
- package/dist/config/config-matchers.js +14 -2
- package/dist/config/tsconfig-paths.js +14 -1
- package/dist/deploy.js +20 -13
- package/dist/entries/app-rsc-entry.js +3 -2
- package/dist/entries/pages-client-entry.js +14 -13
- package/dist/entries/pages-server-entry.js +6 -26
- package/dist/index.js +217 -40
- package/dist/plugins/dynamic-preload-metadata.js +2 -4
- package/dist/plugins/fonts.js +5 -4
- package/dist/plugins/strip-server-exports.d.ts +9 -7
- package/dist/plugins/strip-server-exports.js +493 -46
- package/dist/routing/app-route-graph.js +2 -2
- package/dist/server/app-browser-action-result.js +1 -1
- package/dist/server/app-browser-entry.js +8 -1
- package/dist/server/app-browser-navigation-controller.d.ts +1 -1
- package/dist/server/app-browser-state.d.ts +1 -1
- package/dist/server/app-browser-state.js +19 -11
- package/dist/server/app-browser-visible-commit.d.ts +1 -1
- package/dist/server/app-pages-bridge.d.ts +5 -1
- package/dist/server/app-pages-bridge.js +5 -13
- package/dist/server/app-rsc-handler.d.ts +3 -0
- package/dist/server/app-rsc-handler.js +51 -15
- package/dist/server/app-rsc-route-matching.js +6 -2
- package/dist/server/app-server-action-execution.js +5 -2
- package/dist/server/app-ssr-entry.js +1 -29
- package/dist/server/before-interactive-head.d.ts +17 -0
- package/dist/server/before-interactive-head.js +35 -0
- package/dist/server/csp.js +1 -4
- package/dist/server/dev-server.js +81 -36
- 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 +3 -12
- package/dist/server/navigation-planner.js +24 -0
- package/dist/server/navigation-trace.d.ts +2 -1
- package/dist/server/navigation-trace.js +1 -0
- package/dist/server/operation-token.d.ts +40 -0
- package/dist/server/operation-token.js +85 -0
- package/dist/server/pages-data-route.d.ts +1 -1
- package/dist/server/pages-data-route.js +7 -4
- 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-i18n.js +2 -2
- package/dist/server/pages-page-data.js +3 -1
- package/dist/server/pages-page-handler.js +3 -1
- package/dist/server/pages-page-response.d.ts +2 -0
- package/dist/server/pages-page-response.js +4 -4
- package/dist/server/pages-readiness.js +1 -1
- package/dist/server/pages-request-pipeline.d.ts +7 -7
- package/dist/server/pages-request-pipeline.js +63 -21
- package/dist/server/prod-server.d.ts +3 -1
- package/dist/server/prod-server.js +41 -10
- package/dist/server/static-file-cache.js +16 -4
- package/dist/shims/before-interactive-context.d.ts +14 -3
- package/dist/shims/document.d.ts +15 -20
- package/dist/shims/document.js +5 -8
- package/dist/shims/image.js +9 -2
- 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.js +1 -1
- package/dist/shims/link.js +37 -16
- package/dist/shims/metadata.js +4 -4
- package/dist/shims/navigation.js +2 -0
- package/dist/shims/router.d.ts +6 -2
- package/dist/shims/router.js +99 -20
- package/dist/shims/script.js +8 -4
- package/dist/utils/has-trailing-comma.d.ts +24 -0
- package/dist/utils/has-trailing-comma.js +62 -0
- 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 +1 -1
|
@@ -7,6 +7,13 @@ type ClientAssetFileNameInfo = {
|
|
|
7
7
|
readonly originalFileName?: string;
|
|
8
8
|
readonly originalFileNames?: readonly string[];
|
|
9
9
|
};
|
|
10
|
+
type RscFrameworkModuleInfo = {
|
|
11
|
+
importers: string[];
|
|
12
|
+
isEntry: boolean;
|
|
13
|
+
};
|
|
14
|
+
type RscFrameworkManualChunksMeta = {
|
|
15
|
+
getModuleInfo(id: string): RscFrameworkModuleInfo | null;
|
|
16
|
+
};
|
|
10
17
|
/**
|
|
11
18
|
* Routes client assets into Next-compatible subtrees: `.css` sources go to
|
|
12
19
|
* `<assetsDir>/css/`, everything else to `<assetsDir>/media/`. Returned as a
|
|
@@ -80,18 +87,20 @@ declare function isRscFrameworkModule(id: string): boolean;
|
|
|
80
87
|
* dedicated "framework" chunk in the RSC server build. Returns the bundler-
|
|
81
88
|
* appropriate shape: rolldown's `codeSplitting` for Vite 8+, Rollup's
|
|
82
89
|
* `manualChunks` for Vite 7. See {@link RSC_FRAMEWORK_CHUNK_TEST} for the
|
|
83
|
-
* motivation (issue #1549).
|
|
90
|
+
* motivation (issue #1549). Framework modules that are only reachable through
|
|
91
|
+
* dynamic imports must stay out of the eager framework chunk (issue #2073).
|
|
84
92
|
*/
|
|
85
93
|
declare function createRscFrameworkChunkOutputConfig(viteMajorVersion: number): {
|
|
86
94
|
codeSplitting: {
|
|
87
95
|
groups: {
|
|
88
96
|
name: string;
|
|
89
97
|
test: RegExp;
|
|
98
|
+
entriesAware: boolean;
|
|
90
99
|
}[];
|
|
91
100
|
};
|
|
92
101
|
manualChunks?: undefined;
|
|
93
102
|
} | {
|
|
94
|
-
manualChunks(id: string): string | undefined;
|
|
103
|
+
manualChunks(id: string, meta: RscFrameworkManualChunksMeta): string | undefined;
|
|
95
104
|
codeSplitting?: undefined;
|
|
96
105
|
};
|
|
97
106
|
/**
|
|
@@ -33,9 +33,10 @@ function createClientAssetFileNames(assetsDir) {
|
|
|
33
33
|
* (node_modules/.pnpm/pkg@ver/node_modules/pkg).
|
|
34
34
|
*/
|
|
35
35
|
function getPackageName(id) {
|
|
36
|
-
const
|
|
36
|
+
const normalizedId = id.replaceAll("\\", "/");
|
|
37
|
+
const nmIdx = normalizedId.lastIndexOf("node_modules/");
|
|
37
38
|
if (nmIdx === -1) return null;
|
|
38
|
-
const rest =
|
|
39
|
+
const rest = normalizedId.slice(nmIdx + 13);
|
|
39
40
|
if (rest.startsWith("@")) {
|
|
40
41
|
const parts = rest.split("/");
|
|
41
42
|
return parts.length >= 2 ? parts[0] + "/" + parts[1] : null;
|
|
@@ -153,20 +154,30 @@ function isRscFrameworkModule(id) {
|
|
|
153
154
|
const pkg = getPackageName(id);
|
|
154
155
|
return pkg !== null && FRAMEWORK_PACKAGES.includes(pkg);
|
|
155
156
|
}
|
|
157
|
+
function isStaticallyReachableFromEntry(id, meta, visited = /* @__PURE__ */ new Set()) {
|
|
158
|
+
if (visited.has(id)) return false;
|
|
159
|
+
visited.add(id);
|
|
160
|
+
const moduleInfo = meta.getModuleInfo(id);
|
|
161
|
+
if (!moduleInfo) return false;
|
|
162
|
+
if (moduleInfo.isEntry) return true;
|
|
163
|
+
return moduleInfo.importers.some((importer) => isStaticallyReachableFromEntry(importer, meta, visited));
|
|
164
|
+
}
|
|
156
165
|
/**
|
|
157
166
|
* Output config that isolates React (and the RSC flight runtime) into a
|
|
158
167
|
* dedicated "framework" chunk in the RSC server build. Returns the bundler-
|
|
159
168
|
* appropriate shape: rolldown's `codeSplitting` for Vite 8+, Rollup's
|
|
160
169
|
* `manualChunks` for Vite 7. See {@link RSC_FRAMEWORK_CHUNK_TEST} for the
|
|
161
|
-
* motivation (issue #1549).
|
|
170
|
+
* motivation (issue #1549). Framework modules that are only reachable through
|
|
171
|
+
* dynamic imports must stay out of the eager framework chunk (issue #2073).
|
|
162
172
|
*/
|
|
163
173
|
function createRscFrameworkChunkOutputConfig(viteMajorVersion) {
|
|
164
174
|
if (viteMajorVersion >= 8) return { codeSplitting: { groups: [{
|
|
165
175
|
name: "framework",
|
|
166
|
-
test: RSC_FRAMEWORK_CHUNK_TEST
|
|
176
|
+
test: RSC_FRAMEWORK_CHUNK_TEST,
|
|
177
|
+
entriesAware: true
|
|
167
178
|
}] } };
|
|
168
|
-
return { manualChunks(id) {
|
|
169
|
-
return isRscFrameworkModule(id) ? "framework" : void 0;
|
|
179
|
+
return { manualChunks(id, meta) {
|
|
180
|
+
return isRscFrameworkModule(id) && isStaticallyReachableFromEntry(id, meta) ? "framework" : void 0;
|
|
170
181
|
} };
|
|
171
182
|
}
|
|
172
183
|
/**
|
package/dist/build/prerender.js
CHANGED
|
@@ -659,6 +659,7 @@ async function prerenderApp({ routes, metadataRoutes = [], outDir, config, mode,
|
|
|
659
659
|
for (const params of paramSets) {
|
|
660
660
|
if (params === null || params === void 0) throw new Error(`generateStaticParams() for ${route.pattern} returned an entry with no params object.`);
|
|
661
661
|
const urlPath = buildUrlFromParams(route.pattern, params);
|
|
662
|
+
if (queuedRouteUrls.has(urlPath)) continue;
|
|
662
663
|
queuedRouteUrls.add(urlPath);
|
|
663
664
|
urlsToRender.push({
|
|
664
665
|
urlPath,
|
|
@@ -3,23 +3,49 @@ type PagesRouterLinkTransitionOptions = {
|
|
|
3
3
|
scroll?: boolean;
|
|
4
4
|
shallow?: boolean;
|
|
5
5
|
locale?: string | false;
|
|
6
|
+
_vinextInterpolateDynamicRoute?: boolean;
|
|
6
7
|
};
|
|
7
8
|
type PagesRouterLinkRuntime = {
|
|
8
9
|
push(url: string, as?: string, options?: PagesRouterLinkTransitionOptions): Promise<boolean>;
|
|
9
10
|
replace(url: string, as?: string, options?: PagesRouterLinkTransitionOptions): Promise<boolean>;
|
|
10
11
|
};
|
|
12
|
+
type PagesRouterLinkNavigation = {
|
|
13
|
+
href: string;
|
|
14
|
+
replace: boolean;
|
|
15
|
+
scroll: boolean;
|
|
16
|
+
shallow?: boolean;
|
|
17
|
+
locale?: string | false;
|
|
18
|
+
interpolateDynamicRoute?: boolean;
|
|
19
|
+
};
|
|
20
|
+
declare function resolvePagesRouterQueryOnlyHref(href: string, {
|
|
21
|
+
asPath,
|
|
22
|
+
basePath,
|
|
23
|
+
fallbackHref,
|
|
24
|
+
locales
|
|
25
|
+
}: {
|
|
26
|
+
asPath?: string;
|
|
27
|
+
basePath: string;
|
|
28
|
+
fallbackHref: string;
|
|
29
|
+
locales?: readonly string[];
|
|
30
|
+
}): string;
|
|
11
31
|
declare function navigatePagesRouterLink(router: PagesRouterLinkRuntime, {
|
|
12
32
|
href,
|
|
13
33
|
replace,
|
|
14
34
|
scroll,
|
|
15
35
|
shallow,
|
|
16
|
-
locale
|
|
36
|
+
locale,
|
|
37
|
+
interpolateDynamicRoute
|
|
38
|
+
}: PagesRouterLinkNavigation): Promise<void>;
|
|
39
|
+
declare function navigatePagesRouterLinkWithFallback({
|
|
40
|
+
router,
|
|
41
|
+
loadRouter,
|
|
42
|
+
navigation,
|
|
43
|
+
fallback
|
|
17
44
|
}: {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
locale?: string | false;
|
|
45
|
+
router?: PagesRouterLinkRuntime;
|
|
46
|
+
loadRouter: () => Promise<PagesRouterLinkRuntime | undefined>;
|
|
47
|
+
navigation: PagesRouterLinkNavigation;
|
|
48
|
+
fallback: () => void;
|
|
23
49
|
}): Promise<void>;
|
|
24
50
|
//#endregion
|
|
25
|
-
export { navigatePagesRouterLink };
|
|
51
|
+
export { navigatePagesRouterLink, navigatePagesRouterLinkWithFallback, resolvePagesRouterQueryOnlyHref };
|
|
@@ -1,12 +1,42 @@
|
|
|
1
|
+
import { stripBasePath } from "../utils/base-path.js";
|
|
2
|
+
import { getLocalePathPrefix } from "../utils/domain-locale.js";
|
|
1
3
|
//#region src/client/pages-router-link-navigation.ts
|
|
2
|
-
|
|
4
|
+
function resolvePagesRouterQueryOnlyHref(href, { asPath, basePath, fallbackHref, locales }) {
|
|
5
|
+
if (!href.startsWith("?")) return href;
|
|
6
|
+
try {
|
|
7
|
+
const fallbackUrl = new URL(fallbackHref);
|
|
8
|
+
const base = new URL(asPath ?? `${stripBasePath(fallbackUrl.pathname, basePath)}${fallbackUrl.search}${fallbackUrl.hash}`, "http://vinext.local");
|
|
9
|
+
const locale = getLocalePathPrefix(base.pathname, locales);
|
|
10
|
+
if (locale) base.pathname = base.pathname.slice(locale.length + 1) || "/";
|
|
11
|
+
const resolved = new URL(href, base);
|
|
12
|
+
return resolved.href.slice(resolved.origin.length);
|
|
13
|
+
} catch {
|
|
14
|
+
return href;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
async function navigatePagesRouterLink(router, { href, replace, scroll, shallow, locale, interpolateDynamicRoute = false }) {
|
|
3
18
|
const routerOptions = {
|
|
4
19
|
scroll,
|
|
5
20
|
locale
|
|
6
21
|
};
|
|
22
|
+
if (interpolateDynamicRoute) routerOptions._vinextInterpolateDynamicRoute = true;
|
|
7
23
|
if (shallow !== void 0) routerOptions.shallow = shallow;
|
|
8
24
|
if (replace) await router.replace(href, void 0, routerOptions);
|
|
9
25
|
else await router.push(href, void 0, routerOptions);
|
|
10
26
|
}
|
|
27
|
+
async function navigatePagesRouterLinkWithFallback({ router, loadRouter, navigation, fallback }) {
|
|
28
|
+
let pagesRouter = router;
|
|
29
|
+
if (!pagesRouter) try {
|
|
30
|
+
pagesRouter = await loadRouter();
|
|
31
|
+
} catch {
|
|
32
|
+
fallback();
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
if (!pagesRouter) {
|
|
36
|
+
fallback();
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
await navigatePagesRouterLink(pagesRouter, navigation);
|
|
40
|
+
}
|
|
11
41
|
//#endregion
|
|
12
|
-
export { navigatePagesRouterLink };
|
|
42
|
+
export { navigatePagesRouterLink, navigatePagesRouterLinkWithFallback, resolvePagesRouterQueryOnlyHref };
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { isUnknownRecord } from "../utils/record.js";
|
|
2
2
|
//#region src/client/vinext-next-data.ts
|
|
3
3
|
function extractVinextNextDataJson(html) {
|
|
4
|
+
const canonical = /<script\b(?=[^>]*\bid=["']__NEXT_DATA__["'])(?=[^>]*\btype=["']application\/json["'])[^>]*>([\s\S]*?)<\/script>/.exec(html);
|
|
5
|
+
if (canonical) return canonical[1];
|
|
4
6
|
const assignment = /<script(?:\s[^>]*)?>\s*window\.__NEXT_DATA__\s*=\s*/.exec(html);
|
|
5
7
|
if (!assignment || assignment.index === void 0) return null;
|
|
6
8
|
let start = assignment.index + assignment[0].length;
|
|
@@ -148,6 +148,16 @@ declare function matchRedirect(pathname: string, redirects: NextRedirect[], ctx:
|
|
|
148
148
|
* when evaluating rewrites, so this parameter is required.
|
|
149
149
|
*/
|
|
150
150
|
declare function matchRewrite(pathname: string, rewrites: NextRewrite[], ctx: RequestContext, basePathState?: BasePathMatchState): string | null;
|
|
151
|
+
/**
|
|
152
|
+
* Check whether a rewrite source can match a pathname without evaluating its
|
|
153
|
+
* request-dependent `has` / `missing` conditions.
|
|
154
|
+
*
|
|
155
|
+
* Dev uses this only as a conservative preflight before middleware runs. The
|
|
156
|
+
* conditions may become true after middleware overrides request headers, so
|
|
157
|
+
* evaluating them against the original request would incorrectly skip the
|
|
158
|
+
* Pages request pipeline for file-looking paths.
|
|
159
|
+
*/
|
|
160
|
+
declare function matchesRewriteSource(pathname: string, rewrite: NextRewrite, basePathState?: BasePathMatchState): boolean;
|
|
151
161
|
/**
|
|
152
162
|
* Sanitize a redirect/rewrite destination to collapse protocol-relative URLs.
|
|
153
163
|
*
|
|
@@ -244,4 +254,4 @@ declare function applyLocaleToRoutes<T extends NextRedirect | NextRewrite>(route
|
|
|
244
254
|
trailingSlash?: boolean;
|
|
245
255
|
}): T[];
|
|
246
256
|
//#endregion
|
|
247
|
-
export { BasePathMatchState, RequestContext, applyLocaleToRoutes, applyMiddlewareRequestHeaders, checkHasConditions, escapeHeaderSource, isExternalUrl, isSafeRegex, matchConfigPattern, matchHeaders, matchRedirect, matchRewrite, normalizeHost, parseCookies, preserveRedirectDestinationQuery, proxyExternalRequest, requestContextFromRequest, safeRegExp, sanitizeDestination };
|
|
257
|
+
export { BasePathMatchState, RequestContext, applyLocaleToRoutes, applyMiddlewareRequestHeaders, checkHasConditions, escapeHeaderSource, isExternalUrl, isSafeRegex, matchConfigPattern, matchHeaders, matchRedirect, matchRewrite, matchesRewriteSource, normalizeHost, parseCookies, preserveRedirectDestinationQuery, proxyExternalRequest, requestContextFromRequest, safeRegExp, sanitizeDestination };
|
|
@@ -268,7 +268,7 @@ function isSafeRegex(pattern) {
|
|
|
268
268
|
*/
|
|
269
269
|
function safeRegExp(pattern, flags) {
|
|
270
270
|
if (!isSafeRegex(pattern)) {
|
|
271
|
-
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.`);
|
|
272
272
|
return null;
|
|
273
273
|
}
|
|
274
274
|
try {
|
|
@@ -718,6 +718,18 @@ function matchRewrite(pathname, rewrites, ctx, basePathState = _BASEPATH_DEFAULT
|
|
|
718
718
|
return null;
|
|
719
719
|
}
|
|
720
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
|
+
/**
|
|
721
733
|
* Substitute all matched route params into a redirect/rewrite destination.
|
|
722
734
|
*
|
|
723
735
|
* Handles repeated params (e.g. `/api/:id/:id`) and catch-all suffix forms
|
|
@@ -1031,4 +1043,4 @@ function applyLocaleToRoutes(routes, i18n, type, options = {}) {
|
|
|
1031
1043
|
return out;
|
|
1032
1044
|
}
|
|
1033
1045
|
//#endregion
|
|
1034
|
-
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 };
|
|
@@ -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) {
|
package/dist/deploy.js
CHANGED
|
@@ -374,7 +374,7 @@ function generatePagesRouterWorkerEntry() {
|
|
|
374
374
|
* Cloudflare Worker entry point -- auto-generated by vinext deploy.
|
|
375
375
|
* Edit freely or delete to regenerate on next deploy.
|
|
376
376
|
*/
|
|
377
|
-
import { runPagesRequest, wrapMiddlewareWithBasePath } from "vinext/server/pages-request-pipeline";
|
|
377
|
+
import { fetchWorkerFilesystemRoute, runPagesRequest, wrapMiddlewareWithBasePath } from "vinext/server/pages-request-pipeline";
|
|
378
378
|
import type { PagesPipelineDeps } from "vinext/server/pages-request-pipeline";
|
|
379
379
|
import { handleImageOptimization, DEFAULT_DEVICE_SIZES, DEFAULT_IMAGE_SIZES, isImageOptimizationPath } from "vinext/server/image-optimization";
|
|
380
380
|
import type { ImageConfig } from "vinext/server/image-optimization";
|
|
@@ -384,7 +384,7 @@ import { assetPrefixPathname, isNextStaticPath } from "vinext/utils/asset-prefix
|
|
|
384
384
|
import { hasBasePath, stripBasePath } from "vinext/utils/base-path";
|
|
385
385
|
|
|
386
386
|
// @ts-expect-error -- virtual module resolved by vinext at build time
|
|
387
|
-
import { renderPage, handleApiRoute, runMiddleware, vinextConfig, matchPageRoute } from "virtual:vinext-server-entry";
|
|
387
|
+
import { renderPage, handleApiRoute, runMiddleware, normalizeDataRequest, vinextConfig, matchPageRoute } from "virtual:vinext-server-entry";
|
|
388
388
|
// @ts-expect-error -- virtual module resolved by vinext at build time
|
|
389
389
|
import { registerConfiguredCacheAdapters } from "virtual:vinext-cache-adapters";
|
|
390
390
|
|
|
@@ -448,11 +448,6 @@ export default {
|
|
|
448
448
|
return notFoundStaticAssetResponse();
|
|
449
449
|
}
|
|
450
450
|
|
|
451
|
-
// Capture x-nextjs-data before filterInternalHeaders strips it -- the
|
|
452
|
-
// middleware redirect protocol needs to know whether the inbound request
|
|
453
|
-
// was a _next/data fetch to emit x-nextjs-redirect instead of a 3xx.
|
|
454
|
-
const isDataRequest = request.headers.get("x-nextjs-data") === "1";
|
|
455
|
-
|
|
456
451
|
// Strip internal headers from inbound requests so they cannot be
|
|
457
452
|
// forged to influence routing or impersonate internal state.
|
|
458
453
|
// Request.headers is immutable in Workers, so build a clean copy.
|
|
@@ -476,6 +471,14 @@ export default {
|
|
|
476
471
|
}
|
|
477
472
|
}
|
|
478
473
|
|
|
474
|
+
const dataNorm = normalizeDataRequest(request);
|
|
475
|
+
if (dataNorm.notFoundResponse) return dataNorm.notFoundResponse;
|
|
476
|
+
const isDataReq = dataNorm.isDataReq;
|
|
477
|
+
if (isDataReq) {
|
|
478
|
+
request = dataNorm.request;
|
|
479
|
+
pathname = dataNorm.normalizedPathname;
|
|
480
|
+
}
|
|
481
|
+
|
|
479
482
|
// ── Image optimization via Cloudflare Images binding ──────────
|
|
480
483
|
// Checked after basePath stripping so /<basePath>/_next/image works.
|
|
481
484
|
if (isImageOptimizationPath(pathname)) {
|
|
@@ -504,12 +507,8 @@ export default {
|
|
|
504
507
|
configRewrites,
|
|
505
508
|
configHeaders,
|
|
506
509
|
hadBasePath,
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
// only for renderPage options and shouldDeferErrorPageOnMiss -- false
|
|
510
|
-
// is correct here.
|
|
511
|
-
isDataReq: false,
|
|
512
|
-
isDataRequest,
|
|
510
|
+
isDataReq,
|
|
511
|
+
isDataRequest: isDataReq,
|
|
513
512
|
ctx,
|
|
514
513
|
matchPageRoute: typeof matchPageRoute === "function" ? matchPageRoute : null,
|
|
515
514
|
// Pass the original (pre-basePath-stripping) URL to middleware so that
|
|
@@ -527,6 +526,14 @@ export default {
|
|
|
527
526
|
handleApi: typeof handleApiRoute === "function"
|
|
528
527
|
? (req, apiUrl) => handleApiRoute(req, apiUrl, ctx)
|
|
529
528
|
: null,
|
|
529
|
+
serveFilesystemRoute: async (requestPathname, _stagedHeaders, phase) => {
|
|
530
|
+
return fetchWorkerFilesystemRoute(
|
|
531
|
+
request,
|
|
532
|
+
requestPathname,
|
|
533
|
+
phase,
|
|
534
|
+
(assetRequest) => env.ASSETS.fetch(assetRequest),
|
|
535
|
+
);
|
|
536
|
+
},
|
|
530
537
|
};
|
|
531
538
|
|
|
532
539
|
const result = await runPagesRequest(request, deps);
|
|
@@ -452,6 +452,7 @@ ${rootParamNameEntries.join("\n")}
|
|
|
452
452
|
|
|
453
453
|
export default __createAppRscHandler({
|
|
454
454
|
basePath: __basePath,
|
|
455
|
+
buildId: process.env.__VINEXT_BUILD_ID ?? null,
|
|
455
456
|
ensureRouteLoaded: __ensureRouteLoaded,
|
|
456
457
|
clearRequestContext() {
|
|
457
458
|
__clearRequestContext();
|
|
@@ -867,9 +868,9 @@ export default __createAppRscHandler({
|
|
|
867
868
|
const __isEdge = route ? __isEdgeRuntime(__resolveAppPageSegmentConfig({ layouts: route.layouts, page: route.page }).runtime) : false;
|
|
868
869
|
return __fallbackRenderer.renderNotFound(route, isRscRequest, request, matchedParams, scriptNonce, middlewareContext, { isEdgeRuntime: __isEdge });
|
|
869
870
|
},
|
|
870
|
-
${hasPagesDir ? `async renderPagesFallback({ allowRscDocumentFallback, appRouteMatch, isRscRequest, matchKind, middlewareContext, pathname, request, url }) {
|
|
871
|
+
${hasPagesDir ? `async renderPagesFallback({ allowRscDocumentFallback, appRouteMatch, isDataRequest, isRscRequest, matchKind, middlewareContext, pathname, pagesDataRequest, request, url }) {
|
|
871
872
|
return __renderPagesFallback(
|
|
872
|
-
{ allowRscDocumentFallback, appRouteMatch, isRscRequest, matchKind, middlewareContext, pathname, request, url },
|
|
873
|
+
{ allowRscDocumentFallback, appRouteMatch, isDataRequest, isRscRequest, matchKind, middlewareContext, pathname, pagesDataRequest, request, url },
|
|
873
874
|
{
|
|
874
875
|
loadPagesEntry() {
|
|
875
876
|
return import.meta.viteRsc.loadModule("ssr", "index");
|
|
@@ -50,19 +50,10 @@ async function generateClientEntry(pagesDir, nextConfig, fileMatcher, options =
|
|
|
50
50
|
import "vinext/instrumentation-client";
|
|
51
51
|
import React from "react";
|
|
52
52
|
import { hydrateRoot } from "react-dom/client";
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
// line 13, which also sets window.next as a top-level side effect),
|
|
58
|
-
// and (b) the popstate handler is registered before
|
|
59
|
-
// installPagesRouterRuntime() runs, removing the race window where a
|
|
60
|
-
// popstate event could fire between hydration and runtime install.
|
|
61
|
-
//
|
|
62
|
-
// Mirrors Next.js's bootstrap order: client/next.ts statically imports
|
|
63
|
-
// from './' before calling initialize/hydrate, so window.next is set up
|
|
64
|
-
// before any async work.
|
|
65
|
-
import Router, { wrapWithRouterContext } from "next/router";
|
|
53
|
+
import Router, {
|
|
54
|
+
wrapWithRouterContext,
|
|
55
|
+
_initializePagesRouterReadyFromNextData,
|
|
56
|
+
} from "next/router";
|
|
66
57
|
|
|
67
58
|
const pageLoaders = {
|
|
68
59
|
${loaderEntries.join(",\n")}
|
|
@@ -110,6 +101,14 @@ window.__VINEXT_LINK_PREFETCH_ROUTES__ = ${JSON.stringify(appPrefetchRoutes)};
|
|
|
110
101
|
window.__VINEXT_PAGES_LINK_PREFETCH_ROUTES__ = ${JSON.stringify(pagesPrefetchRoutes)};
|
|
111
102
|
window.__VINEXT_CLIENT_REWRITES__ = ${JSON.stringify(nextConfig.rewrites)};
|
|
112
103
|
|
|
104
|
+
const nextDataElement = document.getElementById("__NEXT_DATA__");
|
|
105
|
+
if (nextDataElement?.textContent) {
|
|
106
|
+
window.__NEXT_DATA__ = JSON.parse(nextDataElement.textContent);
|
|
107
|
+
window.__VINEXT_LOCALE__ = window.__NEXT_DATA__.locale;
|
|
108
|
+
window.__VINEXT_LOCALES__ = window.__NEXT_DATA__.locales;
|
|
109
|
+
window.__VINEXT_DEFAULT_LOCALE__ = window.__NEXT_DATA__.defaultLocale;
|
|
110
|
+
}
|
|
111
|
+
|
|
113
112
|
async function hydrate() {
|
|
114
113
|
const nextData = window.__NEXT_DATA__;
|
|
115
114
|
if (!nextData) {
|
|
@@ -117,6 +116,8 @@ async function hydrate() {
|
|
|
117
116
|
return;
|
|
118
117
|
}
|
|
119
118
|
|
|
119
|
+
_initializePagesRouterReadyFromNextData(nextData);
|
|
120
|
+
|
|
120
121
|
let hydrateRootOptions;
|
|
121
122
|
if (import.meta.env.DEV) {
|
|
122
123
|
const overlay = await import("vinext/dev-error-overlay");
|
|
@@ -100,42 +100,19 @@ if (typeof _instrumentation.onRequestError === "function") {
|
|
|
100
100
|
const middlewareImportCode = middlewarePath ? `import * as middlewareModule from ${JSON.stringify(normalizePathSeparators(middlewarePath))};` : "";
|
|
101
101
|
const middlewareExportCode = middlewarePath ? `
|
|
102
102
|
export async function runMiddleware(request, ctx, options) {
|
|
103
|
-
|
|
104
|
-
// worker entries don't need to know about the data endpoint protocol.
|
|
105
|
-
// Mismatched buildId → JSON 404 short-circuit. Matched → middleware sees
|
|
106
|
-
// the normalized page path via the request URL, and the worker sees the
|
|
107
|
-
// normalized URL via result.rewriteUrl (if middleware didn't already
|
|
108
|
-
// rewrite to something else).
|
|
109
|
-
const __dataNorm = __normalizePagesDataRequest(request, buildId);
|
|
110
|
-
if (__dataNorm.notFoundResponse) {
|
|
111
|
-
return { continue: false, response: __dataNorm.notFoundResponse };
|
|
112
|
-
}
|
|
113
|
-
const __result = await __runGeneratedMiddleware({
|
|
103
|
+
return __runGeneratedMiddleware({
|
|
114
104
|
basePath: vinextConfig.basePath,
|
|
115
105
|
ctx,
|
|
116
106
|
i18nConfig,
|
|
117
|
-
isDataRequest: options?.isDataRequest === true
|
|
107
|
+
isDataRequest: options?.isDataRequest === true,
|
|
118
108
|
isProxy: ${JSON.stringify(isProxyFile(middlewarePath))},
|
|
119
109
|
module: middlewareModule,
|
|
120
|
-
request
|
|
110
|
+
request,
|
|
121
111
|
trailingSlash: vinextConfig.trailingSlash,
|
|
122
112
|
});
|
|
123
|
-
if (__dataNorm.isDataReq && __result.continue && !__result.rewriteUrl && !__result.redirectUrl) {
|
|
124
|
-
return { ...__result, rewriteUrl: __dataNorm.normalizedPathname + __dataNorm.search };
|
|
125
|
-
}
|
|
126
|
-
return __result;
|
|
127
113
|
}
|
|
128
114
|
` : `
|
|
129
115
|
export async function runMiddleware(request) {
|
|
130
|
-
// Even without user middleware, the data-endpoint URL must be normalized so
|
|
131
|
-
// the worker pipeline sees the page path. Mismatched buildId → JSON 404.
|
|
132
|
-
const __dataNorm = __normalizePagesDataRequest(request, buildId);
|
|
133
|
-
if (__dataNorm.notFoundResponse) {
|
|
134
|
-
return { continue: false, response: __dataNorm.notFoundResponse };
|
|
135
|
-
}
|
|
136
|
-
if (__dataNorm.isDataReq) {
|
|
137
|
-
return { continue: true, rewriteUrl: __dataNorm.normalizedPathname + __dataNorm.search };
|
|
138
|
-
}
|
|
139
116
|
return { continue: true };
|
|
140
117
|
}
|
|
141
118
|
`;
|
|
@@ -181,6 +158,9 @@ const i18nConfig = ${i18nConfigJson};
|
|
|
181
158
|
// match _next/data requests against the embedded buildId without needing
|
|
182
159
|
// to load next.config.js at runtime.
|
|
183
160
|
export const buildId = ${buildIdJson};
|
|
161
|
+
export function normalizeDataRequest(request) {
|
|
162
|
+
return __normalizePagesDataRequest(request, buildId);
|
|
163
|
+
}
|
|
184
164
|
const __hasMiddleware = ${JSON.stringify(Boolean(middlewarePath))};
|
|
185
165
|
|
|
186
166
|
// Full resolved config for production server (embedded at build time)
|