vinext 0.1.1 → 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.
Files changed (266) hide show
  1. package/README.md +2 -5
  2. package/dist/build/client-build-config.d.ts +7 -1
  3. package/dist/build/client-build-config.js +9 -1
  4. package/dist/build/prerender.d.ts +9 -1
  5. package/dist/build/prerender.js +41 -12
  6. package/dist/build/run-prerender.d.ts +10 -2
  7. package/dist/build/run-prerender.js +15 -1
  8. package/dist/check.js +4 -3
  9. package/dist/client/app-nav-failure-handler.d.ts +8 -0
  10. package/dist/client/app-nav-failure-handler.js +44 -0
  11. package/dist/client/navigation-runtime.d.ts +3 -2
  12. package/dist/client/vinext-next-data.d.ts +18 -1
  13. package/dist/client/window-next.d.ts +8 -5
  14. package/dist/client/window-next.js +12 -1
  15. package/dist/cloudflare/src/cache/cdn-adapter.runtime.js +6 -1
  16. package/dist/config/config-matchers.d.ts +11 -4
  17. package/dist/config/config-matchers.js +88 -16
  18. package/dist/config/next-config.d.ts +59 -4
  19. package/dist/config/next-config.js +149 -48
  20. package/dist/deploy.d.ts +30 -11
  21. package/dist/deploy.js +189 -101
  22. package/dist/entries/app-browser-entry.d.ts +9 -3
  23. package/dist/entries/app-browser-entry.js +21 -3
  24. package/dist/entries/app-rsc-entry.d.ts +2 -0
  25. package/dist/entries/app-rsc-entry.js +71 -6
  26. package/dist/entries/app-rsc-manifest.js +2 -0
  27. package/dist/entries/app-ssr-entry.js +1 -1
  28. package/dist/entries/pages-client-entry.js +54 -9
  29. package/dist/entries/pages-server-entry.js +48 -11
  30. package/dist/index.d.ts +0 -2
  31. package/dist/index.js +285 -139
  32. package/dist/plugins/dynamic-preload-metadata.d.ts +13 -0
  33. package/dist/plugins/dynamic-preload-metadata.js +415 -0
  34. package/dist/plugins/extensionless-dynamic-import.d.ts +6 -0
  35. package/dist/plugins/extensionless-dynamic-import.js +152 -0
  36. package/dist/plugins/og-assets.js +2 -2
  37. package/dist/plugins/optimize-imports.d.ts +10 -5
  38. package/dist/plugins/optimize-imports.js +27 -21
  39. package/dist/plugins/postcss.js +7 -7
  40. package/dist/plugins/sass.d.ts +53 -24
  41. package/dist/plugins/sass.js +249 -1
  42. package/dist/plugins/typeof-window.d.ts +14 -0
  43. package/dist/plugins/typeof-window.js +150 -0
  44. package/dist/plugins/wasm-module-import.d.ts +15 -0
  45. package/dist/plugins/wasm-module-import.js +50 -0
  46. package/dist/routing/app-route-graph.d.ts +25 -2
  47. package/dist/routing/app-route-graph.js +91 -22
  48. package/dist/routing/file-matcher.d.ts +10 -1
  49. package/dist/routing/file-matcher.js +23 -2
  50. package/dist/routing/pages-router.js +3 -3
  51. package/dist/routing/utils.d.ts +35 -6
  52. package/dist/routing/utils.js +59 -7
  53. package/dist/server/api-handler.d.ts +6 -1
  54. package/dist/server/api-handler.js +21 -15
  55. package/dist/server/app-browser-action-result.d.ts +19 -6
  56. package/dist/server/app-browser-action-result.js +19 -10
  57. package/dist/server/app-browser-entry.js +269 -297
  58. package/dist/server/app-browser-error.d.ts +10 -3
  59. package/dist/server/app-browser-error.js +47 -6
  60. package/dist/server/app-browser-history-controller.d.ts +104 -0
  61. package/dist/server/app-browser-history-controller.js +210 -0
  62. package/dist/server/app-browser-hydration.d.ts +2 -0
  63. package/dist/server/app-browser-hydration.js +1 -0
  64. package/dist/server/app-browser-navigation-controller.d.ts +7 -4
  65. package/dist/server/app-browser-navigation-controller.js +33 -9
  66. package/dist/server/app-browser-rsc-redirect.d.ts +11 -2
  67. package/dist/server/app-browser-rsc-redirect.js +30 -8
  68. package/dist/server/app-browser-server-action-navigation.d.ts +6 -0
  69. package/dist/server/app-browser-server-action-navigation.js +9 -0
  70. package/dist/server/app-browser-state.js +4 -7
  71. package/dist/server/app-browser-stream.js +86 -43
  72. package/dist/server/app-browser-visible-commit.js +1 -1
  73. package/dist/server/app-elements-wire.d.ts +6 -1
  74. package/dist/server/app-elements-wire.js +14 -4
  75. package/dist/server/app-elements.d.ts +2 -2
  76. package/dist/server/app-elements.js +2 -2
  77. package/dist/server/app-fallback-renderer.d.ts +3 -1
  78. package/dist/server/app-fallback-renderer.js +6 -2
  79. package/dist/server/app-middleware.js +1 -0
  80. package/dist/server/app-optimistic-routing.js +24 -3
  81. package/dist/server/app-page-boundary-render.d.ts +3 -1
  82. package/dist/server/app-page-boundary-render.js +31 -16
  83. package/dist/server/app-page-cache-render.d.ts +53 -0
  84. package/dist/server/app-page-cache-render.js +91 -0
  85. package/dist/server/app-page-cache.d.ts +16 -2
  86. package/dist/server/app-page-cache.js +71 -8
  87. package/dist/server/app-page-dispatch.d.ts +34 -0
  88. package/dist/server/app-page-dispatch.js +167 -97
  89. package/dist/server/app-page-element-builder.d.ts +23 -2
  90. package/dist/server/app-page-element-builder.js +42 -10
  91. package/dist/server/app-page-execution.d.ts +7 -2
  92. package/dist/server/app-page-execution.js +53 -18
  93. package/dist/server/app-page-probe.d.ts +1 -0
  94. package/dist/server/app-page-probe.js +4 -0
  95. package/dist/server/app-page-render-observation.d.ts +3 -1
  96. package/dist/server/app-page-render-observation.js +17 -1
  97. package/dist/server/app-page-render.d.ts +13 -2
  98. package/dist/server/app-page-render.js +48 -17
  99. package/dist/server/app-page-request.d.ts +3 -0
  100. package/dist/server/app-page-request.js +5 -3
  101. package/dist/server/app-page-response.js +1 -1
  102. package/dist/server/app-page-route-wiring.d.ts +5 -1
  103. package/dist/server/app-page-route-wiring.js +21 -11
  104. package/dist/server/app-page-stream.d.ts +16 -9
  105. package/dist/server/app-page-stream.js +12 -9
  106. package/dist/server/app-pages-bridge.d.ts +18 -0
  107. package/dist/server/app-pages-bridge.js +22 -5
  108. package/dist/server/app-ppr-fallback-shell-render.d.ts +17 -0
  109. package/dist/server/app-ppr-fallback-shell-render.js +26 -0
  110. package/dist/server/app-ppr-fallback-shell.d.ts +13 -1
  111. package/dist/server/app-ppr-fallback-shell.js +8 -1
  112. package/dist/server/app-route-handler-dispatch.js +9 -2
  113. package/dist/server/app-route-handler-policy.d.ts +1 -0
  114. package/dist/server/app-route-handler-response.js +11 -10
  115. package/dist/server/app-route-handler-runtime.js +12 -1
  116. package/dist/server/app-router-entry.js +5 -0
  117. package/dist/server/app-rsc-cache-busting.js +2 -0
  118. package/dist/server/app-rsc-handler.d.ts +25 -0
  119. package/dist/server/app-rsc-handler.js +153 -53
  120. package/dist/server/app-rsc-response-finalizer.js +1 -1
  121. package/dist/server/app-rsc-route-matching.d.ts +3 -0
  122. package/dist/server/app-rsc-route-matching.js +2 -0
  123. package/dist/server/app-segment-config.d.ts +9 -1
  124. package/dist/server/app-segment-config.js +12 -3
  125. package/dist/server/app-server-action-execution.d.ts +12 -0
  126. package/dist/server/app-server-action-execution.js +47 -15
  127. package/dist/server/app-ssr-entry.d.ts +2 -0
  128. package/dist/server/app-ssr-entry.js +81 -8
  129. package/dist/server/app-ssr-stream.js +9 -1
  130. package/dist/server/cache-control.js +4 -0
  131. package/dist/server/dev-lockfile.js +2 -1
  132. package/dist/server/dev-server.d.ts +2 -2
  133. package/dist/server/dev-server.js +287 -63
  134. package/dist/server/headers.d.ts +8 -1
  135. package/dist/server/headers.js +8 -1
  136. package/dist/server/hybrid-route-priority.d.ts +22 -0
  137. package/dist/server/hybrid-route-priority.js +33 -0
  138. package/dist/server/image-optimization.d.ts +18 -9
  139. package/dist/server/image-optimization.js +37 -23
  140. package/dist/server/implicit-tags.d.ts +2 -1
  141. package/dist/server/implicit-tags.js +4 -1
  142. package/dist/server/instrumentation-runtime.d.ts +6 -0
  143. package/dist/server/instrumentation-runtime.js +8 -0
  144. package/dist/server/isr-decision.d.ts +79 -0
  145. package/dist/server/isr-decision.js +70 -0
  146. package/dist/server/metadata-route-response.js +5 -3
  147. package/dist/server/middleware-runtime.d.ts +13 -0
  148. package/dist/server/middleware-runtime.js +11 -7
  149. package/dist/server/middleware.js +1 -0
  150. package/dist/server/navigation-planner.d.ts +186 -22
  151. package/dist/server/navigation-planner.js +302 -0
  152. package/dist/server/navigation-trace.d.ts +18 -1
  153. package/dist/server/navigation-trace.js +18 -1
  154. package/dist/server/normalize-path.d.ts +0 -8
  155. package/dist/server/normalize-path.js +3 -1
  156. package/dist/server/otel-tracer-extension.d.ts +45 -0
  157. package/dist/server/otel-tracer-extension.js +89 -0
  158. package/dist/server/pages-api-route.d.ts +20 -3
  159. package/dist/server/pages-api-route.js +19 -3
  160. package/dist/server/pages-asset-tags.d.ts +16 -4
  161. package/dist/server/pages-asset-tags.js +22 -12
  162. package/dist/server/pages-data-route.d.ts +8 -1
  163. package/dist/server/pages-data-route.js +16 -3
  164. package/dist/server/pages-get-initial-props.d.ts +54 -4
  165. package/dist/server/pages-get-initial-props.js +43 -1
  166. package/dist/server/pages-node-compat.d.ts +3 -11
  167. package/dist/server/pages-node-compat.js +175 -122
  168. package/dist/server/pages-page-data.d.ts +39 -2
  169. package/dist/server/pages-page-data.js +261 -46
  170. package/dist/server/pages-page-handler.d.ts +5 -2
  171. package/dist/server/pages-page-handler.js +78 -25
  172. package/dist/server/pages-page-response.d.ts +47 -2
  173. package/dist/server/pages-page-response.js +73 -9
  174. package/dist/server/pages-readiness.d.ts +1 -1
  175. package/dist/server/pages-request-pipeline.d.ts +16 -1
  176. package/dist/server/pages-request-pipeline.js +96 -38
  177. package/dist/server/pregenerated-concrete-paths.d.ts +1 -17
  178. package/dist/server/pregenerated-concrete-paths.js +2 -19
  179. package/dist/server/prerender-manifest.d.ts +33 -0
  180. package/dist/server/prerender-manifest.js +54 -0
  181. package/dist/server/prerender-route-params.d.ts +1 -2
  182. package/dist/server/prod-server.d.ts +39 -1
  183. package/dist/server/prod-server.js +107 -37
  184. package/dist/server/request-pipeline.d.ts +3 -15
  185. package/dist/server/request-pipeline.js +58 -47
  186. package/dist/server/rsc-stream-hints.d.ts +5 -1
  187. package/dist/server/rsc-stream-hints.js +6 -1
  188. package/dist/server/seed-cache.js +10 -18
  189. package/dist/shims/app-router-scroll-state.d.ts +3 -1
  190. package/dist/shims/app-router-scroll-state.js +14 -2
  191. package/dist/shims/app-router-scroll.d.ts +3 -0
  192. package/dist/shims/app-router-scroll.js +28 -18
  193. package/dist/shims/cache-runtime.js +12 -4
  194. package/dist/shims/cache.d.ts +1 -0
  195. package/dist/shims/cache.js +1 -1
  196. package/dist/shims/cdn-cache.d.ts +5 -5
  197. package/dist/shims/dynamic-preload-chunks.d.ts +8 -0
  198. package/dist/shims/dynamic-preload-chunks.js +79 -0
  199. package/dist/shims/dynamic.d.ts +4 -0
  200. package/dist/shims/dynamic.js +4 -2
  201. package/dist/shims/error-boundary.d.ts +6 -4
  202. package/dist/shims/error-boundary.js +7 -0
  203. package/dist/shims/error.js +38 -11
  204. package/dist/shims/error.react-server.d.ts +9 -0
  205. package/dist/shims/error.react-server.js +6 -0
  206. package/dist/shims/fetch-cache.d.ts +11 -1
  207. package/dist/shims/fetch-cache.js +55 -20
  208. package/dist/shims/hash-scroll.js +6 -1
  209. package/dist/shims/head.js +6 -1
  210. package/dist/shims/headers.d.ts +16 -2
  211. package/dist/shims/headers.js +66 -5
  212. package/dist/shims/image-config.js +7 -1
  213. package/dist/shims/internal/als-registry.js +28 -1
  214. package/dist/shims/internal/app-route-detection.d.ts +6 -3
  215. package/dist/shims/internal/app-route-detection.js +18 -23
  216. package/dist/shims/internal/app-router-context.d.ts +5 -0
  217. package/dist/shims/internal/hybrid-client-route-owner.d.ts +31 -0
  218. package/dist/shims/internal/hybrid-client-route-owner.js +143 -0
  219. package/dist/shims/internal/navigation-untracked.d.ts +35 -0
  220. package/dist/shims/internal/navigation-untracked.js +55 -0
  221. package/dist/shims/internal/pages-data-target.d.ts +7 -2
  222. package/dist/shims/internal/pages-data-target.js +17 -8
  223. package/dist/shims/internal/pages-router-accessor.d.ts +19 -0
  224. package/dist/shims/internal/pages-router-accessor.js +13 -0
  225. package/dist/shims/internal/router-context.d.ts +2 -1
  226. package/dist/shims/internal/router-context.js +3 -1
  227. package/dist/shims/link.js +12 -5
  228. package/dist/shims/metadata.d.ts +6 -2
  229. package/dist/shims/metadata.js +32 -14
  230. package/dist/shims/navigation.d.ts +14 -17
  231. package/dist/shims/navigation.js +93 -46
  232. package/dist/shims/ppr-fallback-shell.d.ts +5 -1
  233. package/dist/shims/ppr-fallback-shell.js +28 -7
  234. package/dist/shims/router.d.ts +13 -2
  235. package/dist/shims/router.js +434 -116
  236. package/dist/shims/script-nonce-context.d.ts +1 -1
  237. package/dist/shims/script-nonce-context.js +11 -3
  238. package/dist/shims/server.d.ts +33 -2
  239. package/dist/shims/server.js +75 -18
  240. package/dist/shims/slot.js +1 -1
  241. package/dist/shims/unified-request-context.js +2 -0
  242. package/dist/typegen.js +1 -0
  243. package/dist/utils/built-asset-url.d.ts +4 -0
  244. package/dist/utils/built-asset-url.js +11 -0
  245. package/dist/utils/client-build-manifest.js +15 -5
  246. package/dist/utils/client-runtime-metadata.d.ts +45 -0
  247. package/dist/utils/client-runtime-metadata.js +63 -0
  248. package/dist/utils/commonjs-loader.d.ts +16 -0
  249. package/dist/utils/commonjs-loader.js +100 -0
  250. package/dist/utils/deployment-id.d.ts +8 -0
  251. package/dist/utils/deployment-id.js +22 -0
  252. package/dist/utils/hash.d.ts +17 -1
  253. package/dist/utils/hash.js +36 -1
  254. package/dist/utils/html-limited-bots.d.ts +18 -1
  255. package/dist/utils/html-limited-bots.js +23 -1
  256. package/dist/utils/lazy-chunks.d.ts +27 -1
  257. package/dist/utils/lazy-chunks.js +65 -1
  258. package/dist/utils/manifest-paths.d.ts +20 -2
  259. package/dist/utils/manifest-paths.js +38 -3
  260. package/dist/utils/parse-cookie.d.ts +13 -0
  261. package/dist/utils/parse-cookie.js +52 -0
  262. package/dist/utils/path.d.ts +8 -1
  263. package/dist/utils/path.js +13 -1
  264. package/package.json +2 -2
  265. package/dist/shims/internal/parse-cookie-header.d.ts +0 -14
  266. package/dist/shims/internal/parse-cookie-header.js +0 -30
@@ -1,28 +1,93 @@
1
+ import { NEXTJS_DEPLOYMENT_ID_HEADER } from "./headers.js";
1
2
  import { normalizeStaticPathname } from "../routing/route-pattern.js";
2
3
  import { buildCacheStateHeaders } from "./cache-headers.js";
4
+ import { isUnknownRecord } from "../utils/record.js";
5
+ import { applyCdnResponseHeaders } from "./cache-control.js";
6
+ import { decideIsr } from "./isr-decision.js";
3
7
  import { buildPagesCacheValue } from "./isr-cache.js";
4
8
  import { isSerializableProps } from "./pages-serializable-props.js";
5
9
  import { hasPagesGetInitialProps, isResponseSent, loadPagesGetInitialProps } from "./pages-get-initial-props.js";
6
- import { applyCdnResponseHeaders, buildCachedRevalidateCacheControl } from "./cache-control.js";
7
- import { buildNextDataJsonResponse } from "./pages-data-route.js";
8
- import { buildPagesNextDataScript } from "./pages-page-response.js";
10
+ import { isBotUserAgent } from "../utils/html-limited-bots.js";
11
+ import { buildNextDataPropsJsonResponse } from "./pages-data-route.js";
12
+ import { buildPagesNextDataScript, etagMatches, generatePagesETag, isPagesStreamingBot, requestsNoCache } from "./pages-page-response.js";
9
13
  //#region src/server/pages-page-data.ts
10
- function buildPagesDataNotFoundResponse() {
14
+ function buildPagesDataNotFoundResponse(deploymentId) {
15
+ const headers = { "Content-Type": "application/json" };
16
+ if (deploymentId) headers[NEXTJS_DEPLOYMENT_ID_HEADER] = deploymentId;
11
17
  return new Response("{}", {
12
18
  status: 404,
13
- headers: { "Content-Type": "application/json" }
19
+ headers
14
20
  });
15
21
  }
16
22
  function buildPagesNotFoundResult(options) {
17
23
  if (options.isDataReq) return {
18
24
  kind: "response",
19
- response: buildPagesDataNotFoundResponse()
25
+ response: buildPagesDataNotFoundResponse(options.deploymentId)
20
26
  };
21
27
  return { kind: "notFound" };
22
28
  }
23
29
  function resolvePagesRedirectStatus(redirect) {
24
30
  return redirect.statusCode != null ? redirect.statusCode : redirect.permanent ? 308 : 307;
25
31
  }
32
+ function normalizePagesRenderProps(props) {
33
+ return {
34
+ ...props,
35
+ pageProps: props.pageProps
36
+ };
37
+ }
38
+ /**
39
+ * Load `_app.getInitialProps` and return the normalized render props and the
40
+ * extracted `pageProps`. This is shared between the foreground render path and
41
+ * the stale-while-revalidate background regeneration path so both produce the
42
+ * same full props envelope (app-level props plus the page's `pageProps`).
43
+ *
44
+ * `getSharedReqRes` lets callers share the same mock req/res with other
45
+ * data-fetching steps (e.g. `getServerSideProps`) when they run in the same
46
+ * request context.
47
+ */
48
+ async function loadPagesAppInitialRenderProps(options, getSharedReqRes) {
49
+ let pageProps = {};
50
+ let renderProps = { pageProps };
51
+ if (!hasPagesGetInitialProps(options.AppComponent)) return {
52
+ kind: "props",
53
+ pageProps,
54
+ renderProps
55
+ };
56
+ const { req, res, responsePromise } = getSharedReqRes();
57
+ const initialProps = await loadPagesGetInitialProps(options.AppComponent, {
58
+ AppTree: options.createAppTree ?? options.createPageElement,
59
+ Component: options.pageModule.default,
60
+ router: {
61
+ pathname: options.routePattern,
62
+ query: options.query,
63
+ asPath: options.asPath ?? options.routeUrl
64
+ },
65
+ ctx: {
66
+ req,
67
+ res,
68
+ err: options.err,
69
+ pathname: options.routePattern,
70
+ query: options.query,
71
+ asPath: options.asPath ?? options.routeUrl,
72
+ locale: options.i18n.locale,
73
+ locales: options.i18n.locales,
74
+ defaultLocale: options.i18n.defaultLocale
75
+ }
76
+ });
77
+ if (isResponseSent(res)) return {
78
+ kind: "response",
79
+ response: responsePromise
80
+ };
81
+ if (initialProps) {
82
+ renderProps = normalizePagesRenderProps(initialProps);
83
+ pageProps = isUnknownRecord(renderProps.pageProps) ? renderProps.pageProps : {};
84
+ }
85
+ return {
86
+ kind: "props",
87
+ pageProps,
88
+ renderProps
89
+ };
90
+ }
26
91
  /**
27
92
  * Build the response for a `getServerSideProps` / `getStaticProps`
28
93
  * `{ redirect }` result.
@@ -44,12 +109,20 @@ function resolvePagesRedirectStatus(redirect) {
44
109
  * redirects (search `__N_REDIRECT`), consumed in
45
110
  * `packages/next/src/shared/lib/router/router.ts` (`pageProps.__N_REDIRECT`).
46
111
  */
47
- function buildPagesRedirectResponse(redirect, options) {
112
+ function buildPagesRedirectResponse(redirect, options, props = { pageProps: {} }) {
48
113
  const destination = options.sanitizeDestination(redirect.destination);
49
- if (options.isDataReq) return buildNextDataJsonResponse({
50
- __N_REDIRECT: destination,
51
- __N_REDIRECT_STATUS: resolvePagesRedirectStatus(redirect)
52
- }, options.safeJsonStringify);
114
+ if (options.isDataReq) {
115
+ const init = { headers: {} };
116
+ if (options.deploymentId) init.headers[NEXTJS_DEPLOYMENT_ID_HEADER] = options.deploymentId;
117
+ return buildNextDataPropsJsonResponse({
118
+ ...props,
119
+ pageProps: {
120
+ ...isUnknownRecord(props.pageProps) ? props.pageProps : {},
121
+ __N_REDIRECT: destination,
122
+ __N_REDIRECT_STATUS: resolvePagesRedirectStatus(redirect)
123
+ }
124
+ }, options.safeJsonStringify, init);
125
+ }
53
126
  return new Response(null, {
54
127
  status: resolvePagesRedirectStatus(redirect),
55
128
  headers: { Location: destination }
@@ -81,19 +154,47 @@ function matchesPagesStaticPath(pathEntry, params, routeUrl) {
81
154
  });
82
155
  }
83
156
  function buildPagesCacheResponse(html, cacheState, fontLinkHeader, revalidateSeconds, expireSeconds, cacheControl, status) {
84
- const effectiveRevalidateSeconds = cacheControl?.revalidate ?? revalidateSeconds ?? 60;
85
- const effectiveExpireSeconds = cacheControl === void 0 ? void 0 : cacheControl.expire ?? expireSeconds;
157
+ const { cacheControl: cacheControlHeader } = decideIsr({
158
+ cacheState,
159
+ kind: "pages",
160
+ revalidateSeconds: revalidateSeconds ?? 60,
161
+ expireSeconds,
162
+ cacheControlMeta: cacheControl
163
+ });
86
164
  const headers = new Headers({
87
165
  "Content-Type": "text/html",
88
166
  ...buildCacheStateHeaders(cacheState)
89
167
  });
90
- applyCdnResponseHeaders(headers, { cacheControl: buildCachedRevalidateCacheControl(cacheState, effectiveRevalidateSeconds, effectiveExpireSeconds) });
168
+ applyCdnResponseHeaders(headers, { cacheControl: cacheControlHeader });
91
169
  if (fontLinkHeader) headers.set("Link", fontLinkHeader);
92
170
  return new Response(html, {
93
171
  status: status ?? 200,
94
172
  headers
95
173
  });
96
174
  }
175
+ /**
176
+ * For bot / crawler UAs, attach an ETag to a cached ISR response (HIT or
177
+ * STALE) so it is consistent with the fresh-MISS path, then check for a
178
+ * matching `If-None-Match`. When the check passes — and the request did NOT
179
+ * carry `Cache-Control: no-cache` — returns a 304 response; otherwise returns
180
+ * `null` so the caller can return the full response.
181
+ *
182
+ * Extracted to avoid duplicating the same three-line block across the HIT and
183
+ * STALE branches.
184
+ */
185
+ function applyBotETagAndCheck(cachedResponse, html, options) {
186
+ if (!options.userAgent || !isPagesStreamingBot(options.userAgent)) return null;
187
+ const etag = generatePagesETag(html);
188
+ cachedResponse.headers.set("ETag", etag);
189
+ if (!requestsNoCache(options.requestCacheControl) && options.ifNoneMatch && etagMatches(etag, options.ifNoneMatch)) return {
190
+ kind: "response",
191
+ response: new Response(null, {
192
+ status: 304,
193
+ headers: cachedResponse.headers
194
+ })
195
+ };
196
+ return null;
197
+ }
97
198
  function rewritePagesCachedHtml(cachedHtml, freshBody, nextDataScript) {
98
199
  const bodyStart = cachedHtml.indexOf("<div id=\"__next\">");
99
200
  const contentStart = bodyStart >= 0 ? bodyStart + 17 : -1;
@@ -109,11 +210,13 @@ function rewritePagesCachedHtml(cachedHtml, freshBody, nextDataScript) {
109
210
  return "<!DOCTYPE html>\n<html>\n<head>\n</head>\n<body>\n <div id=\"__next\">" + freshBody + "</div>\n " + nextDataScript + "\n</body>\n</html>";
110
211
  }
111
212
  async function renderPagesIsrHtml(options) {
112
- const freshBody = await options.renderIsrPassToStringAsync(options.createPageElement(options.pageProps));
213
+ const renderProps = options.props ?? { pageProps: options.pageProps };
214
+ const freshBody = await options.renderIsrPassToStringAsync(options.createPageElement(renderProps));
113
215
  const nextDataScript = buildPagesNextDataScript({
114
216
  buildId: options.buildId,
115
217
  i18n: options.i18n,
116
218
  pageProps: options.pageProps,
219
+ props: renderProps,
117
220
  params: options.params,
118
221
  routePattern: options.routePattern,
119
222
  safeJsonStringify: options.safeJsonStringify,
@@ -125,6 +228,7 @@ async function renderPagesIsrHtml(options) {
125
228
  async function resolvePagesPageData(options) {
126
229
  const userFacingParams = options.route.isDynamic ? options.params : null;
127
230
  let isFallback = false;
231
+ let shouldPersistFallbackData = false;
128
232
  if (typeof options.pageModule.getStaticPaths === "function" && options.route.isDynamic) {
129
233
  const pathsResult = await options.pageModule.getStaticPaths({
130
234
  locales: options.i18n.locales ?? [],
@@ -133,25 +237,62 @@ async function resolvePagesPageData(options) {
133
237
  const fallback = pathsResult?.fallback ?? false;
134
238
  const isValidPath = (pathsResult?.paths ?? []).some((pathEntry) => matchesPagesStaticPath(pathEntry, options.params, options.routeUrl));
135
239
  if (fallback === false && !isValidPath) return buildPagesNotFoundResult(options);
136
- if (fallback === true && !isValidPath && !options.isDataReq) isFallback = true;
240
+ const isBotRequest = !!options.userAgent && isBotUserAgent(options.userAgent, options.htmlLimitedBots);
241
+ if (fallback === true && !isValidPath && !options.isDataReq && !isBotRequest) isFallback = true;
242
+ shouldPersistFallbackData = fallback === true && !isValidPath && options.isDataReq === true;
137
243
  }
138
244
  let pageProps = {};
139
245
  let gsspRes = null;
140
- if (isFallback) return {
141
- kind: "render",
142
- gsspRes: null,
143
- isrRevalidateSeconds: null,
144
- pageProps,
145
- isFallback: true
146
- };
246
+ let sharedReqRes = null;
247
+ function getSharedReqRes() {
248
+ sharedReqRes ??= options.createGsspReqRes();
249
+ return sharedReqRes;
250
+ }
251
+ let renderProps = { pageProps };
252
+ async function loadForegroundAppInitialRenderProps() {
253
+ const result = await loadPagesAppInitialRenderProps(options, getSharedReqRes);
254
+ if (result.kind === "response") return {
255
+ kind: "response",
256
+ response: await result.response
257
+ };
258
+ renderProps = result.renderProps;
259
+ pageProps = result.pageProps;
260
+ return null;
261
+ }
262
+ if (isFallback) {
263
+ const pathname = options.routeUrl.split("?")[0];
264
+ if ((await options.isrGet(options.isrCacheKey("pages", pathname)))?.value.value?.kind !== "PAGES") {
265
+ const appShortCircuit = await loadForegroundAppInitialRenderProps();
266
+ if (appShortCircuit) return appShortCircuit;
267
+ pageProps = {};
268
+ renderProps = {
269
+ ...renderProps,
270
+ pageProps
271
+ };
272
+ return {
273
+ kind: "render",
274
+ gsspRes: null,
275
+ isrRevalidateSeconds: null,
276
+ pageProps,
277
+ props: renderProps,
278
+ isFallback: true
279
+ };
280
+ }
281
+ }
147
282
  if (typeof options.pageModule.getServerSideProps === "function") {
148
- const { req, res, responsePromise } = options.createGsspReqRes();
283
+ const shortCircuit = await loadForegroundAppInitialRenderProps();
284
+ if (shortCircuit) return shortCircuit;
285
+ renderProps = {
286
+ ...renderProps,
287
+ __N_SSP: true
288
+ };
289
+ const { req, res, responsePromise } = getSharedReqRes();
149
290
  const result = await options.pageModule.getServerSideProps({
150
291
  params: userFacingParams,
151
292
  req,
152
293
  res,
153
294
  query: options.query,
154
- resolvedUrl: options.routeUrl,
295
+ resolvedUrl: options.resolvedUrl ?? options.routeUrl,
155
296
  locale: options.i18n.locale,
156
297
  locales: options.i18n.locales,
157
298
  defaultLocale: options.i18n.defaultLocale
@@ -160,10 +301,19 @@ async function resolvePagesPageData(options) {
160
301
  kind: "response",
161
302
  response: await responsePromise
162
303
  };
163
- if (result?.props) pageProps = await Promise.resolve(result.props);
304
+ if (result?.props) {
305
+ pageProps = {
306
+ ...pageProps,
307
+ ...await Promise.resolve(result.props)
308
+ };
309
+ renderProps = {
310
+ ...renderProps,
311
+ pageProps
312
+ };
313
+ }
164
314
  if (result?.redirect) return {
165
315
  kind: "response",
166
- response: buildPagesRedirectResponse(result.redirect, options)
316
+ response: buildPagesRedirectResponse(result.redirect, options, renderProps)
167
317
  };
168
318
  if (result?.notFound) return buildPagesNotFoundResult(options);
169
319
  if (result?.props !== void 0) isSerializableProps(options.routePattern, "getServerSideProps", pageProps);
@@ -175,13 +325,23 @@ async function resolvePagesPageData(options) {
175
325
  const cacheKey = options.isrCacheKey("pages", pathname);
176
326
  const cached = await options.isrGet(cacheKey);
177
327
  const cachedValue = cached?.value.value;
178
- if (!options.isOnDemandRevalidate && cachedValue?.kind === "PAGES" && cached && !cached.isStale && !options.scriptNonce && !options.isDataReq) return {
179
- kind: "response",
180
- response: buildPagesCacheResponse(cachedValue.html, "HIT", options.fontLinkHeader, void 0, options.expireSeconds, cached.value.cacheControl, cachedValue.status)
181
- };
182
- if (!options.isOnDemandRevalidate && cachedValue?.kind === "PAGES" && cached && cached.isStale && !options.scriptNonce && !options.isDataReq) {
328
+ if (!options.isOnDemandRevalidate && cached?.isStale === false && cachedValue?.kind === "PAGES" && !cachedValue.generatedFromDataRequest && cached && !cached.isStale && !options.scriptNonce && !options.isDataReq) {
329
+ const hitResponse = buildPagesCacheResponse(cachedValue.html, "HIT", options.fontLinkHeader, void 0, options.expireSeconds, cached.value.cacheControl, cachedValue.status);
330
+ const hitBotResult = applyBotETagAndCheck(hitResponse, cachedValue.html, options);
331
+ if (hitBotResult) return hitBotResult;
332
+ return {
333
+ kind: "response",
334
+ response: hitResponse
335
+ };
336
+ }
337
+ if (!options.isOnDemandRevalidate && cachedValue?.kind === "PAGES" && !cachedValue.generatedFromDataRequest && cached && cached.isStale && !options.scriptNonce && !options.isDataReq) {
183
338
  options.triggerBackgroundRegeneration(cacheKey, async function() {
184
339
  return options.runInFreshUnifiedContext(async () => {
340
+ options.applyRequestContexts();
341
+ const freshAppResult = await loadPagesAppInitialRenderProps(options, () => options.createGsspReqRes());
342
+ if (freshAppResult.kind === "response") return;
343
+ let freshPageProps = freshAppResult.pageProps;
344
+ let freshRenderProps = freshAppResult.renderProps;
185
345
  const freshResult = await options.pageModule.getStaticProps?.({
186
346
  params: userFacingParams,
187
347
  locale: options.i18n.locale,
@@ -189,14 +349,25 @@ async function resolvePagesPageData(options) {
189
349
  defaultLocale: options.i18n.defaultLocale,
190
350
  revalidateReason: "stale"
191
351
  });
192
- if (freshResult?.props && typeof freshResult.revalidate === "number" && freshResult.revalidate > 0) {
193
- options.applyRequestContexts();
352
+ if (freshResult?.props) {
353
+ freshPageProps = {
354
+ ...freshPageProps,
355
+ ...freshResult.props
356
+ };
357
+ freshRenderProps = {
358
+ ...freshRenderProps,
359
+ pageProps: freshPageProps
360
+ };
361
+ }
362
+ const freshRevalidateSeconds = typeof freshResult?.revalidate === "number" && freshResult.revalidate > 0 ? freshResult.revalidate : cached.value.cacheControl?.revalidate;
363
+ if (freshResult?.props && freshRevalidateSeconds && freshRevalidateSeconds > 0) {
194
364
  const freshHtml = await renderPagesIsrHtml({
195
365
  buildId: options.buildId,
196
366
  cachedHtml: cachedValue.html,
197
367
  createPageElement: options.createPageElement,
198
368
  i18n: options.i18n,
199
- pageProps: freshResult.props,
369
+ pageProps: freshPageProps,
370
+ props: freshRenderProps,
200
371
  params: options.params,
201
372
  renderIsrPassToStringAsync: options.renderIsrPassToStringAsync,
202
373
  routePattern: options.routePattern,
@@ -204,7 +375,7 @@ async function resolvePagesPageData(options) {
204
375
  nextData: options.nextData,
205
376
  vinext: options.vinext
206
377
  });
207
- await options.isrSet(cacheKey, buildPagesCacheValue(freshHtml, freshResult.props, options.statusCode), freshResult.revalidate, void 0, options.expireSeconds);
378
+ await options.isrSet(cacheKey, buildPagesCacheValue(freshHtml, freshRenderProps, options.statusCode), freshRevalidateSeconds, void 0, options.expireSeconds);
208
379
  }
209
380
  });
210
381
  }, {
@@ -212,29 +383,66 @@ async function resolvePagesPageData(options) {
212
383
  routePath: options.routePattern,
213
384
  routeType: "render"
214
385
  });
386
+ const staleResponse = buildPagesCacheResponse(cachedValue.html, "STALE", options.fontLinkHeader, void 0, options.expireSeconds, cached.value.cacheControl, cachedValue.status);
387
+ const staleBotResult = applyBotETagAndCheck(staleResponse, cachedValue.html, options);
388
+ if (staleBotResult) return staleBotResult;
215
389
  return {
216
390
  kind: "response",
217
- response: buildPagesCacheResponse(cachedValue.html, "STALE", options.fontLinkHeader, void 0, options.expireSeconds, cached.value.cacheControl, cachedValue.status)
391
+ response: staleResponse
218
392
  };
219
393
  }
220
- const result = await options.pageModule.getStaticProps({
394
+ const generatedPageData = !options.isOnDemandRevalidate && cached?.isStale === false && cachedValue?.kind === "PAGES" && cachedValue.generatedFromDataRequest && isUnknownRecord(cachedValue.pageData) ? cachedValue.pageData : null;
395
+ if (!generatedPageData) {
396
+ const shortCircuit = await loadForegroundAppInitialRenderProps();
397
+ if (shortCircuit) return shortCircuit;
398
+ }
399
+ const result = generatedPageData ? null : await options.pageModule.getStaticProps({
221
400
  params: userFacingParams,
222
401
  locale: options.i18n.locale,
223
402
  locales: options.i18n.locales,
224
403
  defaultLocale: options.i18n.defaultLocale,
225
404
  revalidateReason: options.isOnDemandRevalidate ? "on-demand" : options.isBuildTimePrerendering ? "build" : "stale"
226
405
  });
227
- if (result?.props) pageProps = result.props;
406
+ if (generatedPageData) {
407
+ renderProps = generatedPageData;
408
+ pageProps = isUnknownRecord(renderProps.pageProps) ? renderProps.pageProps : {};
409
+ }
410
+ if (result?.props) {
411
+ pageProps = {
412
+ ...pageProps,
413
+ ...result.props
414
+ };
415
+ renderProps = {
416
+ ...renderProps,
417
+ pageProps
418
+ };
419
+ }
228
420
  if (result?.redirect) return {
229
421
  kind: "response",
230
- response: buildPagesRedirectResponse(result.redirect, options)
422
+ response: buildPagesRedirectResponse(result.redirect, options, renderProps)
231
423
  };
232
424
  if (result?.notFound) return buildPagesNotFoundResult(options);
233
425
  if (result?.props !== void 0) isSerializableProps(options.routePattern, "getStaticProps", pageProps);
234
426
  if (typeof result?.revalidate === "number" && result.revalidate > 0) isrRevalidateSeconds = result.revalidate;
427
+ else if (cachedValue?.kind === "PAGES" && cachedValue.generatedFromDataRequest) isrRevalidateSeconds = cached?.value.cacheControl?.revalidate ?? 31536e3;
428
+ if (shouldPersistFallbackData) {
429
+ const revalidateSeconds = isrRevalidateSeconds ?? 31536e3;
430
+ await options.isrSet(cacheKey, {
431
+ kind: "PAGES",
432
+ html: "",
433
+ pageData: renderProps,
434
+ generatedFromDataRequest: true,
435
+ headers: void 0,
436
+ status: void 0
437
+ }, revalidateSeconds, void 0, options.expireSeconds);
438
+ }
439
+ }
440
+ if (typeof options.pageModule.getServerSideProps !== "function" && typeof options.pageModule.getStaticProps !== "function" && hasPagesGetInitialProps(options.AppComponent)) {
441
+ const shortCircuit = await loadForegroundAppInitialRenderProps();
442
+ if (shortCircuit) return shortCircuit;
235
443
  }
236
- if (typeof options.pageModule.getServerSideProps !== "function" && typeof options.pageModule.getStaticProps !== "function" && hasPagesGetInitialProps(options.pageModule.default)) {
237
- const { req, res, responsePromise } = options.createGsspReqRes();
444
+ if (typeof options.pageModule.getServerSideProps !== "function" && typeof options.pageModule.getStaticProps !== "function" && !hasPagesGetInitialProps(options.AppComponent) && hasPagesGetInitialProps(options.pageModule.default)) {
445
+ const { req, res, responsePromise } = getSharedReqRes();
238
446
  const initialProps = await loadPagesGetInitialProps(options.pageModule.default, {
239
447
  req,
240
448
  res,
@@ -250,16 +458,23 @@ async function resolvePagesPageData(options) {
250
458
  kind: "response",
251
459
  response: await responsePromise
252
460
  };
253
- if (initialProps) pageProps = {
254
- ...pageProps,
255
- ...initialProps
256
- };
461
+ if (initialProps) {
462
+ pageProps = {
463
+ ...pageProps,
464
+ ...initialProps
465
+ };
466
+ renderProps = {
467
+ ...renderProps,
468
+ pageProps
469
+ };
470
+ }
257
471
  }
258
472
  return {
259
473
  kind: "render",
260
474
  gsspRes,
261
475
  isrRevalidateSeconds,
262
476
  pageProps,
477
+ props: renderProps,
263
478
  isFallback: false
264
479
  };
265
480
  }
@@ -28,8 +28,10 @@ type I18nConfig = {
28
28
  } | null;
29
29
  type VinextConfigSubset = {
30
30
  basePath: string;
31
+ assetPrefix: string;
31
32
  trailingSlash: boolean;
32
33
  expireTime?: number;
34
+ htmlLimitedBots?: string;
33
35
  clientTraceMetadata?: readonly string[];
34
36
  disableOptimizedLoading: boolean;
35
37
  };
@@ -72,8 +74,8 @@ type CreatePagesPageHandlerOptions = {
72
74
  renderIsrPassToStringAsync: (element: ReactNode) => Promise<string>; /** `safeJsonStringify` from `vinext/html`. */
73
75
  safeJsonStringify: (value: unknown) => string; /** `sanitizeDestination` from the config-matchers module. */
74
76
  sanitizeDestination: (dest: string) => string; /** Build the React page element for a given set of page props. */
75
- createPageElement: (PageComponent: ComponentType, AppComponent: ComponentType | null, pageProps: Record<string, unknown>) => ReactNode; /** Build the element with optional App/Component enhancers (for _document). */
76
- enhancePageElement: (PageComponent: ComponentType, AppComponent: ComponentType | null, pageProps: Record<string, unknown>, opts: RenderPageEnhancers) => ReactNode; /** The `_app` page component (or null). */
77
+ createPageElement: (PageComponent: ComponentType, AppComponent: ComponentType | null, props: Record<string, unknown>) => ReactNode; /** Build the element with optional App/Component enhancers (for _document). */
78
+ enhancePageElement: (PageComponent: ComponentType, AppComponent: ComponentType | null, props: Record<string, unknown>, opts: RenderPageEnhancers) => ReactNode; /** The `_app` page component (or null). */
77
79
  AppComponent: ComponentType | null; /** The `_document` page component (or null). */
78
80
  DocumentComponent: ComponentType | null;
79
81
  };
@@ -81,6 +83,7 @@ type RenderPageOptions = {
81
83
  isDataReq?: boolean;
82
84
  statusCode?: number;
83
85
  asPath?: string;
86
+ originalUrl?: string;
84
87
  renderErrorPageOnMiss?: boolean;
85
88
  __isInternalErrorRender?: boolean;
86
89
  __forcedRoute?: PageRoute;