vinext 0.0.52 → 0.0.54
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/build/clean-output.d.ts +14 -0
- package/dist/build/clean-output.js +36 -0
- package/dist/build/clean-output.js.map +1 -0
- package/dist/build/inline-css.d.ts +7 -0
- package/dist/build/inline-css.js +50 -0
- package/dist/build/inline-css.js.map +1 -0
- package/dist/build/prerender.d.ts +6 -2
- package/dist/build/prerender.js +51 -12
- package/dist/build/prerender.js.map +1 -1
- package/dist/build/run-prerender.js +10 -1
- package/dist/build/run-prerender.js.map +1 -1
- package/dist/build/static-export.d.ts +5 -0
- package/dist/build/static-export.js +8 -3
- package/dist/build/static-export.js.map +1 -1
- package/dist/check.js +4 -0
- package/dist/check.js.map +1 -1
- package/dist/cli.js +19 -4
- package/dist/cli.js.map +1 -1
- package/dist/client/instrumentation-client-inject.d.ts +34 -0
- package/dist/client/instrumentation-client-inject.js +57 -0
- package/dist/client/instrumentation-client-inject.js.map +1 -0
- package/dist/client/navigation-runtime.d.ts +16 -2
- package/dist/client/navigation-runtime.js +16 -1
- package/dist/client/navigation-runtime.js.map +1 -1
- package/dist/client/vinext-next-data.d.ts +2 -1
- package/dist/client/vinext-next-data.js.map +1 -1
- package/dist/client/window-next.d.ts +17 -2
- package/dist/client/window-next.js.map +1 -1
- package/dist/cloudflare/tpr.js +1 -1
- package/dist/cloudflare/tpr.js.map +1 -1
- package/dist/config/config-matchers.js +2 -1
- package/dist/config/config-matchers.js.map +1 -1
- package/dist/config/next-config.d.ts +95 -4
- package/dist/config/next-config.js +173 -14
- package/dist/config/next-config.js.map +1 -1
- package/dist/deploy.js +42 -7
- package/dist/deploy.js.map +1 -1
- package/dist/entries/app-browser-entry.d.ts +11 -1
- package/dist/entries/app-browser-entry.js +16 -6
- package/dist/entries/app-browser-entry.js.map +1 -1
- package/dist/entries/app-rsc-entry.d.ts +12 -3
- package/dist/entries/app-rsc-entry.js +41 -8
- package/dist/entries/app-rsc-entry.js.map +1 -1
- package/dist/entries/app-rsc-manifest.d.ts +21 -1
- package/dist/entries/app-rsc-manifest.js +6 -4
- package/dist/entries/app-rsc-manifest.js.map +1 -1
- package/dist/entries/pages-client-entry.d.ts +4 -1
- package/dist/entries/pages-client-entry.js +40 -3
- package/dist/entries/pages-client-entry.js.map +1 -1
- package/dist/entries/pages-server-entry.js +292 -34
- package/dist/entries/pages-server-entry.js.map +1 -1
- package/dist/entries/runtime-entry-module.d.ts +1 -10
- package/dist/entries/runtime-entry-module.js +2 -12
- package/dist/entries/runtime-entry-module.js.map +1 -1
- package/dist/index.js +91 -10
- package/dist/index.js.map +1 -1
- package/dist/plugins/fonts.js +25 -2
- package/dist/plugins/fonts.js.map +1 -1
- package/dist/plugins/remove-console.d.ts +16 -0
- package/dist/plugins/remove-console.js +176 -0
- package/dist/plugins/remove-console.js.map +1 -0
- package/dist/routing/app-route-graph.d.ts +24 -1
- package/dist/routing/app-route-graph.js +52 -4
- package/dist/routing/app-route-graph.js.map +1 -1
- package/dist/routing/app-router.d.ts +2 -2
- package/dist/routing/app-router.js +2 -2
- package/dist/routing/app-router.js.map +1 -1
- package/dist/routing/file-matcher.d.ts +21 -1
- package/dist/routing/file-matcher.js +39 -1
- package/dist/routing/file-matcher.js.map +1 -1
- package/dist/routing/pages-router.d.ts +1 -1
- package/dist/routing/pages-router.js +10 -3
- package/dist/routing/pages-router.js.map +1 -1
- package/dist/routing/route-trie.js +13 -18
- package/dist/routing/route-trie.js.map +1 -1
- package/dist/routing/utils.d.ts +11 -1
- package/dist/routing/utils.js +15 -1
- package/dist/routing/utils.js.map +1 -1
- package/dist/server/api-handler.js +19 -10
- package/dist/server/api-handler.js.map +1 -1
- package/dist/server/app-browser-action-result.d.ts +16 -1
- package/dist/server/app-browser-action-result.js +15 -1
- package/dist/server/app-browser-action-result.js.map +1 -1
- package/dist/server/app-browser-entry.js +47 -28
- package/dist/server/app-browser-entry.js.map +1 -1
- package/dist/server/app-browser-navigation-controller.d.ts +2 -0
- package/dist/server/app-browser-navigation-controller.js +4 -0
- package/dist/server/app-browser-navigation-controller.js.map +1 -1
- package/dist/server/app-elements-wire.d.ts +13 -4
- package/dist/server/app-elements-wire.js +10 -1
- package/dist/server/app-elements-wire.js.map +1 -1
- package/dist/server/app-elements.d.ts +2 -2
- package/dist/server/app-elements.js +2 -2
- package/dist/server/app-elements.js.map +1 -1
- package/dist/server/app-fallback-renderer.d.ts +27 -8
- package/dist/server/app-fallback-renderer.js +19 -8
- package/dist/server/app-fallback-renderer.js.map +1 -1
- package/dist/server/app-history-state.js +6 -2
- package/dist/server/app-history-state.js.map +1 -1
- package/dist/server/app-inline-css-client.d.ts +7 -0
- package/dist/server/app-inline-css-client.js +37 -0
- package/dist/server/app-inline-css-client.js.map +1 -0
- package/dist/server/app-interception-context-header.d.ts +33 -0
- package/dist/server/app-interception-context-header.js +44 -0
- package/dist/server/app-interception-context-header.js.map +1 -0
- package/dist/server/app-mounted-slots-header.d.ts +19 -0
- package/dist/server/app-mounted-slots-header.js +40 -1
- package/dist/server/app-mounted-slots-header.js.map +1 -1
- package/dist/server/app-optimistic-routing.js +26 -18
- package/dist/server/app-optimistic-routing.js.map +1 -1
- package/dist/server/app-page-boundary-render.d.ts +1 -0
- package/dist/server/app-page-boundary-render.js +2 -0
- package/dist/server/app-page-boundary-render.js.map +1 -1
- package/dist/server/app-page-boundary.d.ts +22 -1
- package/dist/server/app-page-boundary.js +30 -3
- package/dist/server/app-page-boundary.js.map +1 -1
- package/dist/server/app-page-cache.d.ts +9 -3
- package/dist/server/app-page-cache.js +14 -8
- package/dist/server/app-page-cache.js.map +1 -1
- package/dist/server/app-page-dispatch.d.ts +13 -1
- package/dist/server/app-page-dispatch.js +136 -82
- package/dist/server/app-page-dispatch.js.map +1 -1
- package/dist/server/app-page-element-builder.d.ts +2 -1
- package/dist/server/app-page-element-builder.js +17 -30
- package/dist/server/app-page-element-builder.js.map +1 -1
- package/dist/server/app-page-execution.d.ts +1 -0
- package/dist/server/app-page-execution.js +2 -0
- package/dist/server/app-page-execution.js.map +1 -1
- package/dist/server/app-page-head.d.ts +1 -0
- package/dist/server/app-page-head.js +8 -0
- package/dist/server/app-page-head.js.map +1 -1
- package/dist/server/app-page-render-identity.d.ts +22 -0
- package/dist/server/app-page-render-identity.js +42 -0
- package/dist/server/app-page-render-identity.js.map +1 -0
- package/dist/server/app-page-render-observation.js +1 -1
- package/dist/server/app-page-render.d.ts +9 -1
- package/dist/server/app-page-render.js +8 -2
- package/dist/server/app-page-render.js.map +1 -1
- package/dist/server/app-page-request.d.ts +6 -3
- package/dist/server/app-page-request.js +5 -2
- package/dist/server/app-page-request.js.map +1 -1
- package/dist/server/app-page-response.d.ts +11 -1
- package/dist/server/app-page-response.js +16 -4
- package/dist/server/app-page-response.js.map +1 -1
- package/dist/server/app-page-route-wiring.d.ts +16 -0
- package/dist/server/app-page-route-wiring.js +25 -10
- package/dist/server/app-page-route-wiring.js.map +1 -1
- package/dist/server/app-page-stream.d.ts +12 -0
- package/dist/server/app-page-stream.js +3 -0
- package/dist/server/app-page-stream.js.map +1 -1
- package/dist/server/app-route-handler-dispatch.d.ts +1 -0
- package/dist/server/app-route-handler-dispatch.js +3 -0
- package/dist/server/app-route-handler-dispatch.js.map +1 -1
- package/dist/server/app-route-handler-execution.d.ts +1 -0
- package/dist/server/app-route-handler-execution.js +1 -0
- package/dist/server/app-route-handler-execution.js.map +1 -1
- package/dist/server/app-route-handler-response.js +38 -6
- package/dist/server/app-route-handler-response.js.map +1 -1
- package/dist/server/app-rsc-handler.d.ts +16 -3
- package/dist/server/app-rsc-handler.js +60 -11
- package/dist/server/app-rsc-handler.js.map +1 -1
- package/dist/server/app-rsc-request-normalization.d.ts +2 -1
- package/dist/server/app-rsc-request-normalization.js +6 -4
- package/dist/server/app-rsc-request-normalization.js.map +1 -1
- package/dist/server/app-segment-config.d.ts +4 -1
- package/dist/server/app-segment-config.js +6 -1
- package/dist/server/app-segment-config.js.map +1 -1
- package/dist/server/app-server-action-execution.d.ts +22 -3
- package/dist/server/app-server-action-execution.js +46 -7
- package/dist/server/app-server-action-execution.js.map +1 -1
- package/dist/server/app-ssr-entry.d.ts +6 -0
- package/dist/server/app-ssr-entry.js +57 -6
- package/dist/server/app-ssr-entry.js.map +1 -1
- package/dist/server/app-ssr-error-meta.js +3 -3
- package/dist/server/app-ssr-error-meta.js.map +1 -1
- package/dist/server/app-ssr-stream.d.ts +25 -1
- package/dist/server/app-ssr-stream.js +237 -19
- package/dist/server/app-ssr-stream.js.map +1 -1
- package/dist/server/app-static-generation.d.ts +1 -0
- package/dist/server/app-static-generation.js +2 -1
- package/dist/server/app-static-generation.js.map +1 -1
- package/dist/server/client-trace-metadata.d.ts +31 -0
- package/dist/server/client-trace-metadata.js +83 -0
- package/dist/server/client-trace-metadata.js.map +1 -0
- package/dist/server/cookie-utils.d.ts +13 -0
- package/dist/server/cookie-utils.js +20 -0
- package/dist/server/cookie-utils.js.map +1 -0
- package/dist/server/default-not-found-module.d.ts +20 -0
- package/dist/server/default-not-found-module.js +20 -0
- package/dist/server/default-not-found-module.js.map +1 -0
- package/dist/server/dev-server.d.ts +8 -1
- package/dist/server/dev-server.js +56 -11
- package/dist/server/dev-server.js.map +1 -1
- package/dist/server/headers.d.ts +5 -1
- package/dist/server/headers.js +5 -1
- package/dist/server/headers.js.map +1 -1
- package/dist/server/html.d.ts +2 -1
- package/dist/server/html.js +6 -1
- package/dist/server/html.js.map +1 -1
- package/dist/server/image-optimization.d.ts +13 -4
- package/dist/server/image-optimization.js +15 -4
- package/dist/server/image-optimization.js.map +1 -1
- package/dist/server/isr-cache.d.ts +7 -5
- package/dist/server/isr-cache.js +17 -6
- package/dist/server/isr-cache.js.map +1 -1
- package/dist/server/middleware-runtime.js +1 -2
- package/dist/server/middleware-runtime.js.map +1 -1
- package/dist/server/middleware.js +1 -1
- package/dist/server/middleware.js.map +1 -1
- package/dist/server/pages-api-route.d.ts +18 -0
- package/dist/server/pages-api-route.js +3 -1
- package/dist/server/pages-api-route.js.map +1 -1
- package/dist/server/pages-body-parser-config.d.ts +60 -0
- package/dist/server/pages-body-parser-config.js +79 -0
- package/dist/server/pages-body-parser-config.js.map +1 -0
- package/dist/server/pages-data-route.js +1 -0
- package/dist/server/pages-data-route.js.map +1 -1
- package/dist/server/pages-default-404.d.ts +31 -0
- package/dist/server/pages-default-404.js +40 -0
- package/dist/server/pages-default-404.js.map +1 -0
- package/dist/server/pages-document-initial-props.d.ts +7 -0
- package/dist/server/pages-document-initial-props.js +14 -0
- package/dist/server/pages-document-initial-props.js.map +1 -0
- package/dist/server/pages-node-compat.d.ts +10 -0
- package/dist/server/pages-node-compat.js +12 -1
- package/dist/server/pages-node-compat.js.map +1 -1
- package/dist/server/pages-page-data.d.ts +40 -0
- package/dist/server/pages-page-data.js +19 -14
- package/dist/server/pages-page-data.js.map +1 -1
- package/dist/server/pages-page-method.d.ts +48 -0
- package/dist/server/pages-page-method.js +19 -0
- package/dist/server/pages-page-method.js.map +1 -0
- package/dist/server/pages-page-response.d.ts +8 -0
- package/dist/server/pages-page-response.js +21 -11
- package/dist/server/pages-page-response.js.map +1 -1
- package/dist/server/pages-serializable-props.d.ts +25 -0
- package/dist/server/pages-serializable-props.js +69 -0
- package/dist/server/pages-serializable-props.js.map +1 -0
- package/dist/server/prerender-route-params.d.ts +14 -0
- package/dist/server/prerender-route-params.js +94 -0
- package/dist/server/prerender-route-params.js.map +1 -0
- package/dist/server/prod-server.d.ts +3 -23
- package/dist/server/prod-server.js +43 -57
- package/dist/server/prod-server.js.map +1 -1
- package/dist/server/proxy-trust.d.ts +41 -0
- package/dist/server/proxy-trust.js +70 -0
- package/dist/server/proxy-trust.js.map +1 -0
- package/dist/server/request-pipeline.d.ts +3 -3
- package/dist/server/request-pipeline.js +5 -4
- package/dist/server/request-pipeline.js.map +1 -1
- package/dist/server/seed-cache.js +12 -6
- package/dist/server/seed-cache.js.map +1 -1
- package/dist/server/server-action-not-found.js +3 -2
- package/dist/server/server-action-not-found.js.map +1 -1
- package/dist/server/static-file-cache.js +2 -1
- package/dist/server/static-file-cache.js.map +1 -1
- package/dist/server/streaming-metadata.d.ts +5 -0
- package/dist/server/streaming-metadata.js +10 -0
- package/dist/server/streaming-metadata.js.map +1 -0
- package/dist/shims/app-router-scroll-state.d.ts +14 -0
- package/dist/shims/app-router-scroll-state.js +51 -0
- package/dist/shims/app-router-scroll-state.js.map +1 -0
- package/dist/shims/app-router-scroll.d.ts +28 -0
- package/dist/shims/app-router-scroll.js +115 -0
- package/dist/shims/app-router-scroll.js.map +1 -0
- package/dist/shims/before-interactive-context.d.ts +30 -0
- package/dist/shims/before-interactive-context.js +10 -0
- package/dist/shims/before-interactive-context.js.map +1 -0
- package/dist/shims/cache-runtime.d.ts +1 -1
- package/dist/shims/cache-runtime.js +14 -1
- package/dist/shims/cache-runtime.js.map +1 -1
- package/dist/shims/cache.d.ts +6 -0
- package/dist/shims/cache.js +7 -0
- package/dist/shims/cache.js.map +1 -1
- package/dist/shims/default-not-found.d.ts +12 -0
- package/dist/shims/default-not-found.js +61 -0
- package/dist/shims/default-not-found.js.map +1 -0
- package/dist/shims/error.js +3 -0
- package/dist/shims/error.js.map +1 -1
- package/dist/shims/font-local.d.ts +5 -0
- package/dist/shims/font-local.js +6 -2
- package/dist/shims/font-local.js.map +1 -1
- package/dist/shims/head.js +4 -4
- package/dist/shims/head.js.map +1 -1
- package/dist/shims/headers.d.ts +13 -2
- package/dist/shims/headers.js +73 -22
- package/dist/shims/headers.js.map +1 -1
- package/dist/shims/image.d.ts +1 -1
- package/dist/shims/image.js +4 -4
- package/dist/shims/image.js.map +1 -1
- package/dist/shims/internal/app-route-detection.d.ts +37 -0
- package/dist/shims/internal/app-route-detection.js +69 -0
- package/dist/shims/internal/app-route-detection.js.map +1 -0
- package/dist/shims/internal/pages-data-target.d.ts +58 -0
- package/dist/shims/internal/pages-data-target.js +91 -0
- package/dist/shims/internal/pages-data-target.js.map +1 -0
- package/dist/shims/internal/pages-data-url.d.ts +42 -0
- package/dist/shims/internal/pages-data-url.js +73 -0
- package/dist/shims/internal/pages-data-url.js.map +1 -0
- package/dist/shims/link.d.ts +18 -2
- package/dist/shims/link.js +129 -15
- package/dist/shims/link.js.map +1 -1
- package/dist/shims/metadata.d.ts +9 -7
- package/dist/shims/metadata.js +70 -7
- package/dist/shims/metadata.js.map +1 -1
- package/dist/shims/navigation.d.ts +1 -2
- package/dist/shims/navigation.js +94 -20
- package/dist/shims/navigation.js.map +1 -1
- package/dist/shims/router.d.ts +5 -0
- package/dist/shims/router.js +389 -80
- package/dist/shims/router.js.map +1 -1
- package/dist/shims/script.d.ts +11 -1
- package/dist/shims/script.js +158 -15
- package/dist/shims/script.js.map +1 -1
- package/dist/shims/server.js +1 -0
- package/dist/shims/server.js.map +1 -1
- package/dist/shims/url-utils.d.ts +2 -1
- package/dist/shims/url-utils.js +15 -4
- package/dist/shims/url-utils.js.map +1 -1
- package/dist/utils/html-limited-bots.d.ts +5 -0
- package/dist/utils/html-limited-bots.js +15 -0
- package/dist/utils/html-limited-bots.js.map +1 -0
- package/dist/utils/path.d.ts +13 -0
- package/dist/utils/path.js +16 -0
- package/dist/utils/path.js.map +1 -0
- package/dist/utils/query.d.ts +6 -0
- package/dist/utils/query.js +10 -1
- package/dist/utils/query.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { patternToNextFormat } from "../routing/route-validation.js";
|
|
2
2
|
import { pagesRouter } from "../routing/pages-router.js";
|
|
3
|
-
import { normalizePathSeparators } from "
|
|
3
|
+
import { normalizePathSeparators } from "../utils/path.js";
|
|
4
4
|
import { findFileWithExts } from "./pages-entry-helpers.js";
|
|
5
5
|
//#region src/entries/pages-client-entry.ts
|
|
6
6
|
/**
|
|
@@ -14,10 +14,11 @@ import { findFileWithExts } from "./pages-entry-helpers.js";
|
|
|
14
14
|
*
|
|
15
15
|
* Extracted from index.ts.
|
|
16
16
|
*/
|
|
17
|
-
async function generateClientEntry(pagesDir, nextConfig, fileMatcher) {
|
|
17
|
+
async function generateClientEntry(pagesDir, nextConfig, fileMatcher, options = {}) {
|
|
18
18
|
const pageRoutes = await pagesRouter(pagesDir, nextConfig?.pageExtensions, fileMatcher);
|
|
19
19
|
const appFilePath = findFileWithExts(pagesDir, "_app", fileMatcher);
|
|
20
20
|
const hasApp = appFilePath !== null;
|
|
21
|
+
const appPrefetchRoutes = options.appPrefetchRoutes ?? [];
|
|
21
22
|
const loaderEntries = pageRoutes.map((r) => {
|
|
22
23
|
const absPath = normalizePathSeparators(r.filePath);
|
|
23
24
|
const nextFormatPattern = patternToNextFormat(r.pattern);
|
|
@@ -46,6 +47,42 @@ import { wrapWithRouterContext } from "next/router";
|
|
|
46
47
|
const pageLoaders = {
|
|
47
48
|
${loaderEntries.join(",\n")}
|
|
48
49
|
};
|
|
50
|
+
${hasApp ? `
|
|
51
|
+
const appLoader = () => import(${JSON.stringify(appFileBase)});
|
|
52
|
+
` : `
|
|
53
|
+
const appLoader = undefined;
|
|
54
|
+
`}
|
|
55
|
+
// Expose the code-split loader manifest on window so client-side
|
|
56
|
+
// _next/data navigations in shims/router.ts can resolve the correct page
|
|
57
|
+
// chunk for any route. Without this, navigateClient() would have to extract
|
|
58
|
+
// the chunk URL from an HTML response — the whole point of switching to the
|
|
59
|
+
// JSON data endpoint is to avoid that round trip.
|
|
60
|
+
//
|
|
61
|
+
// Keys are route patterns in Next.js bracket format (matching __NEXT_DATA__.page
|
|
62
|
+
// and the keys of pageLoaders above). The patterns list is the same as
|
|
63
|
+
// Object.keys(pageLoaders), exposed separately so navigateClient() can iterate
|
|
64
|
+
// it without re-keying the map. Ordering is the insertion order of pageRoutes,
|
|
65
|
+
// which pagesRouter() has already sorted by specificity (static → dynamic →
|
|
66
|
+
// catch-all → optional catch-all) via compareRoutes — so matchPagesPattern()
|
|
67
|
+
// can iterate in order and trust the first match.
|
|
68
|
+
window.__VINEXT_PAGE_LOADERS__ = pageLoaders;
|
|
69
|
+
window.__VINEXT_PAGE_PATTERNS__ = Object.keys(pageLoaders);
|
|
70
|
+
window.__VINEXT_APP_LOADER__ = appLoader;
|
|
71
|
+
// Expose the App Router prefetch manifest so Pages Router \`<Link>\`s and
|
|
72
|
+
// \`Router.prefetch\` can detect when a prefetch target is actually an App
|
|
73
|
+
// Router route, and mark it on \`Router.components[urlPathname]\` with
|
|
74
|
+
// \`{ __appRouter: true }\`. Mirrors Next.js's \`_bfl\`-driven marker write at
|
|
75
|
+
// .nextjs-ref/packages/next/src/shared/lib/router/router.ts:2525, which the
|
|
76
|
+
// Next.js deploy test
|
|
77
|
+
// test/e2e/app-dir/app/index.test.ts → "should successfully detect app
|
|
78
|
+
// route during prefetch"
|
|
79
|
+
// asserts via \`window.next.router.components[<path>]\`. Issue #1526.
|
|
80
|
+
//
|
|
81
|
+
// In a hybrid Pages + App Router build, this entry runs when the user lands
|
|
82
|
+
// on a Pages Router page. The App Router browser entry sets the same global
|
|
83
|
+
// when the user lands on an App Router page (see app-browser-entry.ts) — the
|
|
84
|
+
// two writes do not race because only one entry executes per page load.
|
|
85
|
+
window.__VINEXT_LINK_PREFETCH_ROUTES__ = ${JSON.stringify(appPrefetchRoutes)};
|
|
49
86
|
|
|
50
87
|
async function hydrate() {
|
|
51
88
|
const nextData = window.__NEXT_DATA__;
|
|
@@ -71,7 +108,7 @@ async function hydrate() {
|
|
|
71
108
|
let element;
|
|
72
109
|
${hasApp ? `
|
|
73
110
|
try {
|
|
74
|
-
const appModule = await
|
|
111
|
+
const appModule = await appLoader();
|
|
75
112
|
const AppComponent = appModule.default;
|
|
76
113
|
window.__VINEXT_APP__ = AppComponent;
|
|
77
114
|
element = React.createElement(AppComponent, { Component: PageComponent, pageProps });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pages-client-entry.js","names":["pagesPatternToNextFormat"],"sources":["../../src/entries/pages-client-entry.ts"],"sourcesContent":["/**\n * Pages Router client hydration entry generator.\n *\n * Generates the virtual client entry module (`virtual:vinext-client-entry`).\n * This is the entry point for `vite build` (client bundle). It maps route\n * patterns to dynamic imports of page modules so Vite code-splits each page\n * into its own chunk. At runtime it reads __NEXT_DATA__ to determine which\n * page to hydrate.\n *\n * Extracted from index.ts.\n */\nimport {\n pagesRouter,\n patternToNextFormat as pagesPatternToNextFormat,\n type Route,\n} from \"../routing/pages-router.js\";\nimport { createValidFileMatcher } from \"../routing/file-matcher.js\";\nimport { type ResolvedNextConfig } from \"../config/next-config.js\";\nimport { findFileWithExts } from \"./pages-entry-helpers.js\";\nimport { normalizePathSeparators } from \"
|
|
1
|
+
{"version":3,"file":"pages-client-entry.js","names":["pagesPatternToNextFormat"],"sources":["../../src/entries/pages-client-entry.ts"],"sourcesContent":["/**\n * Pages Router client hydration entry generator.\n *\n * Generates the virtual client entry module (`virtual:vinext-client-entry`).\n * This is the entry point for `vite build` (client bundle). It maps route\n * patterns to dynamic imports of page modules so Vite code-splits each page\n * into its own chunk. At runtime it reads __NEXT_DATA__ to determine which\n * page to hydrate.\n *\n * Extracted from index.ts.\n */\nimport {\n pagesRouter,\n patternToNextFormat as pagesPatternToNextFormat,\n type Route,\n} from \"../routing/pages-router.js\";\nimport { createValidFileMatcher } from \"../routing/file-matcher.js\";\nimport { type ResolvedNextConfig } from \"../config/next-config.js\";\nimport type { VinextLinkPrefetchRoute } from \"../client/vinext-next-data.js\";\nimport { findFileWithExts } from \"./pages-entry-helpers.js\";\nimport { normalizePathSeparators } from \"../utils/path.js\";\n\nexport async function generateClientEntry(\n pagesDir: string,\n nextConfig: ResolvedNextConfig,\n fileMatcher: ReturnType<typeof createValidFileMatcher>,\n options: { appPrefetchRoutes?: readonly VinextLinkPrefetchRoute[] } = {},\n): Promise<string> {\n const pageRoutes = await pagesRouter(pagesDir, nextConfig?.pageExtensions, fileMatcher);\n\n const appFilePath = findFileWithExts(pagesDir, \"_app\", fileMatcher);\n const hasApp = appFilePath !== null;\n const appPrefetchRoutes = options.appPrefetchRoutes ?? [];\n\n // Build a map of route pattern -> dynamic import.\n // Keys must use Next.js bracket format (e.g. \"/user/[id]\") to match\n // __NEXT_DATA__.page which is set via patternToNextFormat() during SSR.\n const loaderEntries = pageRoutes.map((r: Route) => {\n const absPath = normalizePathSeparators(r.filePath);\n const nextFormatPattern = pagesPatternToNextFormat(r.pattern);\n // JSON.stringify safely escapes quotes, backslashes, and special chars in\n // both the route pattern and the absolute file path.\n // lgtm[js/bad-code-sanitization]\n return ` ${JSON.stringify(nextFormatPattern)}: () => import(${JSON.stringify(absPath)})`;\n });\n\n const appFileBase = appFilePath ? normalizePathSeparators(appFilePath) : undefined;\n\n return `\nimport \"vinext/instrumentation-client\";\nimport React from \"react\";\nimport { hydrateRoot } from \"react-dom/client\";\nimport { installPagesRouterRuntime } from \"vinext/pages-router-runtime\";\n// Statically import next/router as the very first vinext shim so that\n// (a) installWindowNext runs at top-level — \\`window.next.router\\` is\n// available to test harnesses and third-party scripts BEFORE\n// hydrate() resolves (see .nextjs-ref/packages/next/src/client/next.ts\n// line 13, which also sets window.next as a top-level side effect),\n// and (b) the popstate handler is registered before\n// installPagesRouterRuntime() runs, removing the race window where a\n// popstate event could fire between hydration and runtime install.\n//\n// Mirrors Next.js's bootstrap order: client/next.ts statically imports\n// from './' before calling initialize/hydrate, so window.next is set up\n// before any async work.\nimport { wrapWithRouterContext } from \"next/router\";\n\nconst pageLoaders = {\n${loaderEntries.join(\",\\n\")}\n};\n${\n hasApp\n ? `\nconst appLoader = () => import(${JSON.stringify(appFileBase!)});\n`\n : `\nconst appLoader = undefined;\n`\n}\n// Expose the code-split loader manifest on window so client-side\n// _next/data navigations in shims/router.ts can resolve the correct page\n// chunk for any route. Without this, navigateClient() would have to extract\n// the chunk URL from an HTML response — the whole point of switching to the\n// JSON data endpoint is to avoid that round trip.\n//\n// Keys are route patterns in Next.js bracket format (matching __NEXT_DATA__.page\n// and the keys of pageLoaders above). The patterns list is the same as\n// Object.keys(pageLoaders), exposed separately so navigateClient() can iterate\n// it without re-keying the map. Ordering is the insertion order of pageRoutes,\n// which pagesRouter() has already sorted by specificity (static → dynamic →\n// catch-all → optional catch-all) via compareRoutes — so matchPagesPattern()\n// can iterate in order and trust the first match.\nwindow.__VINEXT_PAGE_LOADERS__ = pageLoaders;\nwindow.__VINEXT_PAGE_PATTERNS__ = Object.keys(pageLoaders);\nwindow.__VINEXT_APP_LOADER__ = appLoader;\n// Expose the App Router prefetch manifest so Pages Router \\`<Link>\\`s and\n// \\`Router.prefetch\\` can detect when a prefetch target is actually an App\n// Router route, and mark it on \\`Router.components[urlPathname]\\` with\n// \\`{ __appRouter: true }\\`. Mirrors Next.js's \\`_bfl\\`-driven marker write at\n// .nextjs-ref/packages/next/src/shared/lib/router/router.ts:2525, which the\n// Next.js deploy test\n// test/e2e/app-dir/app/index.test.ts → \"should successfully detect app\n// route during prefetch\"\n// asserts via \\`window.next.router.components[<path>]\\`. Issue #1526.\n//\n// In a hybrid Pages + App Router build, this entry runs when the user lands\n// on a Pages Router page. The App Router browser entry sets the same global\n// when the user lands on an App Router page (see app-browser-entry.ts) — the\n// two writes do not race because only one entry executes per page load.\nwindow.__VINEXT_LINK_PREFETCH_ROUTES__ = ${JSON.stringify(appPrefetchRoutes)};\n\nasync function hydrate() {\n const nextData = window.__NEXT_DATA__;\n if (!nextData) {\n console.error(\"[vinext] No __NEXT_DATA__ found\");\n return;\n }\n\n const { pageProps } = nextData.props;\n const loader = pageLoaders[nextData.page];\n if (!loader) {\n console.error(\"[vinext] No page loader for route:\", nextData.page);\n return;\n }\n\n const pageModule = await loader();\n const PageComponent = pageModule.default;\n if (!PageComponent) {\n console.error(\"[vinext] Page module has no default export\");\n return;\n }\n\n let element;\n ${\n hasApp\n ? `\n try {\n const appModule = await appLoader();\n const AppComponent = appModule.default;\n window.__VINEXT_APP__ = AppComponent;\n element = React.createElement(AppComponent, { Component: PageComponent, pageProps });\n } catch {\n element = React.createElement(PageComponent, pageProps);\n }\n `\n : `\n element = React.createElement(PageComponent, pageProps);\n `\n }\n\n // Wrap with RouterContext.Provider so next/router and next/compat/router work during hydration.\n element = wrapWithRouterContext(element);\n\n const container = document.getElementById(\"__next\");\n if (!container) {\n console.error(\"[vinext] No #__next element found\");\n return;\n }\n\n const root = hydrateRoot(container, element);\n window.__VINEXT_ROOT__ = root;\n installPagesRouterRuntime();\n const hydratedAt = performance.now();\n window.__VINEXT_HYDRATED_AT = hydratedAt;\n window.__NEXT_HYDRATED = true;\n window.__NEXT_HYDRATED_AT = hydratedAt;\n window.__NEXT_HYDRATED_CB?.();\n}\n\nhydrate();\n`;\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAsBA,eAAsB,oBACpB,UACA,YACA,aACA,UAAsE,EAAE,EACvD;CACjB,MAAM,aAAa,MAAM,YAAY,UAAU,YAAY,gBAAgB,YAAY;CAEvF,MAAM,cAAc,iBAAiB,UAAU,QAAQ,YAAY;CACnE,MAAM,SAAS,gBAAgB;CAC/B,MAAM,oBAAoB,QAAQ,qBAAqB,EAAE;CAKzD,MAAM,gBAAgB,WAAW,KAAK,MAAa;EACjD,MAAM,UAAU,wBAAwB,EAAE,SAAS;EACnD,MAAM,oBAAoBA,oBAAyB,EAAE,QAAQ;EAI7D,OAAO,KAAK,KAAK,UAAU,kBAAkB,CAAC,iBAAiB,KAAK,UAAU,QAAQ,CAAC;GACvF;CAEF,MAAM,cAAc,cAAc,wBAAwB,YAAY,GAAG,KAAA;CAEzE,OAAO;;;;;;;;;;;;;;;;;;;;EAoBP,cAAc,KAAK,MAAM,CAAC;;EAG1B,SACI;iCAC2B,KAAK,UAAU,YAAa,CAAC;IAExD;;EAGL;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2CA+B0C,KAAK,UAAU,kBAAkB,CAAC;;;;;;;;;;;;;;;;;;;;;;;;IAyBzE,SACI;;;;;;;;;MAUA;;IAGL"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { apiRouter, pagesRouter } from "../routing/pages-router.js";
|
|
2
|
-
import { normalizePathSeparators
|
|
2
|
+
import { normalizePathSeparators } from "../utils/path.js";
|
|
3
|
+
import { resolveEntryPath } from "./runtime-entry-module.js";
|
|
3
4
|
import { isProxyFile } from "../server/middleware.js";
|
|
4
5
|
import { findFileWithExts } from "./pages-entry-helpers.js";
|
|
5
6
|
//#region src/entries/pages-server-entry.ts
|
|
@@ -18,7 +19,9 @@ const _routeTriePath = resolveEntryPath("../routing/route-trie.js", import.meta.
|
|
|
18
19
|
const _pagesI18nPath = resolveEntryPath("../server/pages-i18n.js", import.meta.url);
|
|
19
20
|
const _pagesPageResponsePath = resolveEntryPath("../server/pages-page-response.js", import.meta.url);
|
|
20
21
|
const _pagesPageDataPath = resolveEntryPath("../server/pages-page-data.js", import.meta.url);
|
|
22
|
+
const _pagesPageMethodPath = resolveEntryPath("../server/pages-page-method.js", import.meta.url);
|
|
21
23
|
const _pagesDataRoutePath = resolveEntryPath("../server/pages-data-route.js", import.meta.url);
|
|
24
|
+
const _pagesDefault404Path = resolveEntryPath("../server/pages-default-404.js", import.meta.url);
|
|
22
25
|
const _pagesNodeCompatPath = resolveEntryPath("../server/pages-node-compat.js", import.meta.url);
|
|
23
26
|
const _pagesApiRoutePath = resolveEntryPath("../server/pages-api-route.js", import.meta.url);
|
|
24
27
|
const _isrCachePath = resolveEntryPath("../server/isr-cache.js", import.meta.url);
|
|
@@ -46,9 +49,12 @@ async function generateServerEntry(pagesDir, nextConfig, fileMatcher, middleware
|
|
|
46
49
|
const apiRouteEntries = apiRoutes.map((r, i) => ` { pattern: ${JSON.stringify(r.pattern)}, patternParts: ${JSON.stringify(r.patternParts)}, isDynamic: ${r.isDynamic}, params: ${JSON.stringify(r.params)}, module: api_${i} }`);
|
|
47
50
|
const appFilePath = findFileWithExts(pagesDir, "_app", fileMatcher);
|
|
48
51
|
const docFilePath = findFileWithExts(pagesDir, "_document", fileMatcher);
|
|
52
|
+
const errorFilePath = findFileWithExts(pagesDir, "_error", fileMatcher);
|
|
49
53
|
const appAssetPathJson = appFilePath !== null ? JSON.stringify(normalizePathSeparators(appFilePath)) : "null";
|
|
50
54
|
const appImportCode = appFilePath !== null ? `import { default as AppComponent } from ${JSON.stringify(normalizePathSeparators(appFilePath))};` : `const AppComponent = null;`;
|
|
51
55
|
const docImportCode = docFilePath !== null ? `import { default as DocumentComponent } from ${JSON.stringify(normalizePathSeparators(docFilePath))};` : `const DocumentComponent = null;`;
|
|
56
|
+
const errorAssetPathJson = errorFilePath !== null ? JSON.stringify(normalizePathSeparators(errorFilePath)) : "null";
|
|
57
|
+
const errorImportCode = errorFilePath !== null ? `import * as ErrorPageModule from ${JSON.stringify(normalizePathSeparators(errorFilePath))};` : `const ErrorPageModule = null;`;
|
|
52
58
|
const i18nConfigJson = nextConfig?.i18n ? JSON.stringify({
|
|
53
59
|
locales: nextConfig.i18n.locales,
|
|
54
60
|
defaultLocale: nextConfig.i18n.defaultLocale,
|
|
@@ -69,6 +75,8 @@ async function generateServerEntry(pagesDir, nextConfig, fileMatcher, middleware
|
|
|
69
75
|
headers: nextConfig?.headers ?? [],
|
|
70
76
|
expireTime: nextConfig?.expireTime,
|
|
71
77
|
i18n: nextConfig?.i18n ?? null,
|
|
78
|
+
disableOptimizedLoading: nextConfig?.disableOptimizedLoading === true,
|
|
79
|
+
clientTraceMetadata: nextConfig?.clientTraceMetadata,
|
|
72
80
|
images: {
|
|
73
81
|
deviceSizes: nextConfig?.images?.deviceSizes,
|
|
74
82
|
imageSizes: nextConfig?.images?.imageSizes,
|
|
@@ -93,19 +101,44 @@ if (typeof _instrumentation.onRequestError === "function") {
|
|
|
93
101
|
const middlewareImportCode = middlewarePath ? `import * as middlewareModule from ${JSON.stringify(normalizePathSeparators(middlewarePath))};` : "";
|
|
94
102
|
const middlewareExportCode = middlewarePath ? `
|
|
95
103
|
export async function runMiddleware(request, ctx, options) {
|
|
96
|
-
|
|
104
|
+
// Auto-detect /_next/data/<buildId>/<page>.json requests so user-written
|
|
105
|
+
// worker entries don't need to know about the data endpoint protocol.
|
|
106
|
+
// Mismatched buildId → JSON 404 short-circuit. Matched → middleware sees
|
|
107
|
+
// the normalized page path via the request URL, and the worker sees the
|
|
108
|
+
// normalized URL via result.rewriteUrl (if middleware didn't already
|
|
109
|
+
// rewrite to something else).
|
|
110
|
+
const __dataNorm = __normalizePagesDataRequest(request);
|
|
111
|
+
if (__dataNorm.notFoundResponse) {
|
|
112
|
+
return { continue: false, response: __dataNorm.notFoundResponse };
|
|
113
|
+
}
|
|
114
|
+
const __result = await __runGeneratedMiddleware({
|
|
97
115
|
basePath: vinextConfig.basePath,
|
|
98
116
|
ctx,
|
|
99
117
|
i18nConfig,
|
|
100
|
-
isDataRequest: options?.isDataRequest === true,
|
|
118
|
+
isDataRequest: options?.isDataRequest === true || __dataNorm.isDataReq,
|
|
101
119
|
isProxy: ${JSON.stringify(isProxyFile(middlewarePath))},
|
|
102
120
|
module: middlewareModule,
|
|
103
|
-
request,
|
|
121
|
+
request: __dataNorm.request,
|
|
104
122
|
trailingSlash: vinextConfig.trailingSlash,
|
|
105
123
|
});
|
|
124
|
+
if (__dataNorm.isDataReq && __result.continue && !__result.rewriteUrl && !__result.redirectUrl) {
|
|
125
|
+
return { ...__result, rewriteUrl: __dataNorm.normalizedPathname + __dataNorm.search };
|
|
126
|
+
}
|
|
127
|
+
return __result;
|
|
106
128
|
}
|
|
107
129
|
` : `
|
|
108
|
-
export async function runMiddleware() {
|
|
130
|
+
export async function runMiddleware(request) {
|
|
131
|
+
// Even without user middleware, the data-endpoint URL must be normalized so
|
|
132
|
+
// the worker pipeline sees the page path. Mismatched buildId → JSON 404.
|
|
133
|
+
const __dataNorm = __normalizePagesDataRequest(request);
|
|
134
|
+
if (__dataNorm.notFoundResponse) {
|
|
135
|
+
return { continue: false, response: __dataNorm.notFoundResponse };
|
|
136
|
+
}
|
|
137
|
+
if (__dataNorm.isDataReq) {
|
|
138
|
+
return { continue: true, rewriteUrl: __dataNorm.normalizedPathname + __dataNorm.search };
|
|
139
|
+
}
|
|
140
|
+
return { continue: true };
|
|
141
|
+
}
|
|
109
142
|
`;
|
|
110
143
|
return `
|
|
111
144
|
import ${JSON.stringify(_serverGlobalsPath)};
|
|
@@ -142,7 +175,9 @@ import {
|
|
|
142
175
|
} from ${JSON.stringify(_isrCachePath)};
|
|
143
176
|
import { getScriptNonceFromHeaderSources as __getScriptNonceFromHeaderSources } from ${JSON.stringify(_cspPath)};
|
|
144
177
|
import { resolvePagesPageData as __resolvePagesPageData } from ${JSON.stringify(_pagesPageDataPath)};
|
|
145
|
-
import {
|
|
178
|
+
import { resolvePagesPageMethodResponse as __resolvePagesPageMethodResponse } from ${JSON.stringify(_pagesPageMethodPath)};
|
|
179
|
+
import { buildNextDataJsonResponse as __buildNextDataJsonResponse, buildNextDataNotFoundResponse as __buildNextDataNotFoundResponse, isNextDataPathname as __isNextDataPathname, parseNextDataPathname as __parseNextDataPathname } from ${JSON.stringify(_pagesDataRoutePath)};
|
|
180
|
+
import { buildDefaultPagesNotFoundResponse as __buildDefaultPagesNotFoundResponse } from ${JSON.stringify(_pagesDefault404Path)};
|
|
146
181
|
import { renderPagesPageResponse as __renderPagesPageResponse } from ${JSON.stringify(_pagesPageResponsePath)};
|
|
147
182
|
${instrumentationImportCode}
|
|
148
183
|
${middlewareImportCode}
|
|
@@ -156,6 +191,7 @@ const i18nConfig = ${i18nConfigJson};
|
|
|
156
191
|
// match _next/data requests against the embedded buildId without needing
|
|
157
192
|
// to load next.config.js at runtime.
|
|
158
193
|
export const buildId = ${buildIdJson};
|
|
194
|
+
const __hasMiddleware = ${JSON.stringify(Boolean(middlewarePath))};
|
|
159
195
|
|
|
160
196
|
// Full resolved config for production server (embedded at build time)
|
|
161
197
|
export const vinextConfig = ${vinextConfigJson};
|
|
@@ -178,6 +214,40 @@ function isrCacheKey(router, pathname) {
|
|
|
178
214
|
return __sharedIsrCacheKey(router, pathname, buildId || undefined);
|
|
179
215
|
}
|
|
180
216
|
|
|
217
|
+
/**
|
|
218
|
+
* Detect and normalize /_next/data/<buildId>/<page>.json requests in one
|
|
219
|
+
* place so user-written worker entries don't need to know about the data
|
|
220
|
+
* endpoint protocol. Returns the normalized request (with the page path as
|
|
221
|
+
* its URL), an isDataReq flag, and notFoundResponse when the buildId in
|
|
222
|
+
* the URL does not match this server's buildId — callers should return that
|
|
223
|
+
* response immediately so a stale client falls back to a hard navigation.
|
|
224
|
+
*/
|
|
225
|
+
function __normalizePagesDataRequest(request) {
|
|
226
|
+
const reqUrl = new URL(request.url);
|
|
227
|
+
if (!__isNextDataPathname(reqUrl.pathname)) {
|
|
228
|
+
return { isDataReq: false, request, normalizedPathname: null, search: "", notFoundResponse: null };
|
|
229
|
+
}
|
|
230
|
+
const dataMatch = buildId ? __parseNextDataPathname(reqUrl.pathname, buildId) : null;
|
|
231
|
+
if (!dataMatch) {
|
|
232
|
+
return {
|
|
233
|
+
isDataReq: false,
|
|
234
|
+
request,
|
|
235
|
+
normalizedPathname: null,
|
|
236
|
+
search: "",
|
|
237
|
+
notFoundResponse: __buildNextDataNotFoundResponse(),
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
const normalizedUrl = new URL(reqUrl);
|
|
241
|
+
normalizedUrl.pathname = dataMatch.pagePathname;
|
|
242
|
+
return {
|
|
243
|
+
isDataReq: true,
|
|
244
|
+
request: new Request(normalizedUrl, request),
|
|
245
|
+
normalizedPathname: dataMatch.pagePathname,
|
|
246
|
+
search: reqUrl.search,
|
|
247
|
+
notFoundResponse: null,
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
|
|
181
251
|
async function renderToStringAsync(element) {
|
|
182
252
|
const stream = await renderToReadableStream(element);
|
|
183
253
|
await stream.allReady;
|
|
@@ -204,11 +274,22 @@ ${apiImports.join("\n")}
|
|
|
204
274
|
|
|
205
275
|
${appImportCode}
|
|
206
276
|
${docImportCode}
|
|
277
|
+
${errorImportCode}
|
|
207
278
|
|
|
208
279
|
export const pageRoutes = [
|
|
209
280
|
${pageRouteEntries.join(",\n")}
|
|
210
281
|
];
|
|
211
282
|
const _pageRouteTrie = _buildRouteTrie(pageRoutes);
|
|
283
|
+
const _errorPageRoute = ErrorPageModule
|
|
284
|
+
? {
|
|
285
|
+
pattern: "/_error",
|
|
286
|
+
patternParts: ["_error"],
|
|
287
|
+
isDynamic: false,
|
|
288
|
+
params: [],
|
|
289
|
+
module: ErrorPageModule,
|
|
290
|
+
filePath: ${errorAssetPathJson},
|
|
291
|
+
}
|
|
292
|
+
: null;
|
|
212
293
|
|
|
213
294
|
const apiRoutes = [
|
|
214
295
|
${apiRouteEntries.join(",\n")}
|
|
@@ -240,7 +321,14 @@ export function matchPageRoute(url, request) {
|
|
|
240
321
|
}
|
|
241
322
|
|
|
242
323
|
function parseQuery(url) {
|
|
243
|
-
|
|
324
|
+
// Per RFC 3986 only the first "?" separates path from query, so additional
|
|
325
|
+
// "?" chars belong to the query string (e.g. /linker?href=/about?hello=world
|
|
326
|
+
// has query "href=/about?hello=world"). split("?")[1] would drop everything
|
|
327
|
+
// after the second "?" and strip embedded query strings from values.
|
|
328
|
+
const queryIndex = url.indexOf("?");
|
|
329
|
+
if (queryIndex === -1) return {};
|
|
330
|
+
const hashIndex = url.indexOf("#", queryIndex + 1);
|
|
331
|
+
const qs = hashIndex === -1 ? url.slice(queryIndex + 1) : url.slice(queryIndex + 1, hashIndex);
|
|
244
332
|
if (!qs) return {};
|
|
245
333
|
const p = new URLSearchParams(qs);
|
|
246
334
|
const q = {};
|
|
@@ -268,14 +356,39 @@ function patternToNextFormat(pattern) {
|
|
|
268
356
|
.replace(/:([^\\/]+?)(?=\\/|$)/g, "[$1]");
|
|
269
357
|
}
|
|
270
358
|
|
|
271
|
-
function
|
|
359
|
+
function resolveSsrManifest(manifest) {
|
|
272
360
|
// Fall back to embedded manifest (set by vinext:cloudflare-build for Workers)
|
|
273
|
-
|
|
361
|
+
return (manifest && Object.keys(manifest).length > 0)
|
|
274
362
|
? manifest
|
|
275
363
|
: (typeof globalThis !== "undefined" && globalThis.__VINEXT_SSR_MANIFEST__) || null;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
function getManifestFilesForModule(manifest, moduleId) {
|
|
367
|
+
if (!manifest || !moduleId) return null;
|
|
368
|
+
|
|
369
|
+
var files = manifest[moduleId];
|
|
370
|
+
if (files) return files;
|
|
371
|
+
|
|
372
|
+
for (var key in manifest) {
|
|
373
|
+
if (moduleId.endsWith("/" + key) || moduleId === key) {
|
|
374
|
+
return manifest[key];
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
return null;
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
function collectAssetTags(manifest, moduleIds, scriptNonce) {
|
|
381
|
+
const m = resolveSsrManifest(manifest);
|
|
276
382
|
const tags = [];
|
|
277
383
|
const seen = new Set();
|
|
278
384
|
const nonceAttr = __createNonceAttribute(scriptNonce);
|
|
385
|
+
// Mirrors Next.js \`_document\` behaviour: when \`experimental.disableOptimizedLoading\`
|
|
386
|
+
// is false (the default), page scripts are emitted with \`defer\` in <head>. See
|
|
387
|
+
// .nextjs-ref/packages/next/src/pages/_document.tsx getScripts() — \`defer={!disableOptimizedLoading}\`.
|
|
388
|
+
// vinext always emits \`type="module"\` (which already defers implicitly), but
|
|
389
|
+
// upstream tests (e.g. test/e2e/optimized-loading) assert the literal \`defer\`
|
|
390
|
+
// attribute, and adding it preserves parity without changing browser behaviour.
|
|
391
|
+
const deferAttr = vinextConfig.disableOptimizedLoading ? "" : " defer";
|
|
279
392
|
|
|
280
393
|
// Load the set of lazy chunk filenames (only reachable via dynamic imports).
|
|
281
394
|
// These should NOT get <link rel="modulepreload"> or <script type="module">
|
|
@@ -289,7 +402,7 @@ function collectAssetTags(manifest, moduleIds, scriptNonce) {
|
|
|
289
402
|
const entry = globalThis.__VINEXT_CLIENT_ENTRY__;
|
|
290
403
|
seen.add(entry);
|
|
291
404
|
tags.push('<link rel="modulepreload"' + nonceAttr + ' href="/' + entry + '" />');
|
|
292
|
-
tags.push('<script type="module"' + nonceAttr + ' src="/' + entry + '" crossorigin><\/script>');
|
|
405
|
+
tags.push('<script type="module"' + deferAttr + nonceAttr + ' src="/' + entry + '" crossorigin><\/script>');
|
|
293
406
|
}
|
|
294
407
|
if (m) {
|
|
295
408
|
// Always inject shared chunks (framework, vinext runtime, entry) and
|
|
@@ -305,18 +418,7 @@ function collectAssetTags(manifest, moduleIds, scriptNonce) {
|
|
|
305
418
|
// Collect assets for the requested page modules
|
|
306
419
|
for (var mi = 0; mi < moduleIds.length; mi++) {
|
|
307
420
|
var id = moduleIds[mi];
|
|
308
|
-
var files = m
|
|
309
|
-
if (!files) {
|
|
310
|
-
// Absolute path didn't match — try matching by suffix.
|
|
311
|
-
// Manifest keys are relative (e.g. "pages/about.tsx") while
|
|
312
|
-
// moduleIds may be absolute (e.g. "/home/.../pages/about.tsx").
|
|
313
|
-
for (var mk in m) {
|
|
314
|
-
if (id.endsWith("/" + mk) || id === mk) {
|
|
315
|
-
files = m[mk];
|
|
316
|
-
break;
|
|
317
|
-
}
|
|
318
|
-
}
|
|
319
|
-
}
|
|
421
|
+
var files = getManifestFilesForModule(m, id);
|
|
320
422
|
if (files) {
|
|
321
423
|
for (var fi = 0; fi < files.length; fi++) allFiles.push(files[fi]);
|
|
322
424
|
}
|
|
@@ -370,20 +472,55 @@ function collectAssetTags(manifest, moduleIds, scriptNonce) {
|
|
|
370
472
|
// (React.lazy, next/dynamic) and should only be fetched on demand.
|
|
371
473
|
if (lazySet && lazySet.has(tf)) continue;
|
|
372
474
|
tags.push('<link rel="modulepreload"' + nonceAttr + ' href="/' + tf + '" />');
|
|
373
|
-
tags.push('<script type="module"' + nonceAttr + ' src="/' + tf + '" crossorigin><\/script>');
|
|
475
|
+
tags.push('<script type="module"' + deferAttr + nonceAttr + ' src="/' + tf + '" crossorigin><\/script>');
|
|
374
476
|
}
|
|
375
477
|
}
|
|
376
478
|
}
|
|
377
479
|
return tags.join("\\n ");
|
|
378
480
|
}
|
|
379
481
|
|
|
482
|
+
function resolveClientModuleUrl(manifest, moduleId) {
|
|
483
|
+
const files = getManifestFilesForModule(resolveSsrManifest(manifest), moduleId);
|
|
484
|
+
if (!files) return undefined;
|
|
485
|
+
for (var i = 0; i < files.length; i++) {
|
|
486
|
+
var file = files[i];
|
|
487
|
+
if (!file || !file.endsWith(".js")) continue;
|
|
488
|
+
if (file.charAt(0) !== "/") file = "/" + file;
|
|
489
|
+
return file;
|
|
490
|
+
}
|
|
491
|
+
return undefined;
|
|
492
|
+
}
|
|
493
|
+
|
|
380
494
|
export async function renderPage(request, url, manifest, ctx, middlewareHeaders, options) {
|
|
381
495
|
if (ctx) return _runWithExecutionContext(ctx, () => _renderPage(request, url, manifest, middlewareHeaders, options));
|
|
382
496
|
return _renderPage(request, url, manifest, middlewareHeaders, options);
|
|
383
497
|
}
|
|
384
498
|
|
|
385
499
|
async function _renderPage(request, url, manifest, middlewareHeaders, options) {
|
|
386
|
-
|
|
500
|
+
let isDataReq = !!(options && options.isDataReq);
|
|
501
|
+
// Auto-detect /_next/data/... requests by inspecting the incoming request
|
|
502
|
+
// URL. The worker pipeline does not need to know about the data endpoint
|
|
503
|
+
// protocol — when it forwards an unrewritten data URL as the url arg, we
|
|
504
|
+
// normalize it to the page path here.
|
|
505
|
+
if (!isDataReq) {
|
|
506
|
+
const __dataNorm = __normalizePagesDataRequest(request);
|
|
507
|
+
if (__dataNorm.notFoundResponse) return __dataNorm.notFoundResponse;
|
|
508
|
+
if (__dataNorm.isDataReq) {
|
|
509
|
+
isDataReq = true;
|
|
510
|
+
if (url && url.startsWith("/_next/data/")) {
|
|
511
|
+
const __qs = url.includes("?") ? url.slice(url.indexOf("?")) : "";
|
|
512
|
+
url = __dataNorm.normalizedPathname + __qs;
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
const statusCode = options && typeof options.statusCode === "number" ? options.statusCode : undefined;
|
|
517
|
+
const asPath = options && typeof options.asPath === "string" ? options.asPath : undefined;
|
|
518
|
+
const renderErrorPageOnMiss = !(options && options.renderErrorPageOnMiss === false);
|
|
519
|
+
// Guard against infinite recursion when the user's custom 500/error page
|
|
520
|
+
// itself throws during render. When this flag is set, the catch block below
|
|
521
|
+
// returns the plain "Internal Server Error" text response instead of trying
|
|
522
|
+
// to render an error page again. Fixes #1458.
|
|
523
|
+
const isInternalErrorRender = !!(options && options.__isInternalErrorRender);
|
|
387
524
|
const localeInfo = i18nConfig
|
|
388
525
|
? resolvePagesI18nRequest(
|
|
389
526
|
url,
|
|
@@ -405,13 +542,35 @@ async function _renderPage(request, url, manifest, middlewareHeaders, options) {
|
|
|
405
542
|
return new Response(null, { status: 307, headers: { Location: localeInfo.redirectUrl } });
|
|
406
543
|
}
|
|
407
544
|
|
|
408
|
-
|
|
545
|
+
// Internal error render path: caller has pinned a specific route (the
|
|
546
|
+
// user's pages/500 or pages/_error) to render in response to an SSR throw.
|
|
547
|
+
// Skip route matching so we don't accidentally double-route, and skip the
|
|
548
|
+
// missing-route 404 fallback. See catch block below. Fixes #1458.
|
|
549
|
+
let match = options && options.__forcedRoute
|
|
550
|
+
? { route: options.__forcedRoute, params: {} }
|
|
551
|
+
: matchRoute(routeUrl, pageRoutes);
|
|
552
|
+
let renderStatusCodeOverride = statusCode;
|
|
553
|
+
let renderAsPath = asPath;
|
|
409
554
|
if (!match) {
|
|
410
555
|
if (isDataReq) {
|
|
411
556
|
return __buildNextDataNotFoundResponse();
|
|
412
557
|
}
|
|
413
|
-
|
|
414
|
-
|
|
558
|
+
if (!renderErrorPageOnMiss) {
|
|
559
|
+
return __buildDefaultPagesNotFoundResponse();
|
|
560
|
+
}
|
|
561
|
+
const notFoundMatch = matchRoute("/404", pageRoutes);
|
|
562
|
+
// matchRoute may match a catch-all (e.g. [...slug]); only use the explicit pages/404 route.
|
|
563
|
+
if (notFoundMatch && notFoundMatch.route.pattern === "/404") {
|
|
564
|
+
match = notFoundMatch;
|
|
565
|
+
renderStatusCodeOverride = 404;
|
|
566
|
+
renderAsPath = routeUrl;
|
|
567
|
+
} else if (_errorPageRoute) {
|
|
568
|
+
match = { route: _errorPageRoute, params: {} };
|
|
569
|
+
renderStatusCodeOverride = 404;
|
|
570
|
+
renderAsPath = routeUrl;
|
|
571
|
+
} else {
|
|
572
|
+
return __buildDefaultPagesNotFoundResponse();
|
|
573
|
+
}
|
|
415
574
|
}
|
|
416
575
|
|
|
417
576
|
const { route, params } = match;
|
|
@@ -422,12 +581,13 @@ async function _renderPage(request, url, manifest, middlewareHeaders, options) {
|
|
|
422
581
|
ensureFetchPatch();
|
|
423
582
|
try {
|
|
424
583
|
const routePattern = patternToNextFormat(route.pattern);
|
|
584
|
+
const renderStatusCode = renderStatusCodeOverride ?? (routePattern === "/404" ? 404 : undefined);
|
|
425
585
|
const query = mergeRouteParamsIntoQuery(parseQuery(routeUrl), params);
|
|
426
586
|
if (typeof setSSRContext === "function") {
|
|
427
587
|
setSSRContext({
|
|
428
588
|
pathname: routePattern,
|
|
429
589
|
query,
|
|
430
|
-
asPath: routeUrl,
|
|
590
|
+
asPath: renderAsPath || routeUrl,
|
|
431
591
|
locale: locale,
|
|
432
592
|
locales: i18nConfig ? i18nConfig.locales : undefined,
|
|
433
593
|
defaultLocale: currentDefaultLocale,
|
|
@@ -450,6 +610,31 @@ async function _renderPage(request, url, manifest, middlewareHeaders, options) {
|
|
|
450
610
|
if (!PageComponent) {
|
|
451
611
|
return new Response("Page has no default export", { status: 500 });
|
|
452
612
|
}
|
|
613
|
+
|
|
614
|
+
// Refs #1463: reject non-GET/HEAD methods on static (no
|
|
615
|
+
// getServerSideProps) Pages routes with 405 + Allow: GET, HEAD.
|
|
616
|
+
// Skip for error/status pages (/_error, /404, /500), data requests
|
|
617
|
+
// (those go through the JSON envelope path and have their own shape),
|
|
618
|
+
// and renders that are already an error-page miss-render override.
|
|
619
|
+
// Mirrors Next.js's base-server.ts L2277 carve-outs.
|
|
620
|
+
if (
|
|
621
|
+
!isDataReq &&
|
|
622
|
+
routePattern !== "/_error" &&
|
|
623
|
+
routePattern !== "/404" &&
|
|
624
|
+
routePattern !== "/500" &&
|
|
625
|
+
renderStatusCodeOverride === undefined
|
|
626
|
+
) {
|
|
627
|
+
const methodResponse = __resolvePagesPageMethodResponse({
|
|
628
|
+
hasGetServerSideProps: typeof pageModule.getServerSideProps === "function",
|
|
629
|
+
method: request.method,
|
|
630
|
+
});
|
|
631
|
+
if (methodResponse) {
|
|
632
|
+
return methodResponse;
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
const pageModuleUrl = resolveClientModuleUrl(manifest, route.filePath);
|
|
637
|
+
const appModuleUrl = resolveClientModuleUrl(manifest, _appAssetPath);
|
|
453
638
|
const scriptNonce = __getScriptNonceFromHeaderSources(request.headers, middlewareHeaders);
|
|
454
639
|
// Build font Link header early so it's available for ISR cached responses too.
|
|
455
640
|
// Font preloads are module-level state populated at import time and persist across requests.
|
|
@@ -470,7 +655,7 @@ async function _renderPage(request, url, manifest, middlewareHeaders, options) {
|
|
|
470
655
|
setSSRContext({
|
|
471
656
|
pathname: routePattern,
|
|
472
657
|
query,
|
|
473
|
-
asPath: routeUrl,
|
|
658
|
+
asPath: renderAsPath || routeUrl,
|
|
474
659
|
locale: locale,
|
|
475
660
|
locales: i18nConfig ? i18nConfig.locales : undefined,
|
|
476
661
|
defaultLocale: currentDefaultLocale,
|
|
@@ -508,6 +693,13 @@ async function _renderPage(request, url, manifest, middlewareHeaders, options) {
|
|
|
508
693
|
isrGet,
|
|
509
694
|
isrSet,
|
|
510
695
|
expireSeconds: vinextConfig.expireTime,
|
|
696
|
+
// The vinext build phase boots the prod server with VINEXT_PRERENDER=1
|
|
697
|
+
// and fetches every statically-generated page through it. That hit is
|
|
698
|
+
// the "build" prerender for revalidateReason; runtime hits are not.
|
|
699
|
+
// Mirrors Next.js's \`renderOpts.isBuildTimePrerendering\`. See
|
|
700
|
+
// \`.nextjs-ref/packages/next/src/server/render.tsx\` and
|
|
701
|
+
// \`packages/vinext/src/build/prerender.ts\`.
|
|
702
|
+
isBuildTimePrerendering: typeof process !== "undefined" && process.env && process.env.VINEXT_PRERENDER === "1",
|
|
511
703
|
pageModule,
|
|
512
704
|
params,
|
|
513
705
|
query,
|
|
@@ -529,12 +721,21 @@ async function _renderPage(request, url, manifest, middlewareHeaders, options) {
|
|
|
529
721
|
safeJsonStringify,
|
|
530
722
|
sanitizeDestination: sanitizeDestinationLocal,
|
|
531
723
|
scriptNonce,
|
|
724
|
+
statusCode: renderStatusCode,
|
|
532
725
|
triggerBackgroundRegeneration,
|
|
726
|
+
vinext: {
|
|
727
|
+
pageModuleUrl,
|
|
728
|
+
appModuleUrl,
|
|
729
|
+
hasMiddleware: __hasMiddleware,
|
|
730
|
+
},
|
|
533
731
|
});
|
|
534
732
|
if (pageDataResult.kind === "response") {
|
|
535
733
|
return pageDataResult.response;
|
|
536
734
|
}
|
|
537
735
|
let pageProps = pageDataResult.pageProps;
|
|
736
|
+
if (routePattern === "/_error" && typeof renderStatusCode === "number") {
|
|
737
|
+
pageProps = { ...pageProps, statusCode: renderStatusCode };
|
|
738
|
+
}
|
|
538
739
|
var gsspRes = pageDataResult.gsspRes;
|
|
539
740
|
let isrRevalidateSeconds = pageDataResult.isrRevalidateSeconds;
|
|
540
741
|
const isFallbackRender = pageDataResult.isFallback === true;
|
|
@@ -547,7 +748,7 @@ async function _renderPage(request, url, manifest, middlewareHeaders, options) {
|
|
|
547
748
|
setSSRContext({
|
|
548
749
|
pathname: routePattern,
|
|
549
750
|
query,
|
|
550
|
-
asPath: routeUrl,
|
|
751
|
+
asPath: renderAsPath || routeUrl,
|
|
551
752
|
locale: locale,
|
|
552
753
|
locales: i18nConfig ? i18nConfig.locales : undefined,
|
|
553
754
|
defaultLocale: currentDefaultLocale,
|
|
@@ -564,14 +765,33 @@ async function _renderPage(request, url, manifest, middlewareHeaders, options) {
|
|
|
564
765
|
// cookies set on the gsspRes by getServerSideProps are forwarded so
|
|
565
766
|
// middleware/auth flows work the same as the HTML page.
|
|
566
767
|
if (isDataReq) {
|
|
567
|
-
const init = {};
|
|
568
|
-
if (gsspRes && gsspRes.
|
|
569
|
-
|
|
570
|
-
for (const
|
|
768
|
+
const init = { headers: {} };
|
|
769
|
+
if (gsspRes && typeof gsspRes.getHeaders === "function") {
|
|
770
|
+
const gsspHeaders = gsspRes.getHeaders();
|
|
771
|
+
for (const k of Object.keys(gsspHeaders)) {
|
|
772
|
+
const v = gsspHeaders[k];
|
|
571
773
|
if (v === undefined || v === null) continue;
|
|
572
774
|
init.headers[k] = Array.isArray(v) ? v.join(", ") : String(v);
|
|
573
775
|
}
|
|
574
776
|
}
|
|
777
|
+
if (gsspRes) {
|
|
778
|
+
// Default Cache-Control for gSSP-driven _next/data responses,
|
|
779
|
+
// matching Next.js's pages-handler.ts (revalidate: 0 →
|
|
780
|
+
// getCacheControlHeader). Skip when gSSP already set one via
|
|
781
|
+
// res.setHeader (case-insensitive). Mirrors the HTML branch in
|
|
782
|
+
// pages-page-response.ts and the dev-server branch. Fixes #1461.
|
|
783
|
+
var hasUserCacheControl = false;
|
|
784
|
+
for (const headerKey of Object.keys(init.headers)) {
|
|
785
|
+
if (headerKey.toLowerCase() === "cache-control") {
|
|
786
|
+
hasUserCacheControl = true;
|
|
787
|
+
break;
|
|
788
|
+
}
|
|
789
|
+
}
|
|
790
|
+
if (!hasUserCacheControl) {
|
|
791
|
+
init.headers["Cache-Control"] =
|
|
792
|
+
"private, no-cache, no-store, max-age=0, must-revalidate";
|
|
793
|
+
}
|
|
794
|
+
}
|
|
575
795
|
return __buildNextDataJsonResponse(pageProps, safeJsonStringify, init);
|
|
576
796
|
}
|
|
577
797
|
|
|
@@ -624,6 +844,7 @@ async function _renderPage(request, url, manifest, middlewareHeaders, options) {
|
|
|
624
844
|
}
|
|
625
845
|
},
|
|
626
846
|
getSSRHeadHTML: typeof getSSRHeadHTML === "function" ? getSSRHeadHTML : undefined,
|
|
847
|
+
clientTraceMetadata: vinextConfig.clientTraceMetadata,
|
|
627
848
|
gsspRes,
|
|
628
849
|
isrCacheKey,
|
|
629
850
|
expireSeconds: vinextConfig.expireTime,
|
|
@@ -649,6 +870,12 @@ async function _renderPage(request, url, manifest, middlewareHeaders, options) {
|
|
|
649
870
|
routeUrl,
|
|
650
871
|
safeJsonStringify,
|
|
651
872
|
scriptNonce,
|
|
873
|
+
statusCode: renderStatusCode,
|
|
874
|
+
vinext: {
|
|
875
|
+
pageModuleUrl,
|
|
876
|
+
appModuleUrl,
|
|
877
|
+
hasMiddleware: __hasMiddleware,
|
|
878
|
+
},
|
|
652
879
|
});
|
|
653
880
|
} catch (e) {
|
|
654
881
|
console.error("[vinext] SSR error:", e);
|
|
@@ -657,6 +884,37 @@ async function _renderPage(request, url, manifest, middlewareHeaders, options) {
|
|
|
657
884
|
{ path: url, method: request.method, headers: Object.fromEntries(request.headers.entries()) },
|
|
658
885
|
{ routerKind: "Pages Router", routePath: route.pattern, routeType: "render" },
|
|
659
886
|
).catch(() => { /* ignore reporting errors */ });
|
|
887
|
+
// Data (_next/data) requests can't render HTML, and avoid recursion if
|
|
888
|
+
// we're already in the middle of rendering the error page itself.
|
|
889
|
+
// Mirrors Next.js base-server.ts which renders /500 (or _error) when
|
|
890
|
+
// SSR throws. Fixes #1458.
|
|
891
|
+
if (!isInternalErrorRender && !isDataReq) {
|
|
892
|
+
// Look for an explicit pages/500.tsx first, then fall back to _error.
|
|
893
|
+
// Only match the literal /500 pattern — never a catch-all/dynamic route.
|
|
894
|
+
let errorRoute = null;
|
|
895
|
+
for (var __i = 0; __i < pageRoutes.length; __i++) {
|
|
896
|
+
if (pageRoutes[__i].pattern === "/500") {
|
|
897
|
+
errorRoute = pageRoutes[__i];
|
|
898
|
+
break;
|
|
899
|
+
}
|
|
900
|
+
}
|
|
901
|
+
if (!errorRoute && _errorPageRoute) {
|
|
902
|
+
errorRoute = _errorPageRoute;
|
|
903
|
+
}
|
|
904
|
+
if (errorRoute) {
|
|
905
|
+
try {
|
|
906
|
+
return await _renderPage(request, url, manifest, middlewareHeaders, {
|
|
907
|
+
statusCode: 500,
|
|
908
|
+
asPath: url,
|
|
909
|
+
renderErrorPageOnMiss: false,
|
|
910
|
+
__isInternalErrorRender: true,
|
|
911
|
+
__forcedRoute: errorRoute,
|
|
912
|
+
});
|
|
913
|
+
} catch (errorPageErr) {
|
|
914
|
+
console.error("[vinext] Error page render failed:", errorPageErr);
|
|
915
|
+
}
|
|
916
|
+
}
|
|
917
|
+
}
|
|
660
918
|
return new Response("Internal Server Error", { status: 500 });
|
|
661
919
|
}
|
|
662
920
|
});
|