vinext 0.1.2 → 0.1.3
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/prerender.d.ts +9 -1
- package/dist/build/prerender.js +41 -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/vinext-next-data.d.ts +18 -1
- 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.js +73 -14
- package/dist/config/next-config.d.ts +46 -4
- package/dist/config/next-config.js +147 -48
- package/dist/deploy.d.ts +30 -11
- package/dist/deploy.js +180 -99
- 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 +64 -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 +53 -8
- package/dist/entries/pages-server-entry.js +41 -5
- package/dist/index.js +200 -62
- package/dist/plugins/extensionless-dynamic-import.d.ts +6 -0
- package/dist/plugins/extensionless-dynamic-import.js +152 -0
- 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/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 +44 -14
- 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 +19 -10
- package/dist/server/app-browser-entry.js +167 -90
- 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 +4 -2
- 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-stream.js +86 -43
- 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 +18 -0
- package/dist/server/app-pages-bridge.js +22 -5
- 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 +25 -0
- package/dist/server/app-rsc-handler.js +154 -54
- package/dist/server/app-rsc-route-matching.d.ts +3 -0
- package/dist/server/app-rsc-route-matching.js +2 -0
- 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 +42 -13
- package/dist/server/app-ssr-entry.d.ts +2 -0
- package/dist/server/app-ssr-entry.js +83 -10
- package/dist/server/cache-control.js +4 -0
- package/dist/server/dev-server.d.ts +2 -2
- package/dist/server/dev-server.js +244 -51
- 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/navigation-planner.d.ts +133 -30
- package/dist/server/navigation-planner.js +114 -0
- package/dist/server/navigation-trace.d.ts +8 -1
- package/dist/server/navigation-trace.js +8 -1
- 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 +8 -1
- package/dist/server/pages-data-route.js +11 -2
- 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-node-compat.js +2 -2
- package/dist/server/pages-page-data.d.ts +11 -2
- package/dist/server/pages-page-data.js +204 -33
- package/dist/server/pages-page-handler.d.ts +4 -2
- package/dist/server/pages-page-handler.js +59 -22
- package/dist/server/pages-page-response.d.ts +2 -1
- package/dist/server/pages-page-response.js +7 -4
- package/dist/server/pages-request-pipeline.d.ts +1 -0
- package/dist/server/pages-request-pipeline.js +73 -36
- 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.js +9 -3
- 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/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/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/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/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-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 +12 -5
- package/dist/shims/navigation.d.ts +8 -2
- package/dist/shims/navigation.js +61 -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 +13 -2
- package/dist/shims/router.js +419 -128
- 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/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/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
|
@@ -6,6 +6,7 @@ import { NEXTJS_DEPLOYMENT_ID_HEADER } from "./headers.js";
|
|
|
6
6
|
import { normalizeStaticPathname } from "../routing/route-pattern.js";
|
|
7
7
|
import { importModule, reportRequestError } from "./instrumentation.js";
|
|
8
8
|
import { buildCacheStateHeaders } from "./cache-headers.js";
|
|
9
|
+
import { isUnknownRecord } from "../utils/record.js";
|
|
9
10
|
import { _runWithCacheState } from "../shims/cache.js";
|
|
10
11
|
import { NEVER_CACHE_CONTROL, NO_STORE_CACHE_CONTROL } from "./cache-control.js";
|
|
11
12
|
import { buildMissIsrCacheControl, decideIsr } from "./isr-decision.js";
|
|
@@ -28,7 +29,8 @@ import { resolvePagesPageMethodResponse } from "./pages-page-method.js";
|
|
|
28
29
|
import { isSerializableProps } from "./pages-serializable-props.js";
|
|
29
30
|
import { loadUserDocumentInitialProps, runDocumentRenderPage } from "./pages-document-initial-props.js";
|
|
30
31
|
import { callDocumentGetInitialProps } from "./document-initial-head.js";
|
|
31
|
-
import { loadPagesGetInitialProps } from "./pages-get-initial-props.js";
|
|
32
|
+
import { hasPagesGetInitialProps, loadDevAppInitialProps, loadPagesGetInitialProps } from "./pages-get-initial-props.js";
|
|
33
|
+
import { isBotUserAgent } from "../utils/html-limited-bots.js";
|
|
32
34
|
import path from "node:path";
|
|
33
35
|
import React from "react";
|
|
34
36
|
import { renderToReadableStream } from "react-dom/server.edge";
|
|
@@ -60,7 +62,7 @@ async function renderIsrPassToStringAsync(element) {
|
|
|
60
62
|
* (`buildPagesRedirectResponse`) and Next.js's `render.tsx` `__N_REDIRECT`
|
|
61
63
|
* handling. See AGENTS.md "dev and prod server parity".
|
|
62
64
|
*/
|
|
63
|
-
function writeGsspRedirect(res, redirect, isDataReq) {
|
|
65
|
+
function writeGsspRedirect(res, redirect, isDataReq, props) {
|
|
64
66
|
const status = redirect.statusCode ?? (redirect.permanent ? 308 : 307);
|
|
65
67
|
let dest = redirect.destination;
|
|
66
68
|
if (!dest.startsWith("http://") && !dest.startsWith("https://")) dest = dest.replace(/^[\\/]+/, "/");
|
|
@@ -69,10 +71,14 @@ function writeGsspRedirect(res, redirect, isDataReq) {
|
|
|
69
71
|
const dataHeaders = { "Content-Type": "application/json" };
|
|
70
72
|
if (deploymentId) dataHeaders[NEXTJS_DEPLOYMENT_ID_HEADER] = deploymentId;
|
|
71
73
|
res.writeHead(200, dataHeaders);
|
|
72
|
-
res.end(JSON.stringify({
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
74
|
+
res.end(JSON.stringify({
|
|
75
|
+
...props,
|
|
76
|
+
pageProps: {
|
|
77
|
+
...isUnknownRecord(props.pageProps) ? props.pageProps : {},
|
|
78
|
+
__N_REDIRECT: dest,
|
|
79
|
+
__N_REDIRECT_STATUS: status
|
|
80
|
+
}
|
|
81
|
+
}));
|
|
76
82
|
return;
|
|
77
83
|
}
|
|
78
84
|
res.writeHead(status, { Location: dest });
|
|
@@ -190,12 +196,12 @@ function parseCookieLocale(req, i18nConfig) {
|
|
|
190
196
|
* 4. Render the component to HTML
|
|
191
197
|
* 5. Wrap in _document shell and send response
|
|
192
198
|
*/
|
|
193
|
-
function createSSRHandler(server, runner, routes, pagesDir, i18nConfig, fileMatcher, basePath = "", trailingSlash = false, hasMiddleware = false, hasRewrites = false, clientTraceMetadata) {
|
|
199
|
+
function createSSRHandler(server, runner, routes, pagesDir, i18nConfig, fileMatcher, basePath = "", trailingSlash = false, hasMiddleware = false, hasRewrites = false, clientTraceMetadata, htmlLimitedBots) {
|
|
194
200
|
const matcher = fileMatcher ?? createValidFileMatcher();
|
|
195
201
|
const pagePatterns = routes.map((r) => patternToNextFormat(r.pattern));
|
|
196
202
|
const _alsRegistration = Promise.all([runner.import("vinext/head-state"), runner.import("vinext/router-state")]);
|
|
197
203
|
_alsRegistration.catch(() => {});
|
|
198
|
-
return async (req, res, url, statusCode, isDataReq = false) => {
|
|
204
|
+
return async (req, res, url, statusCode, isDataReq = false, originalUrl = url) => {
|
|
199
205
|
const _reqStart = now();
|
|
200
206
|
let _compileEnd;
|
|
201
207
|
let _renderEnd;
|
|
@@ -245,6 +251,11 @@ function createSSRHandler(server, runner, routes, pagesDir, i18nConfig, fileMatc
|
|
|
245
251
|
return;
|
|
246
252
|
}
|
|
247
253
|
const { route, params } = match;
|
|
254
|
+
req.url = originalUrl;
|
|
255
|
+
const parsedResolvedUrl = new URL(localeStrippedUrl, "http://vinext.local");
|
|
256
|
+
const originalRequestSearch = new URL(originalUrl, "http://vinext.local").search;
|
|
257
|
+
const gsspResolvedUrl = parsedResolvedUrl.pathname + originalRequestSearch;
|
|
258
|
+
const requestAsPath = isDataReq ? gsspResolvedUrl : originalUrl;
|
|
248
259
|
const userFacingParams = route.isDynamic ? params : null;
|
|
249
260
|
const query = mergeRouteParamsIntoQuery(parseQueryString(url), params);
|
|
250
261
|
return runWithRequestContext(createRequestContext(), async () => {
|
|
@@ -278,7 +289,7 @@ function createSSRHandler(server, runner, routes, pagesDir, i18nConfig, fileMatc
|
|
|
278
289
|
if (typeof routerShim.setSSRContext === "function") routerShim.setSSRContext({
|
|
279
290
|
pathname: patternToNextFormat(route.pattern),
|
|
280
291
|
query,
|
|
281
|
-
asPath:
|
|
292
|
+
asPath: requestAsPath,
|
|
282
293
|
navigationIsReady,
|
|
283
294
|
nextData: pagesNextData,
|
|
284
295
|
locale: locale ?? currentDefaultLocale,
|
|
@@ -312,8 +323,10 @@ function createSSRHandler(server, runner, routes, pagesDir, i18nConfig, fileMatc
|
|
|
312
323
|
}
|
|
313
324
|
}
|
|
314
325
|
let pageProps = {};
|
|
326
|
+
let renderProps = { pageProps };
|
|
315
327
|
let isrRevalidateSeconds = null;
|
|
316
328
|
let isFallbackRender = false;
|
|
329
|
+
let shouldPersistFallbackData = false;
|
|
317
330
|
if (typeof pageModule.getStaticPaths === "function" && route.isDynamic) {
|
|
318
331
|
const pathsResult = await pageModule.getStaticPaths({
|
|
319
332
|
locales: i18nConfig?.locales ?? [],
|
|
@@ -344,12 +357,15 @@ function createSSRHandler(server, runner, routes, pagesDir, i18nConfig, fileMatc
|
|
|
344
357
|
await renderErrorPage(server, runner, req, res, url, pagesDir, 404, routerShim.wrapWithRouterContext, matcher);
|
|
345
358
|
return;
|
|
346
359
|
}
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
360
|
+
const userAgentHeader = req.headers["user-agent"];
|
|
361
|
+
const userAgent = Array.isArray(userAgentHeader) ? userAgentHeader[0] : userAgentHeader;
|
|
362
|
+
const isBotRequest = !!userAgent && isBotUserAgent(userAgent, htmlLimitedBots);
|
|
363
|
+
if (fallback === true && !isValidPath && !isDataReq && !isBotRequest) {
|
|
364
|
+
isFallbackRender = (await isrGet(pagesIsrCacheKey(url.split("?")[0])))?.value.value?.kind !== "PAGES";
|
|
365
|
+
if (isFallbackRender && typeof routerShim.setSSRContext === "function") routerShim.setSSRContext({
|
|
350
366
|
pathname: patternToNextFormat(route.pattern),
|
|
351
367
|
query,
|
|
352
|
-
asPath:
|
|
368
|
+
asPath: requestAsPath,
|
|
353
369
|
navigationIsReady: false,
|
|
354
370
|
locale: locale ?? currentDefaultLocale,
|
|
355
371
|
locales: i18nConfig?.locales,
|
|
@@ -358,25 +374,71 @@ function createSSRHandler(server, runner, routes, pagesDir, i18nConfig, fileMatc
|
|
|
358
374
|
isFallback: true
|
|
359
375
|
});
|
|
360
376
|
}
|
|
377
|
+
shouldPersistFallbackData = fallback === true && !isValidPath && isDataReq;
|
|
361
378
|
}
|
|
362
379
|
const gsspExtraHeaders = {};
|
|
380
|
+
const hasAppGetInitialProps = hasPagesGetInitialProps(AppComponent);
|
|
381
|
+
async function loadAppInitialProps() {
|
|
382
|
+
if (!hasAppGetInitialProps) return false;
|
|
383
|
+
const appResult = await loadDevAppInitialProps({
|
|
384
|
+
appComponent: AppComponent,
|
|
385
|
+
appTree: (appTreeProps) => {
|
|
386
|
+
const appTree = React.createElement(AppComponent, {
|
|
387
|
+
...appTreeProps,
|
|
388
|
+
Component: PageComponent,
|
|
389
|
+
pageProps: appTreeProps.pageProps,
|
|
390
|
+
router: routerShim.default
|
|
391
|
+
});
|
|
392
|
+
return typeof routerShim.wrapWithRouterContext === "function" ? routerShim.wrapWithRouterContext(appTree) : appTree;
|
|
393
|
+
},
|
|
394
|
+
component: PageComponent,
|
|
395
|
+
req,
|
|
396
|
+
res,
|
|
397
|
+
pathname: patternToNextFormat(route.pattern),
|
|
398
|
+
query,
|
|
399
|
+
asPath: requestAsPath,
|
|
400
|
+
locale: locale ?? currentDefaultLocale,
|
|
401
|
+
locales: i18nConfig?.locales,
|
|
402
|
+
defaultLocale: currentDefaultLocale
|
|
403
|
+
});
|
|
404
|
+
if (appResult.kind === "response-sent") return true;
|
|
405
|
+
if (appResult.kind === "render") {
|
|
406
|
+
pageProps = appResult.pageProps;
|
|
407
|
+
renderProps = appResult.renderProps;
|
|
408
|
+
}
|
|
409
|
+
return false;
|
|
410
|
+
}
|
|
363
411
|
if (typeof pageModule.getServerSideProps === "function" && !isFallbackRender) {
|
|
412
|
+
if (await loadAppInitialProps()) return;
|
|
413
|
+
renderProps = {
|
|
414
|
+
...renderProps,
|
|
415
|
+
__N_SSP: true
|
|
416
|
+
};
|
|
364
417
|
const headersBeforeGSSP = new Set(Object.keys(res.getHeaders()));
|
|
365
418
|
const context = {
|
|
366
419
|
params: userFacingParams,
|
|
367
420
|
req,
|
|
368
421
|
res,
|
|
369
422
|
query,
|
|
370
|
-
resolvedUrl:
|
|
423
|
+
resolvedUrl: gsspResolvedUrl,
|
|
371
424
|
locale: locale ?? currentDefaultLocale,
|
|
372
425
|
locales: i18nConfig?.locales,
|
|
373
426
|
defaultLocale: currentDefaultLocale
|
|
374
427
|
};
|
|
375
428
|
const result = await pageModule.getServerSideProps(context);
|
|
376
429
|
if (res.writableEnded) return;
|
|
377
|
-
if (result && "props" in result)
|
|
430
|
+
if (result && "props" in result) {
|
|
431
|
+
pageProps = {
|
|
432
|
+
...pageProps,
|
|
433
|
+
...await Promise.resolve(result.props)
|
|
434
|
+
};
|
|
435
|
+
renderProps = {
|
|
436
|
+
...renderProps,
|
|
437
|
+
pageProps
|
|
438
|
+
};
|
|
439
|
+
}
|
|
378
440
|
if (result && "redirect" in result) {
|
|
379
|
-
writeGsspRedirect(res, result.redirect, isDataReq);
|
|
441
|
+
writeGsspRedirect(res, result.redirect, isDataReq, renderProps);
|
|
380
442
|
return;
|
|
381
443
|
}
|
|
382
444
|
if (result && "notFound" in result && result.notFound) {
|
|
@@ -417,7 +479,7 @@ function createSSRHandler(server, runner, routes, pagesDir, i18nConfig, fileMatc
|
|
|
417
479
|
const cacheKey = pagesIsrCacheKey(url.split("?")[0]);
|
|
418
480
|
const cached = await isrGet(cacheKey);
|
|
419
481
|
const isOnDemandRevalidate = isOnDemandRevalidateRequest(req.headers[PRERENDER_REVALIDATE_HEADER]);
|
|
420
|
-
if (!isOnDemandRevalidate && cached && !cached.isStale && cached.value.value?.kind === "PAGES" && !scriptNonce && !isDataReq) {
|
|
482
|
+
if (!isOnDemandRevalidate && cached && !cached.isStale && cached.value.value?.kind === "PAGES" && !cached.value.value.generatedFromDataRequest && !scriptNonce && !isDataReq) {
|
|
421
483
|
const cachedHtml = cached.value.value.html;
|
|
422
484
|
const transformedHtml = await server.transformIndexHtml(url, cachedHtml);
|
|
423
485
|
const { cacheControl: hitCacheControl } = decideIsr({
|
|
@@ -435,12 +497,84 @@ function createSSRHandler(server, runner, routes, pagesDir, i18nConfig, fileMatc
|
|
|
435
497
|
res.end(transformedHtml);
|
|
436
498
|
return;
|
|
437
499
|
}
|
|
438
|
-
if (!isOnDemandRevalidate && cached && cached.isStale && cached.value.value?.kind === "PAGES" && !scriptNonce && !isDataReq) {
|
|
500
|
+
if (!isOnDemandRevalidate && cached && cached.isStale && cached.value.value?.kind === "PAGES" && !cached.value.value.generatedFromDataRequest && !scriptNonce && !isDataReq) {
|
|
439
501
|
const cachedHtml = cached.value.value.html;
|
|
440
502
|
const transformedHtml = await server.transformIndexHtml(url, cachedHtml);
|
|
441
503
|
triggerBackgroundRegeneration(cacheKey, async () => {
|
|
442
|
-
return runWithRequestContext(createRequestContext({
|
|
504
|
+
return runWithRequestContext(createRequestContext({
|
|
505
|
+
executionContext: null,
|
|
506
|
+
ssrContext: {
|
|
507
|
+
pathname: patternToNextFormat(route.pattern),
|
|
508
|
+
query,
|
|
509
|
+
asPath: requestAsPath,
|
|
510
|
+
navigationIsReady,
|
|
511
|
+
locale: locale ?? currentDefaultLocale,
|
|
512
|
+
locales: i18nConfig?.locales,
|
|
513
|
+
defaultLocale: currentDefaultLocale
|
|
514
|
+
},
|
|
515
|
+
i18nContext: i18nConfig ? {
|
|
516
|
+
locale: locale ?? currentDefaultLocale,
|
|
517
|
+
locales: i18nConfig.locales,
|
|
518
|
+
defaultLocale: currentDefaultLocale,
|
|
519
|
+
domainLocales,
|
|
520
|
+
hostname: req.headers.host?.split(":", 1)[0]
|
|
521
|
+
} : null
|
|
522
|
+
}), async () => {
|
|
443
523
|
ensureFetchPatch();
|
|
524
|
+
let freshPageProps = {};
|
|
525
|
+
let freshRenderProps = { pageProps: freshPageProps };
|
|
526
|
+
let RegenApp = null;
|
|
527
|
+
const appPath = path.join(pagesDir, "_app");
|
|
528
|
+
if (findFileWithExtensions(appPath, matcher)) try {
|
|
529
|
+
RegenApp = (await runner.import(appPath)).default ?? null;
|
|
530
|
+
} catch {}
|
|
531
|
+
if (RegenApp && hasPagesGetInitialProps(RegenApp)) {
|
|
532
|
+
const regenReq = {
|
|
533
|
+
url: req.url,
|
|
534
|
+
headers: req.headers,
|
|
535
|
+
method: req.method
|
|
536
|
+
};
|
|
537
|
+
const regenRes = {
|
|
538
|
+
headersSent: false,
|
|
539
|
+
writableEnded: false,
|
|
540
|
+
statusCode: 200,
|
|
541
|
+
getHeaders() {
|
|
542
|
+
return {};
|
|
543
|
+
}
|
|
544
|
+
};
|
|
545
|
+
const initialProps = await loadPagesGetInitialProps(RegenApp, {
|
|
546
|
+
AppTree: (appTreeProps) => {
|
|
547
|
+
const appTree = React.createElement(RegenApp, {
|
|
548
|
+
...appTreeProps,
|
|
549
|
+
Component: pageModule.default,
|
|
550
|
+
pageProps: appTreeProps.pageProps,
|
|
551
|
+
router: routerShim.default
|
|
552
|
+
});
|
|
553
|
+
return typeof routerShim.wrapWithRouterContext === "function" ? routerShim.wrapWithRouterContext(appTree) : appTree;
|
|
554
|
+
},
|
|
555
|
+
Component: pageModule.default,
|
|
556
|
+
router: {
|
|
557
|
+
pathname: patternToNextFormat(route.pattern),
|
|
558
|
+
query,
|
|
559
|
+
asPath: requestAsPath
|
|
560
|
+
},
|
|
561
|
+
ctx: {
|
|
562
|
+
req: regenReq,
|
|
563
|
+
res: regenRes,
|
|
564
|
+
pathname: patternToNextFormat(route.pattern),
|
|
565
|
+
query,
|
|
566
|
+
asPath: requestAsPath,
|
|
567
|
+
locale: locale ?? currentDefaultLocale,
|
|
568
|
+
locales: i18nConfig?.locales,
|
|
569
|
+
defaultLocale: currentDefaultLocale
|
|
570
|
+
}
|
|
571
|
+
});
|
|
572
|
+
if (regenRes.headersSent || regenRes.writableEnded) return;
|
|
573
|
+
if (initialProps) {
|
|
574
|
+
freshRenderProps = initialProps;
|
|
575
|
+
freshPageProps = isUnknownRecord(initialProps.pageProps) ? initialProps.pageProps : {};
|
|
576
|
+
}
|
|
577
|
+
}
|
|
444
578
|
const freshResult = await pageModule.getStaticProps({
|
|
445
579
|
params: userFacingParams,
|
|
446
580
|
locale: locale ?? currentDefaultLocale,
|
|
@@ -449,13 +583,20 @@ function createSSRHandler(server, runner, routes, pagesDir, i18nConfig, fileMatc
|
|
|
449
583
|
revalidateReason: "stale"
|
|
450
584
|
});
|
|
451
585
|
if (freshResult && "props" in freshResult) {
|
|
452
|
-
const revalidate = typeof freshResult.revalidate === "number" ? freshResult.revalidate : 0;
|
|
586
|
+
const revalidate = typeof freshResult.revalidate === "number" ? freshResult.revalidate : cached.value.cacheControl?.revalidate ?? 0;
|
|
453
587
|
if (revalidate > 0) {
|
|
454
|
-
|
|
588
|
+
freshPageProps = {
|
|
589
|
+
...freshPageProps,
|
|
590
|
+
...freshResult.props
|
|
591
|
+
};
|
|
592
|
+
freshRenderProps = {
|
|
593
|
+
...freshRenderProps,
|
|
594
|
+
pageProps: freshPageProps
|
|
595
|
+
};
|
|
455
596
|
if (typeof routerShim.setSSRContext === "function") routerShim.setSSRContext({
|
|
456
597
|
pathname: patternToNextFormat(route.pattern),
|
|
457
598
|
query,
|
|
458
|
-
asPath:
|
|
599
|
+
asPath: requestAsPath,
|
|
459
600
|
navigationIsReady,
|
|
460
601
|
locale: locale ?? currentDefaultLocale,
|
|
461
602
|
locales: i18nConfig?.locales,
|
|
@@ -473,15 +614,12 @@ function createSSRHandler(server, runner, routes, pagesDir, i18nConfig, fileMatc
|
|
|
473
614
|
hostname: req.headers.host?.split(":", 1)[0]
|
|
474
615
|
});
|
|
475
616
|
}
|
|
476
|
-
let RegenApp = null;
|
|
477
|
-
const appPath = path.join(pagesDir, "_app");
|
|
478
|
-
if (findFileWithExtensions(appPath, matcher)) try {
|
|
479
|
-
RegenApp = (await runner.import(appPath)).default ?? null;
|
|
480
|
-
} catch {}
|
|
481
617
|
let el = RegenApp ? React.createElement(RegenApp, {
|
|
618
|
+
...freshRenderProps,
|
|
482
619
|
Component: pageModule.default,
|
|
483
|
-
pageProps:
|
|
484
|
-
|
|
620
|
+
pageProps: freshRenderProps.pageProps,
|
|
621
|
+
router: routerShim.default
|
|
622
|
+
}) : React.createElement(pageModule.default, freshPageProps);
|
|
485
623
|
if (routerShim.wrapWithRouterContext) el = routerShim.wrapWithRouterContext(el);
|
|
486
624
|
const freshBody = await renderIsrPassToStringAsync(withScriptNonce(el, scriptNonce));
|
|
487
625
|
const viteRoot = server.config?.root;
|
|
@@ -497,7 +635,7 @@ function createSSRHandler(server, runner, routes, pagesDir, i18nConfig, fileMatc
|
|
|
497
635
|
}
|
|
498
636
|
};
|
|
499
637
|
await isrSet(cacheKey, buildPagesCacheValue(`<!DOCTYPE html><html><head></head><body><div id="__next">${freshBody}</div>${`<script>window.__NEXT_DATA__ = ${safeJsonStringify({
|
|
500
|
-
props:
|
|
638
|
+
props: freshRenderProps,
|
|
501
639
|
page: patternToNextFormat(route.pattern),
|
|
502
640
|
query: params,
|
|
503
641
|
buildId: process.env.__VINEXT_BUILD_ID,
|
|
@@ -507,7 +645,7 @@ function createSSRHandler(server, runner, routes, pagesDir, i18nConfig, fileMatc
|
|
|
507
645
|
defaultLocale: currentDefaultLocale,
|
|
508
646
|
domainLocales,
|
|
509
647
|
...freshPagesNextData
|
|
510
|
-
})}${i18nConfig ? `;window.__VINEXT_LOCALE__=${safeJsonStringify(locale ?? currentDefaultLocale)};window.__VINEXT_LOCALES__=${safeJsonStringify(i18nConfig.locales)};window.__VINEXT_DEFAULT_LOCALE__=${safeJsonStringify(currentDefaultLocale)}` : ""}<\/script>`}\n ${cachedHtml.match(/<script type="module">[\s\S]*?<\/script>/)?.[0] ?? ""}</body></html>`,
|
|
648
|
+
})}${i18nConfig ? `;window.__VINEXT_LOCALE__=${safeJsonStringify(locale ?? currentDefaultLocale)};window.__VINEXT_LOCALES__=${safeJsonStringify(i18nConfig.locales)};window.__VINEXT_DEFAULT_LOCALE__=${safeJsonStringify(currentDefaultLocale)}` : ""}<\/script>`}\n ${cachedHtml.match(/<script type="module">[\s\S]*?<\/script>/)?.[0] ?? ""}</body></html>`, freshRenderProps), revalidate);
|
|
511
649
|
setRevalidateDuration(cacheKey, revalidate);
|
|
512
650
|
}
|
|
513
651
|
}
|
|
@@ -539,10 +677,25 @@ function createSSRHandler(server, runner, routes, pagesDir, i18nConfig, fileMatc
|
|
|
539
677
|
defaultLocale: currentDefaultLocale,
|
|
540
678
|
revalidateReason: isOnDemandRevalidate ? "on-demand" : "stale"
|
|
541
679
|
};
|
|
542
|
-
const
|
|
543
|
-
if (
|
|
680
|
+
const generatedPageData = !isOnDemandRevalidate && cached?.isStale === false && cached?.value.value?.kind === "PAGES" && cached.value.value.generatedFromDataRequest && isUnknownRecord(cached.value.value.pageData) ? cached.value.value.pageData : null;
|
|
681
|
+
if (!generatedPageData && await loadAppInitialProps()) return;
|
|
682
|
+
const result = generatedPageData ? null : await pageModule.getStaticProps(context);
|
|
683
|
+
if (generatedPageData) {
|
|
684
|
+
renderProps = generatedPageData;
|
|
685
|
+
pageProps = isUnknownRecord(renderProps.pageProps) ? renderProps.pageProps : {};
|
|
686
|
+
}
|
|
687
|
+
if (result && "props" in result) {
|
|
688
|
+
pageProps = {
|
|
689
|
+
...pageProps,
|
|
690
|
+
...await Promise.resolve(result.props)
|
|
691
|
+
};
|
|
692
|
+
renderProps = {
|
|
693
|
+
...renderProps,
|
|
694
|
+
pageProps
|
|
695
|
+
};
|
|
696
|
+
}
|
|
544
697
|
if (result && "redirect" in result) {
|
|
545
|
-
writeGsspRedirect(res, result.redirect, isDataReq);
|
|
698
|
+
writeGsspRedirect(res, result.redirect, isDataReq, renderProps);
|
|
546
699
|
return;
|
|
547
700
|
}
|
|
548
701
|
if (result && "notFound" in result && result.notFound) {
|
|
@@ -559,25 +712,48 @@ function createSSRHandler(server, runner, routes, pagesDir, i18nConfig, fileMatc
|
|
|
559
712
|
}
|
|
560
713
|
if (result && "props" in result) isSerializableProps(patternToNextFormat(route.pattern), "getStaticProps", pageProps);
|
|
561
714
|
if (typeof result?.revalidate === "number" && result.revalidate > 0) isrRevalidateSeconds = result.revalidate;
|
|
715
|
+
else if (cached?.value.value?.kind === "PAGES" && cached.value.value.generatedFromDataRequest) isrRevalidateSeconds = cached.value.cacheControl?.revalidate ?? 31536e3;
|
|
562
716
|
}
|
|
563
|
-
if (typeof pageModule.getServerSideProps !== "function" && typeof pageModule.getStaticProps !== "function") {
|
|
717
|
+
if (typeof pageModule.getServerSideProps !== "function" && typeof pageModule.getStaticProps !== "function" && hasAppGetInitialProps) {
|
|
718
|
+
if (await loadAppInitialProps()) return;
|
|
719
|
+
}
|
|
720
|
+
if (typeof pageModule.getServerSideProps !== "function" && typeof pageModule.getStaticProps !== "function" && !hasAppGetInitialProps) {
|
|
564
721
|
const initialProps = await loadPagesGetInitialProps(PageComponent, {
|
|
565
722
|
req,
|
|
566
723
|
res,
|
|
567
724
|
pathname: patternToNextFormat(route.pattern),
|
|
568
725
|
query,
|
|
569
|
-
asPath:
|
|
726
|
+
asPath: requestAsPath,
|
|
570
727
|
locale: locale ?? currentDefaultLocale,
|
|
571
728
|
locales: i18nConfig?.locales,
|
|
572
729
|
defaultLocale: currentDefaultLocale
|
|
573
730
|
});
|
|
574
731
|
if (res.headersSent || res.writableEnded) return;
|
|
575
|
-
if (initialProps)
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
732
|
+
if (initialProps) {
|
|
733
|
+
pageProps = {
|
|
734
|
+
...pageProps,
|
|
735
|
+
...initialProps
|
|
736
|
+
};
|
|
737
|
+
renderProps = {
|
|
738
|
+
...renderProps,
|
|
739
|
+
pageProps
|
|
740
|
+
};
|
|
741
|
+
}
|
|
579
742
|
}
|
|
580
743
|
if (isDataReq) {
|
|
744
|
+
if (shouldPersistFallbackData) {
|
|
745
|
+
const cacheKey = pagesIsrCacheKey(url.split("?")[0]);
|
|
746
|
+
const revalidateSeconds = isrRevalidateSeconds ?? 31536e3;
|
|
747
|
+
await isrSet(cacheKey, {
|
|
748
|
+
kind: "PAGES",
|
|
749
|
+
html: "",
|
|
750
|
+
pageData: renderProps,
|
|
751
|
+
generatedFromDataRequest: true,
|
|
752
|
+
headers: void 0,
|
|
753
|
+
status: void 0
|
|
754
|
+
}, revalidateSeconds);
|
|
755
|
+
setRevalidateDuration(cacheKey, revalidateSeconds);
|
|
756
|
+
}
|
|
581
757
|
const dataHeaders = { "Content-Type": "application/json" };
|
|
582
758
|
if (gsspExtraHeaders) for (const [k, v] of Object.entries(gsspExtraHeaders)) dataHeaders[k] = v;
|
|
583
759
|
const dataRoutePattern = patternToNextFormat(route.pattern);
|
|
@@ -586,7 +762,7 @@ function createSSRHandler(server, runner, routes, pagesDir, i18nConfig, fileMatc
|
|
|
586
762
|
if (deploymentId) dataHeaders[NEXTJS_DEPLOYMENT_ID_HEADER] = deploymentId;
|
|
587
763
|
}
|
|
588
764
|
res.writeHead(statusCode ?? 200, dataHeaders);
|
|
589
|
-
res.end(JSON.stringify(
|
|
765
|
+
res.end(JSON.stringify(renderProps));
|
|
590
766
|
_renderEnd = now();
|
|
591
767
|
return;
|
|
592
768
|
}
|
|
@@ -594,8 +770,10 @@ function createSSRHandler(server, runner, routes, pagesDir, i18nConfig, fileMatc
|
|
|
594
770
|
let element;
|
|
595
771
|
const wrapWithRouterContext = routerShim.wrapWithRouterContext;
|
|
596
772
|
if (AppComponent) element = createElement(AppComponent, {
|
|
773
|
+
...renderProps,
|
|
597
774
|
Component: PageComponent,
|
|
598
|
-
pageProps
|
|
775
|
+
pageProps: renderProps.pageProps,
|
|
776
|
+
router: routerShim.default
|
|
599
777
|
});
|
|
600
778
|
else element = createElement(PageComponent, pageProps);
|
|
601
779
|
if (wrapWithRouterContext) element = wrapWithRouterContext(element);
|
|
@@ -647,11 +825,14 @@ function createSSRHandler(server, runner, routes, pagesDir, i18nConfig, fileMatc
|
|
|
647
825
|
import "vinext/instrumentation-client";
|
|
648
826
|
import React from "react";
|
|
649
827
|
import { hydrateRoot } from "react-dom/client";
|
|
650
|
-
import {
|
|
651
|
-
import { wrapWithRouterContext } from "next/router";
|
|
828
|
+
import Router, { wrapWithRouterContext } from "next/router";
|
|
652
829
|
|
|
653
830
|
const nextData = window.__NEXT_DATA__;
|
|
654
|
-
const
|
|
831
|
+
const props = nextData.props && typeof nextData.props === "object" ? nextData.props : {};
|
|
832
|
+
const rawPageProps = props.pageProps;
|
|
833
|
+
const pageProps = rawPageProps && typeof rawPageProps === "object" ? rawPageProps : {};
|
|
834
|
+
window.__VINEXT_PAGE_LOADERS__ = { [nextData.page]: () => import("${pageModuleUrl}") };
|
|
835
|
+
window.__VINEXT_APP_LOADER__ = ${appModuleUrl ? `() => import("${appModuleUrl}")` : "undefined"};
|
|
655
836
|
|
|
656
837
|
async function hydrate() {
|
|
657
838
|
let hydrateRootOptions;
|
|
@@ -673,24 +854,34 @@ async function hydrate() {
|
|
|
673
854
|
const appModule = await import("${appModuleUrl}");
|
|
674
855
|
const AppComponent = appModule.default;
|
|
675
856
|
window.__VINEXT_APP__ = AppComponent;
|
|
676
|
-
element = React.createElement(AppComponent, {
|
|
857
|
+
element = React.createElement(AppComponent, {
|
|
858
|
+
...props,
|
|
859
|
+
Component: PageComponent,
|
|
860
|
+
pageProps: rawPageProps,
|
|
861
|
+
router: Router,
|
|
862
|
+
});
|
|
677
863
|
` : `
|
|
678
864
|
element = React.createElement(PageComponent, pageProps);
|
|
679
865
|
`}
|
|
680
|
-
|
|
866
|
+
let resolveHydrationCommit;
|
|
867
|
+
const hydrationCommitted = new Promise((resolve) => { resolveHydrationCommit = resolve; });
|
|
868
|
+
element = wrapWithRouterContext(element, resolveHydrationCommit);
|
|
681
869
|
const root = hydrateRoot(document.getElementById("__next"), element, hydrateRootOptions);
|
|
682
870
|
window.__VINEXT_ROOT__ = root;
|
|
683
|
-
|
|
871
|
+
await hydrationCommitted;
|
|
684
872
|
const hydratedAt = performance.now();
|
|
685
873
|
window.__VINEXT_HYDRATED_AT = hydratedAt;
|
|
686
874
|
window.__NEXT_HYDRATED = true;
|
|
687
875
|
window.__NEXT_HYDRATED_AT = hydratedAt;
|
|
688
876
|
window.__NEXT_HYDRATED_CB?.();
|
|
877
|
+
if (nextData.isFallback) {
|
|
878
|
+
await Router.replace(window.location.pathname + window.location.search + window.location.hash, undefined, { _h: 1, scroll: false });
|
|
879
|
+
}
|
|
689
880
|
}
|
|
690
881
|
hydrate();
|
|
691
882
|
<\/script>`;
|
|
692
883
|
const nextDataScript = createInlineScriptTag(`window.__NEXT_DATA__ = ${safeJsonStringify({
|
|
693
|
-
props:
|
|
884
|
+
props: renderProps,
|
|
694
885
|
page: patternToNextFormat(route.pattern),
|
|
695
886
|
query: params,
|
|
696
887
|
buildId: process.env.__VINEXT_BUILD_ID,
|
|
@@ -726,7 +917,7 @@ hydrate();
|
|
|
726
917
|
documentContext: {
|
|
727
918
|
pathname: patternToNextFormat(route.pattern),
|
|
728
919
|
query,
|
|
729
|
-
asPath:
|
|
920
|
+
asPath: requestAsPath
|
|
730
921
|
},
|
|
731
922
|
enhancePageElement: (renderPageOpts) => {
|
|
732
923
|
let FinalApp = AppComponent;
|
|
@@ -735,6 +926,7 @@ hydrate();
|
|
|
735
926
|
if (renderPageOpts && typeof renderPageOpts.enhanceComponent === "function") FinalComp = renderPageOpts.enhanceComponent(FinalComp);
|
|
736
927
|
let enhancedElement;
|
|
737
928
|
if (FinalApp) enhancedElement = createElement(FinalApp, {
|
|
929
|
+
...renderProps,
|
|
738
930
|
Component: FinalComp,
|
|
739
931
|
pageProps
|
|
740
932
|
});
|
|
@@ -753,6 +945,7 @@ hydrate();
|
|
|
753
945
|
if (typeof routerShim.setSSRContext === "function") routerShim.setSSRContext(null);
|
|
754
946
|
if (!scriptNonce && isrRevalidateSeconds !== null && isrRevalidateSeconds > 0) {
|
|
755
947
|
let isrElement = AppComponent ? createElement(AppComponent, {
|
|
948
|
+
...renderProps,
|
|
756
949
|
Component: pageModule.default,
|
|
757
950
|
pageProps
|
|
758
951
|
}) : createElement(pageModule.default, pageProps);
|
|
@@ -767,7 +960,7 @@ hydrate();
|
|
|
767
960
|
reportRequestError(e instanceof Error ? e : new Error(String(e)), {
|
|
768
961
|
path: url,
|
|
769
962
|
method: req.method ?? "GET",
|
|
770
|
-
headers: Object.fromEntries(Object.entries(req.headers).map(([k, v]) => [k, Array.isArray(v) ? v.join(", ") : String(v ?? "")]))
|
|
963
|
+
headers: Object.fromEntries(Object.entries(req.headers).filter(([k]) => !k.startsWith(":")).map(([k, v]) => [k, Array.isArray(v) ? v.join(", ") : String(v ?? "")]))
|
|
771
964
|
}, {
|
|
772
965
|
routerKind: "Pages Router",
|
|
773
966
|
routePath: route.pattern,
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
//#region src/server/hybrid-route-priority.d.ts
|
|
2
|
+
type HybridRoutePriorityRoute = {
|
|
3
|
+
isDynamic: boolean;
|
|
4
|
+
pattern: string;
|
|
5
|
+
sourcePath?: string | null;
|
|
6
|
+
};
|
|
7
|
+
declare function validateHybridRouteConflicts(pagesRoutes: readonly HybridRoutePriorityRoute[], appRoutes: readonly HybridRoutePriorityRoute[]): void;
|
|
8
|
+
/**
|
|
9
|
+
* Return whether a matched Pages Router route should own the request instead
|
|
10
|
+
* of a matched App Router route.
|
|
11
|
+
*
|
|
12
|
+
* Next.js registers Pages providers before App providers, then sorts all
|
|
13
|
+
* dynamic route pathnames together in DefaultRouteMatcherManager. Vinext keeps
|
|
14
|
+
* separate route tries for each router, so the hybrid boundary needs to apply
|
|
15
|
+
* that same cross-router ordering after both routers have produced their best
|
|
16
|
+
* local match. The decision itself lives in
|
|
17
|
+
* `routing/utils.ts#compareHybridRoutePatterns` so the server and client
|
|
18
|
+
* always reach the same answer.
|
|
19
|
+
*/
|
|
20
|
+
declare function pagesRouteHasPriorityOverAppRoute(pagesRoute: HybridRoutePriorityRoute, appRoute: HybridRoutePriorityRoute | null): boolean;
|
|
21
|
+
//#endregion
|
|
22
|
+
export { HybridRoutePriorityRoute, pagesRouteHasPriorityOverAppRoute, validateHybridRouteConflicts };
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { compareHybridRoutePatterns } from "../routing/utils.js";
|
|
2
|
+
import { validateRoutePatterns } from "../routing/route-validation.js";
|
|
3
|
+
//#region src/server/hybrid-route-priority.ts
|
|
4
|
+
function validateHybridRouteConflicts(pagesRoutes, appRoutes) {
|
|
5
|
+
const pagesByPattern = new Map(pagesRoutes.map((route) => [route.pattern, route]));
|
|
6
|
+
const conflicts = appRoutes.flatMap((appRoute) => {
|
|
7
|
+
const pagesRoute = pagesByPattern.get(appRoute.pattern);
|
|
8
|
+
return pagesRoute === void 0 ? [] : [[pagesRoute, appRoute]];
|
|
9
|
+
});
|
|
10
|
+
if (conflicts.length > 0) {
|
|
11
|
+
const message = `Conflicting app and page file${conflicts.length === 1 ? " was" : "s were"} found, please remove the conflicting files to continue:`;
|
|
12
|
+
throw new Error(`${message}\n${conflicts.map(([pagesRoute, appRoute]) => ` "${pagesRoute.sourcePath ?? pagesRoute.pattern}" - "${appRoute.sourcePath ?? appRoute.pattern}"`).join("\n")}`);
|
|
13
|
+
}
|
|
14
|
+
validateRoutePatterns([...pagesRoutes.map((route) => route.pattern), ...appRoutes.map((route) => route.pattern)]);
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Return whether a matched Pages Router route should own the request instead
|
|
18
|
+
* of a matched App Router route.
|
|
19
|
+
*
|
|
20
|
+
* Next.js registers Pages providers before App providers, then sorts all
|
|
21
|
+
* dynamic route pathnames together in DefaultRouteMatcherManager. Vinext keeps
|
|
22
|
+
* separate route tries for each router, so the hybrid boundary needs to apply
|
|
23
|
+
* that same cross-router ordering after both routers have produced their best
|
|
24
|
+
* local match. The decision itself lives in
|
|
25
|
+
* `routing/utils.ts#compareHybridRoutePatterns` so the server and client
|
|
26
|
+
* always reach the same answer.
|
|
27
|
+
*/
|
|
28
|
+
function pagesRouteHasPriorityOverAppRoute(pagesRoute, appRoute) {
|
|
29
|
+
if (appRoute === null) return true;
|
|
30
|
+
return compareHybridRoutePatterns(pagesRoute.pattern, pagesRoute.isDynamic, appRoute.pattern, appRoute.isDynamic) === "pages";
|
|
31
|
+
}
|
|
32
|
+
//#endregion
|
|
33
|
+
export { pagesRouteHasPriorityOverAppRoute, validateHybridRouteConflicts };
|
|
@@ -33,7 +33,15 @@ declare function isImageOptimizationPath(pathname: string): boolean;
|
|
|
33
33
|
* Controls SVG handling and security headers for the image endpoint.
|
|
34
34
|
*/
|
|
35
35
|
type ImageConfig = {
|
|
36
|
-
/**
|
|
36
|
+
/** Allowed device widths. Defaults to Next.js device sizes. */deviceSizes?: number[]; /** Allowed fixed-image widths. Defaults to Next.js image sizes. */
|
|
37
|
+
imageSizes?: number[];
|
|
38
|
+
/**
|
|
39
|
+
* Allowed output qualities. When unset, any quality from 1-100 is permitted
|
|
40
|
+
* (matches Next.js: an unset `images.qualities` is not restricted to a single
|
|
41
|
+
* value). When set, only the listed qualities are accepted.
|
|
42
|
+
*/
|
|
43
|
+
qualities?: number[]; /** Allow SVG through the image optimization endpoint. Default: false. */
|
|
44
|
+
dangerouslyAllowSVG?: boolean;
|
|
37
45
|
/**
|
|
38
46
|
* Allow image optimization for hostnames that resolve to private IP addresses.
|
|
39
47
|
* Default: false.
|
|
@@ -54,18 +62,19 @@ type ImageConfig = {
|
|
|
54
62
|
*/
|
|
55
63
|
declare const DEFAULT_DEVICE_SIZES: number[];
|
|
56
64
|
declare const DEFAULT_IMAGE_SIZES: number[];
|
|
65
|
+
type ParseImageParamsOptions = {
|
|
66
|
+
isDev?: boolean;
|
|
67
|
+
};
|
|
68
|
+
declare function resolveDevImageRedirect(requestUrl: URL, allowedWidths?: number[], allowedQualities?: number[], options?: ParseImageParamsOptions): string | null;
|
|
57
69
|
/**
|
|
58
70
|
* Parse and validate image optimization query parameters.
|
|
59
71
|
* Returns null if the request is malformed.
|
|
60
72
|
*
|
|
61
|
-
*
|
|
62
|
-
*
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
* When `allowedWidths` is not provided, any width from 0 to ABSOLUTE_MAX_WIDTH
|
|
66
|
-
* is accepted (backwards-compatible fallback).
|
|
73
|
+
* Ported from Next.js:
|
|
74
|
+
* test/integration/image-optimizer/test/index.test.ts
|
|
75
|
+
* https://github.com/vercel/next.js/blob/canary/test/integration/image-optimizer/test/index.test.ts
|
|
67
76
|
*/
|
|
68
|
-
declare function parseImageParams(url: URL, allowedWidths?: number[]): {
|
|
77
|
+
declare function parseImageParams(url: URL, allowedWidths?: number[], allowedQualities?: number[], options?: ParseImageParamsOptions): {
|
|
69
78
|
imageUrl: string;
|
|
70
79
|
width: number;
|
|
71
80
|
quality: number;
|
|
@@ -113,4 +122,4 @@ type ImageHandlers = {
|
|
|
113
122
|
*/
|
|
114
123
|
declare function handleImageOptimization(request: Request, handlers: ImageHandlers, allowedWidths?: number[], imageConfig?: ImageConfig): Promise<Response>;
|
|
115
124
|
//#endregion
|
|
116
|
-
export { DEFAULT_DEVICE_SIZES, DEFAULT_IMAGE_SIZES, IMAGE_CACHE_CONTROL, IMAGE_CONTENT_SECURITY_POLICY, IMAGE_OPTIMIZATION_PATH, ImageConfig, ImageHandlers, VINEXT_IMAGE_OPTIMIZATION_PATH, handleImageOptimization, isImageOptimizationPath, isSafeImageContentType, negotiateImageFormat, parseImageParams };
|
|
125
|
+
export { DEFAULT_DEVICE_SIZES, DEFAULT_IMAGE_SIZES, IMAGE_CACHE_CONTROL, IMAGE_CONTENT_SECURITY_POLICY, IMAGE_OPTIMIZATION_PATH, ImageConfig, ImageHandlers, ParseImageParamsOptions, VINEXT_IMAGE_OPTIMIZATION_PATH, handleImageOptimization, isImageOptimizationPath, isSafeImageContentType, negotiateImageFormat, parseImageParams, resolveDevImageRedirect };
|