vinext 1.0.0 → 1.0.1

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 (148) hide show
  1. package/THIRD_PARTY_LICENSES.md +26 -0
  2. package/dist/build/lifecycle.js +10 -10
  3. package/dist/build/pages-client-assets-module.js +6 -1
  4. package/dist/build/precompress.js +1 -1
  5. package/dist/build/prerender-paths.js +3 -7
  6. package/dist/build/prerender.d.ts +8 -1
  7. package/dist/build/prerender.js +134 -38
  8. package/dist/build/run-prerender.js +4 -3
  9. package/dist/build/server-entry.d.ts +2 -0
  10. package/dist/build/server-entry.js +7 -1
  11. package/dist/client/browser-globals.d.ts +4 -0
  12. package/dist/client/browser-globals.js +5 -0
  13. package/dist/client/navigation-runtime.d.ts +0 -1
  14. package/dist/client/navigation-runtime.js +2 -2
  15. package/dist/config/dotenv.js +14 -3
  16. package/dist/entries/app-rsc-entry.js +3 -2
  17. package/dist/index.js +142 -71
  18. package/dist/init-cloudflare.d.ts +1 -1
  19. package/dist/init-cloudflare.js +6 -6
  20. package/dist/init-platform.js +1 -1
  21. package/dist/init.js +4 -2
  22. package/dist/plugins/commonjs-syntax.d.ts +16 -0
  23. package/dist/plugins/commonjs-syntax.js +22 -0
  24. package/dist/plugins/ignore-dynamic-requests.d.ts +11 -0
  25. package/dist/plugins/ignore-dynamic-requests.js +54 -3
  26. package/dist/plugins/import-meta-url.js +6 -6
  27. package/dist/plugins/og-asset-ownership.d.ts +2 -0
  28. package/dist/plugins/og-asset-ownership.js +24 -13
  29. package/dist/plugins/og-assets.d.ts +18 -0
  30. package/dist/plugins/og-assets.js +50 -8
  31. package/dist/plugins/og-harfbuzz.js +38 -27
  32. package/dist/plugins/optimize-imports.js +2 -1
  33. package/dist/plugins/require-context.d.ts +1 -0
  34. package/dist/plugins/require-context.js +28 -1
  35. package/dist/plugins/scan-build-css.d.ts +12 -0
  36. package/dist/plugins/scan-build-css.js +39 -0
  37. package/dist/plugins/strip-server-exports.d.ts +2 -0
  38. package/dist/plugins/strip-server-exports.js +3 -1
  39. package/dist/plugins/transform-result.d.ts +18 -0
  40. package/dist/plugins/transform-result.js +23 -2
  41. package/dist/plugins/typeof-window.d.ts +10 -0
  42. package/dist/plugins/typeof-window.js +33 -9
  43. package/dist/routing/app-route-graph.d.ts +0 -1
  44. package/dist/routing/app-route-graph.js +2 -4
  45. package/dist/routing/app-route-ids.d.ts +3 -0
  46. package/dist/routing/app-route-ids.js +6 -0
  47. package/dist/server/app-bfcache-id.d.ts +1 -0
  48. package/dist/server/app-bfcache-id.js +7 -1
  49. package/dist/server/app-bfcache-identity.js +1 -2
  50. package/dist/server/app-browser-entry.js +4 -2
  51. package/dist/server/app-browser-hydration.d.ts +1 -1
  52. package/dist/server/app-browser-hydration.js +2 -2
  53. package/dist/server/app-browser-navigation-controller.js +1 -1
  54. package/dist/server/app-browser-state.js +1 -1
  55. package/dist/server/app-browser-stream.d.ts +1 -1
  56. package/dist/server/app-history-state.d.ts +0 -1
  57. package/dist/server/app-history-state.js +2 -5
  58. package/dist/server/app-page-cache-render.js +2 -1
  59. package/dist/server/app-page-render.js +2 -1
  60. package/dist/server/app-page-search-params-observation.js +1 -1
  61. package/dist/server/app-page-stream.js +1 -1
  62. package/dist/server/app-page-tracing.js +2 -1
  63. package/dist/server/app-pages-bridge.js +3 -2
  64. package/dist/server/app-render-abort-error.d.ts +3 -0
  65. package/dist/server/app-render-abort-error.js +8 -0
  66. package/dist/server/app-request-stage-independent-entry.js +4 -7
  67. package/dist/server/app-route-handler-cache.d.ts +2 -1
  68. package/dist/server/app-route-handler-cache.js +11 -7
  69. package/dist/server/app-route-handler-dispatch.js +10 -3
  70. package/dist/server/app-route-handler-execution.d.ts +9 -1
  71. package/dist/server/app-route-handler-execution.js +28 -13
  72. package/dist/server/app-route-handler-policy.js +2 -2
  73. package/dist/server/app-route-handler-response.d.ts +1 -1
  74. package/dist/server/app-route-handler-response.js +14 -5
  75. package/dist/server/app-router-entry.d.ts +2 -1
  76. package/dist/server/app-router-entry.js +5 -9
  77. package/dist/server/app-rsc-errors.d.ts +0 -1
  78. package/dist/server/app-rsc-errors.js +2 -6
  79. package/dist/server/app-rsc-handler.d.ts +1 -0
  80. package/dist/server/app-rsc-handler.js +18 -7
  81. package/dist/server/app-rsc-request-normalization.d.ts +1 -1
  82. package/dist/server/app-rsc-request-normalization.js +3 -2
  83. package/dist/server/app-rsc-response-finalizer.js +4 -1
  84. package/dist/server/app-rsc-route-matching.js +1 -1
  85. package/dist/server/app-server-action-execution.d.ts +2 -1
  86. package/dist/server/app-ssr-entry.js +3 -3
  87. package/dist/server/app-ssr-search-params-gate.js +1 -1
  88. package/dist/server/app-ssr-stream.js +1 -1
  89. package/dist/server/cache-control.js +3 -11
  90. package/dist/server/cacheability-request.js +49 -49
  91. package/dist/server/config-headers.js +1 -1
  92. package/dist/server/dev-server.js +11 -3
  93. package/dist/server/headers.d.ts +2 -0
  94. package/dist/server/headers.js +5 -1
  95. package/dist/server/http-error-responses.js +1 -0
  96. package/dist/server/isr-cache.d.ts +2 -0
  97. package/dist/server/isr-cache.js +6 -1
  98. package/dist/server/metadata-route-response.js +94 -37
  99. package/dist/server/pages-api-route.js +8 -2
  100. package/dist/server/pages-asset-tags.d.ts +1 -0
  101. package/dist/server/pages-asset-tags.js +73 -22
  102. package/dist/server/pages-client-assets.d.ts +2 -0
  103. package/dist/server/pages-page-data.d.ts +6 -1
  104. package/dist/server/pages-page-data.js +71 -65
  105. package/dist/server/pages-page-handler.js +29 -11
  106. package/dist/server/pages-page-response.js +3 -1
  107. package/dist/server/pages-request-pipeline.d.ts +2 -1
  108. package/dist/server/pages-request-pipeline.js +20 -5
  109. package/dist/server/pages-request-stage-entry.js +6 -4
  110. package/dist/server/prerender-manifest.d.ts +6 -0
  111. package/dist/server/prerender-manifest.js +1 -1
  112. package/dist/server/prod-server.js +3 -13
  113. package/dist/server/response-stage-cacheability.js +1 -1
  114. package/dist/server/worker-revalidation-context.d.ts +2 -1
  115. package/dist/server/worker-revalidation-context.js +1 -0
  116. package/dist/server/workers-tracing.d.ts +17 -0
  117. package/dist/server/workers-tracing.js +48 -8
  118. package/dist/shims/cache-request-state.d.ts +3 -14
  119. package/dist/shims/cache-request-state.js +2 -13
  120. package/dist/shims/cache-runtime.js +4 -2
  121. package/dist/shims/cache.d.ts +2 -1
  122. package/dist/shims/cache.js +4 -2
  123. package/dist/shims/cacheability-classification.d.ts +1 -1
  124. package/dist/shims/cacheability-classification.js +2 -2
  125. package/dist/shims/cdn-cache.d.ts +10 -1
  126. package/dist/shims/cdn-cache.js +16 -9
  127. package/dist/shims/error.d.ts +4 -18
  128. package/dist/shims/error.js +17 -10
  129. package/dist/shims/error.react-server.d.ts +4 -6
  130. package/dist/shims/error.react-server.js +4 -1
  131. package/dist/shims/fetch-cache.js +4 -3
  132. package/dist/shims/headers.d.ts +6 -69
  133. package/dist/shims/headers.js +37 -181
  134. package/dist/shims/internal/cache-context-accessor.d.ts +16 -0
  135. package/dist/shims/internal/cache-context-accessor.js +15 -0
  136. package/dist/shims/internal/headers-state.d.ts +74 -0
  137. package/dist/shims/internal/headers-state.js +157 -0
  138. package/dist/shims/navigation.js +2 -2
  139. package/dist/shims/request-state-types.d.ts +2 -1
  140. package/dist/shims/root-params.js +1 -1
  141. package/dist/shims/server.js +52 -2
  142. package/dist/shims/unified-request-context.d.ts +1 -1
  143. package/dist/utils/encode-cache-tag.d.ts +1 -0
  144. package/dist/utils/encode-cache-tag.js +11 -1
  145. package/dist/utils/vite-cli-invocation.js +8 -1
  146. package/package.json +6 -2
  147. package/dist/server/metadata-route-cache-policy.d.ts +0 -5
  148. package/dist/server/metadata-route-cache-policy.js +0 -6
@@ -1,8 +1,10 @@
1
+ import { isFullyBufferedBody } from "./fully-buffered-response.js";
1
2
  import { patternToNextFormat } from "../routing/route-validation.js";
2
3
  import { frameworkTracer } from "./tracer.js";
3
- import { getRouteCacheabilityCaptureOptions, getRouteCacheabilityDynamicReason, isRouteCacheabilityEvaluation, markRouteCacheabilityExplicitResponsePolicy, markRouteCacheabilityResponseBodyComplete } from "../shims/cacheability-classification.js";
4
+ import { getRouteCacheabilityCaptureOptions, getRouteCacheabilityDynamicReason, isRouteCacheabilityEvaluation, markRouteCacheabilityExplicitResponsePolicy, markRouteCacheabilityResponseBodyComplete, recordRouteCacheability } from "../shims/cacheability-classification.js";
4
5
  import { NEVER_CACHE_CONTROL, applyCdnResponseHeaders, hasCdnResponsePolicy, hasExplicitNonCacheableResponsePolicy } from "./cache-control.js";
5
- import { isrCacheControl } from "./isr-cache.js";
6
+ import { buildAppRouteMissIsrCacheControl } from "./isr-decision.js";
7
+ import { isrCacheControl, resolveRouteExpireSeconds } from "./isr-cache.js";
6
8
  import { isDraftModeRequest, setHeadersContext } from "../shims/headers.js";
7
9
  import { _drainPendingRevalidations } from "../shims/cache-request-state.js";
8
10
  import { copyLinkHeaderProvenance } from "./app-response-header-provenance.js";
@@ -18,6 +20,10 @@ function hasExplicitCacheableResponsePolicy(headers) {
18
20
  return !hasExplicitNonCacheableResponsePolicy(headers) && hasCdnResponsePolicy(headers);
19
21
  }
20
22
  async function completeAppRouteHandlerResponse(response) {
23
+ if (isFullyBufferedBody(response)) return {
24
+ completed: true,
25
+ response
26
+ };
21
27
  const { captureCacheabilityAdmissionBody } = await import("./cacheability-request.js");
22
28
  const captureOptions = getRouteCacheabilityCaptureOptions();
23
29
  const captured = await captureCacheabilityAdmissionBody(response.body, captureOptions?.captureDeadlineAt ?? Date.now() + 2e4, CACHEABILITY_ADMISSION_RESPONSE_BODY_LIMIT, captureOptions?.captureBudget);
@@ -189,16 +195,13 @@ async function executeAppRouteHandlerImpl(options) {
189
195
  const handlerResult = tracedResult.handlerResult;
190
196
  let { dynamicUsedInHandler, response } = handlerResult;
191
197
  assertSupportedAppRouteHandlerResponse(response);
192
- const handlerSetCachePolicy = hasCdnResponsePolicy(response.headers);
193
- const hasExplicitCacheablePolicy = hasExplicitCacheableResponsePolicy(response.headers);
194
- if (hasExplicitCacheablePolicy) markRouteCacheabilityExplicitResponsePolicy();
195
198
  const draftModeBeforeCompletion = options.getActiveDraftModeState?.() ?? options.isDraftMode === true;
196
199
  const handlerDraftCookieBeforeCompletion = options.getDraftModeCookieHeader() ?? options.initialDraftModeCookie;
197
200
  if (shouldCompleteAppRouteHandlerResponse({
198
201
  dynamicConfig: options.handler.dynamic,
199
202
  dynamicUsedInHandler,
200
- hasExplicitCacheablePolicy,
201
- handlerSetCachePolicy,
203
+ hasExplicitCacheablePolicy: hasExplicitCacheableResponsePolicy(response.headers),
204
+ handlerSetCachePolicy: hasCdnResponsePolicy(response.headers),
202
205
  isAutoHead: options.isAutoHead,
203
206
  isDraftMode: draftModeBeforeCompletion || handlerDraftCookieBeforeCompletion != null,
204
207
  isProduction: options.isProduction,
@@ -213,6 +216,9 @@ async function executeAppRouteHandlerImpl(options) {
213
216
  const dynamicUsedDuringCompletion = options.consumeDynamicUsage();
214
217
  dynamicUsedInHandler = handlerResult.didAccessDynamicRequest() || dynamicUsedDuringCompletion || dynamicUsedInHandler;
215
218
  }
219
+ const browserCacheControl = response.headers.get("Cache-Control") ?? void 0;
220
+ const handlerSetCachePolicy = hasCdnResponsePolicy(response.headers);
221
+ if (handlerSetCachePolicy) markRouteCacheabilityExplicitResponsePolicy();
216
222
  const requestCacheabilityVeto = getRouteCacheabilityDynamicReason();
217
223
  const responseMustStayPrivate = Boolean(options.bypassSharedCache === true || options.handler.dynamic === "force-dynamic" || dynamicUsedInHandler || requestCacheabilityVeto || cleanupDeferredToBody);
218
224
  if (dynamicUsedInHandler) markKnownDynamicAppRoute(options.routePattern);
@@ -222,6 +228,15 @@ async function executeAppRouteHandlerImpl(options) {
222
228
  const shouldApplyDraftPolicy = (options.getActiveDraftModeState?.() ?? options.isDraftMode === true) || draftCookie != null;
223
229
  if (handlerDraftCookie != null) markKnownDynamicAppRoute(options.routePattern);
224
230
  const routeTags = options.buildPageCacheTags(options.cleanPathname, options.getCollectedFetchTags());
231
+ const frameworkCacheable = (options.isRevalidation === true || response.status < 400 || response.status === 404) && options.revalidateSeconds !== null && options.revalidateSeconds > 0 && !responseMustStayPrivate && !shouldApplyDraftPolicy && pendingCookies.length === 0 && !response.headers.has("set-cookie") && (options.method === "GET" || options.isAutoHead);
232
+ recordRouteCacheability(frameworkCacheable ? {
233
+ cacheable: true,
234
+ cacheControl: buildAppRouteMissIsrCacheControl(options.revalidateSeconds, options.expireSeconds),
235
+ tags: routeTags
236
+ } : {
237
+ cacheable: false,
238
+ dynamicUsage: responseMustStayPrivate || shouldApplyDraftPolicy || options.revalidateSeconds === 0
239
+ });
225
240
  if (shouldApplyAppRouteHandlerRevalidateHeader({
226
241
  dynamicUsedInHandler: responseMustStayPrivate,
227
242
  handlerSetCachePolicy,
@@ -234,9 +249,9 @@ async function executeAppRouteHandlerImpl(options) {
234
249
  if (revalidateSeconds == null) throw new Error("Expected route handler revalidate seconds");
235
250
  applyRouteHandlerRevalidateHeader(response, revalidateSeconds, options.expireSeconds, routeTags);
236
251
  }
237
- if (shouldWriteAppRouteHandlerCache({
252
+ if (frameworkCacheable && shouldWriteAppRouteHandlerCache({
238
253
  dynamicConfig: options.handler.dynamic,
239
- dynamicUsedInHandler: responseMustStayPrivate,
254
+ dynamicUsedInHandler: responseMustStayPrivate || pendingCookies.length > 0 || response.headers.has("set-cookie"),
240
255
  handlerSetCachePolicy,
241
256
  isAutoHead: options.isAutoHead,
242
257
  isDraftMode: shouldApplyDraftPolicy,
@@ -251,9 +266,9 @@ async function executeAppRouteHandlerImpl(options) {
251
266
  if (revalidateSeconds == null) throw new Error("Expected route handler cache revalidate seconds");
252
267
  const routeWritePromise = (async () => {
253
268
  try {
254
- const routeCacheValue = await buildAppRouteCacheValue(routeClone);
269
+ const routeCacheValue = await buildAppRouteCacheValue(routeClone, browserCacheControl);
255
270
  await options.isrSet(routeKey, routeCacheValue, {
256
- cacheControl: isrCacheControl(revalidateSeconds, { expireSeconds: options.expireSeconds }),
271
+ cacheControl: isrCacheControl(revalidateSeconds === Infinity ? false : revalidateSeconds, { expireSeconds: resolveRouteExpireSeconds(options.revalidateSeconds, options.expireSeconds) }),
257
272
  tags: routeTags
258
273
  });
259
274
  options.isrDebug?.("route cache written", routeKey);
@@ -268,7 +283,7 @@ async function executeAppRouteHandlerImpl(options) {
268
283
  draftCookie,
269
284
  isHead: options.isAutoHead
270
285
  }), options.middlewareContext, middlewareMergeOptions), shouldApplyDraftPolicy);
271
- const preserveHandlerPolicy = isRouteCacheabilityEvaluation() ? hasExplicitCacheablePolicy : handlerSetCachePolicy;
286
+ const preserveHandlerPolicy = handlerSetCachePolicy;
272
287
  if (options.bypassSharedCache === true || responseMustStayPrivate && !preserveHandlerPolicy) {
273
288
  const headers = new Headers(finalized.headers);
274
289
  applyCdnResponseHeaders(headers, { cacheControl: NEVER_CACHE_CONTROL });
@@ -328,4 +343,4 @@ async function executeAppRouteHandlerImpl(options) {
328
343
  }
329
344
  }
330
345
  //#endregion
331
- export { applyDraftModeCachePolicy, executeAppRouteHandler, runAppRouteHandler, traceAppRouteHandlerExecution };
346
+ export { applyDraftModeCachePolicy, completeAppRouteHandlerResponse, executeAppRouteHandler, runAppRouteHandler, traceAppRouteHandlerExecution };
@@ -36,7 +36,7 @@ function resolveAppRouteHandlerMethod(handler, method) {
36
36
  };
37
37
  }
38
38
  function shouldReadAppRouteHandlerCache(options) {
39
- return options.isProduction && options.revalidateSeconds !== null && options.revalidateSeconds > 0 && options.revalidateSeconds !== Infinity && options.dynamicConfig !== "force-dynamic" && !options.isDraftMode && !options.isKnownDynamic && (options.method === "GET" || options.isAutoHead) && typeof options.handlerFn === "function";
39
+ return options.isProduction && options.revalidateSeconds !== null && options.revalidateSeconds > 0 && options.dynamicConfig !== "force-dynamic" && !options.isDraftMode && !options.isKnownDynamic && (options.method === "GET" || options.isAutoHead) && typeof options.handlerFn === "function";
40
40
  }
41
41
  function shouldApplyAppRouteHandlerRevalidateHeader(options) {
42
42
  return options.revalidateSeconds !== null && !options.isDraftMode && !options.dynamicUsedInHandler && (options.method === "GET" || options.isAutoHead) && !options.handlerSetCachePolicy;
@@ -51,7 +51,7 @@ function shouldCompleteAppRouteHandlerResponse(options) {
51
51
  return options.isProduction && (options.revalidateSeconds !== null && options.revalidateSeconds > 0 || options.requiresCompletedResponseAdmission === true || options.hasExplicitCacheablePolicy === true) && options.dynamicConfig !== "force-dynamic" && !options.isDraftMode && !options.dynamicUsedInHandler && (options.method === "GET" || options.isAutoHead);
52
52
  }
53
53
  function shouldWriteAppRouteHandlerCache(options) {
54
- return options.isProduction && options.revalidateSeconds !== null && options.revalidateSeconds > 0 && options.revalidateSeconds !== Infinity && options.dynamicConfig !== "force-dynamic" && !options.isDraftMode && shouldApplyAppRouteHandlerRevalidateHeader(options);
54
+ return options.isProduction && options.revalidateSeconds !== null && options.revalidateSeconds > 0 && options.dynamicConfig !== "force-dynamic" && !options.isDraftMode && !options.dynamicUsedInHandler && (options.method === "GET" || options.isAutoHead);
55
55
  }
56
56
  function resolveAppRouteHandlerSpecialError(error, requestUrl, options) {
57
57
  if (!(error && typeof error === "object" && "digest" in error)) return null;
@@ -23,6 +23,6 @@ export declare function assertSupportedAppRouteHandlerResponse(response: Respons
23
23
  export declare function buildRouteHandlerCachedResponse(cachedValue: CachedRouteValue, options: BuildRouteHandlerCachedResponseOptions): Response;
24
24
  export declare function applyRouteHandlerRevalidateHeader(response: Response, revalidateSeconds: number, expireSeconds?: number, tags?: readonly string[]): void;
25
25
  export declare function markRouteHandlerCacheMiss(response: Response): void;
26
- export declare function buildAppRouteCacheValue(response: Response): Promise<CachedRouteValue>;
26
+ export declare function buildAppRouteCacheValue(response: Response, browserCacheControl?: string): Promise<CachedRouteValue>;
27
27
  export declare function finalizeRouteHandlerResponse(response: Response, options: FinalizeRouteHandlerResponseOptions): Response;
28
28
  //#endregion
@@ -1,7 +1,7 @@
1
1
  import "../utils/protocol-headers.js";
2
2
  import { NEXT_CACHE_TAGS_HEADER, VINEXT_METADATA_ROUTE_CACHE_HEADER } from "./headers.js";
3
3
  import { processMiddlewareHeaders } from "./request-pipeline.js";
4
- import { markRouteCacheabilityExplicitConfigPolicy } from "../shims/cacheability-classification.js";
4
+ import { markRouteCacheabilityExplicitResponsePolicy, recordRouteCacheability } from "../shims/cacheability-classification.js";
5
5
  import { applyCdnResponseHeaders } from "./cache-control.js";
6
6
  import { buildAppRouteMissIsrCacheControl, decideIsr } from "./isr-decision.js";
7
7
  import { setCacheStateHeaders } from "./cache-headers.js";
@@ -50,14 +50,22 @@ function buildRouteHandlerCachedResponse(cachedValue, options) {
50
50
  expireSeconds: options.expireSeconds,
51
51
  cacheControlMeta: options.cacheControl
52
52
  });
53
- applyCdnResponseHeaders(headers, { cacheControl });
54
- return new Response(options.isHead ? null : cachedValue.body, {
53
+ recordRouteCacheability({
54
+ cacheable: true,
55
+ cacheControl
56
+ });
57
+ if (headers.has("Cache-Control")) markRouteCacheabilityExplicitResponsePolicy();
58
+ applyCdnResponseHeaders(headers, {
59
+ cacheControl,
60
+ browserCacheControl: headers.get("Cache-Control") ?? void 0
61
+ });
62
+ const hasNoBody = options.isHead || cachedValue.status === 204 || cachedValue.status === 205 || cachedValue.status === 304;
63
+ return new Response(hasNoBody ? null : cachedValue.body, {
55
64
  status: cachedValue.status,
56
65
  headers
57
66
  });
58
67
  }
59
68
  function applyRouteHandlerRevalidateHeader(response, revalidateSeconds, expireSeconds, tags) {
60
- markRouteCacheabilityExplicitConfigPolicy();
61
69
  applyCdnResponseHeaders(response.headers, {
62
70
  cacheControl: buildAppRouteMissIsrCacheControl(revalidateSeconds, expireSeconds),
63
71
  tags
@@ -125,13 +133,14 @@ function applyMutableCookieFallbacks(headers, pendingCookies) {
125
133
  for (const cookie of fallbackCookies.values()) headers.append("Set-Cookie", cookie);
126
134
  for (const cookie of returnedCookies) headers.append("Set-Cookie", normalizeReturnedCookie(cookie));
127
135
  }
128
- async function buildAppRouteCacheValue(response) {
136
+ async function buildAppRouteCacheValue(response, browserCacheControl) {
129
137
  const body = await response.arrayBuffer();
130
138
  const headers = {};
131
139
  response.headers.forEach((value, key) => {
132
140
  if (key === "set-cookie" || key === "connection" || key === "content-length" || key === "date" || key === "keep-alive" || key === "transfer-encoding" || key === "x-next-cache-tags" || key === "x-vinext-metadata-route-cache" || key === "x-vinext-prerender-cache-life" || key === "X-Vinext-Cache".toLowerCase() || key === "x-nextjs-cache".toLowerCase() || key === "cache-control" || key.startsWith("x-middleware-")) return;
133
141
  headers[key] = value;
134
142
  });
143
+ if (browserCacheControl !== void 0) headers["cache-control"] = browserCacheControl;
135
144
  const setCookies = response.headers.getSetCookie?.() ?? [];
136
145
  if (setCookies.length > 0) headers["set-cookie"] = setCookies;
137
146
  return {
@@ -1,3 +1,4 @@
1
+ import { VinextRequestStageContext } from "./multi-stage.js";
1
2
  import { ExecutionContextLike } from "../shims/request-context.js";
2
3
  import { __ensureInstrumentation } from "virtual:vinext-rsc-entry";
3
4
  //#region src/server/app-router-entry.d.ts
@@ -8,7 +9,7 @@ type WorkerAssetEnv = {
8
9
  };
9
10
  declare const _default: {
10
11
  __ensureInstrumentation: typeof __ensureInstrumentation;
11
- fetch(request: Request, env?: WorkerAssetEnv, ctx?: ExecutionContextLike): Promise<Response>;
12
+ fetch(request: Request, env?: WorkerAssetEnv, ctx?: ExecutionContextLike & VinextRequestStageContext): Promise<Response>;
12
13
  };
13
14
  //#endregion
14
15
  export { _default as default };
@@ -11,7 +11,7 @@ import { getCdnCacheAdapter } from "../shims/cdn-cache.js";
11
11
  import { applyCdnResponseIdentityHeaders, validateCdnRequest } from "./cache-control.js";
12
12
  import { getImageOptimizer, handleConfiguredImageOptimization, isImageOptimizationPath } from "./image-optimization.js";
13
13
  import { traceFrameworkRequest } from "./request-tracing.js";
14
- import { createStaticAssetRequest, finalizeMissingStaticAssetResponse, resolveStaticAssetSignal } from "./worker-utils.js";
14
+ import { createStaticAssetRequest, resolveStaticAssetSignal } from "./worker-utils.js";
15
15
  import { readTrustedPrerenderRouteParams, serializePrerenderRouteParamsHeader } from "./prerender-route-params.js";
16
16
  import { createWorkerRevalidationContext } from "./worker-revalidation-context.js";
17
17
  import { createWorkerPrerenderDiscoveryContext, createWorkerPrerenderReadinessResponse } from "./worker-prerender-discovery.js";
@@ -48,6 +48,7 @@ async function handleRequest(request, env, platformCtx) {
48
48
  const requestCtx = platformCtx?.trustedRevalidateOrigin ? platformCtx : createWorkerRevalidationContext(platformCtx, (internalRequest, internalCtx) => handleRequest(internalRequest, env, internalCtx));
49
49
  registerConfiguredCacheAdapters(env);
50
50
  const cdnCacheAdapter = getCdnCacheAdapter();
51
+ const assets = platformCtx?.assets ?? cdnCacheAdapter.assets ?? env?.ASSETS;
51
52
  let ctx = createWorkerPrerenderDiscoveryContext(requestCtx, request, __prerenderSecret);
52
53
  const readinessResponse = createWorkerPrerenderReadinessResponse(ctx, request);
53
54
  if (readinessResponse) {
@@ -81,10 +82,7 @@ async function handleRequest(request, env, platformCtx) {
81
82
  const cdnValidationResponse = await validateCdnRequest(request);
82
83
  if (cdnValidationResponse) return cdnValidationResponse;
83
84
  const url = new URL(request.url);
84
- if (isImageOptimizationPath(url.pathname) && env?.ASSETS && getImageOptimizer()) {
85
- const assetFetcher = env.ASSETS;
86
- return handleConfiguredImageOptimization(request, (assetPath) => Promise.resolve(assetFetcher.fetch(new Request(new URL(assetPath, request.url)))), __imageAllowedWidths, __imageConfig);
87
- }
85
+ if (isImageOptimizationPath(url.pathname) && assets && getImageOptimizer()) return handleConfiguredImageOptimization(request, (assetPath) => Promise.resolve(assets.fetch(new Request(new URL(assetPath, request.url)))), __imageAllowedWidths, __imageConfig);
88
86
  if (isOpenRedirectShaped(url.pathname)) return notFoundResponse();
89
87
  try {
90
88
  decodeURIComponent(url.pathname);
@@ -105,12 +103,10 @@ async function handleRequest(request, env, platformCtx) {
105
103
  const result = await (ctx ? runWithExecutionContext(ctx, handleFn) : handleFn());
106
104
  if (result instanceof Response) {
107
105
  let response = result;
108
- if (env?.ASSETS) {
109
- const assetFetcher = env.ASSETS;
110
- const assetResponse = await resolveStaticAssetSignal(response, { fetchAsset: (path) => Promise.resolve(assetFetcher.fetch(createStaticAssetRequest(path, request))) });
106
+ if (assets) {
107
+ const assetResponse = await resolveStaticAssetSignal(response, { fetchAsset: (path) => Promise.resolve(assets.fetch(createStaticAssetRequest(path, request))) });
111
108
  if (assetResponse) response = assetResponse;
112
109
  }
113
- response = finalizeMissingStaticAssetResponse(response, missingBuildAsset);
114
110
  return finalizeCacheabilityResponse ? finalizeCacheabilityResponse(response, ctx) : response;
115
111
  }
116
112
  if (result === null || result === void 0) {
@@ -22,7 +22,6 @@ type CreateRscOnErrorHandlerOptions = {
22
22
  export declare function hasDigest(error: unknown): error is {
23
23
  digest: unknown;
24
24
  };
25
- export declare function isAppRenderAbortError(error: unknown): boolean;
26
25
  /**
27
26
  * vinext's mirror of Next.js's `getDigestForWellKnownError`: returns the digest
28
27
  * string only when the error is a genuine control-flow signal — a redirect,
@@ -1,5 +1,6 @@
1
1
  import { isNavigationSignalError } from "../utils/navigation-signal.js";
2
2
  import { resolveAppPageSpecialError } from "./app-page-execution.js";
3
+ import { isAppRenderAbortError } from "./app-render-abort-error.js";
3
4
  //#region src/server/app-rsc-errors.ts
4
5
  const ORIGINAL_SERVER_ERROR = Symbol.for("vinext.originalServerError");
5
6
  function hasDigest(error) {
@@ -7,11 +8,6 @@ function hasDigest(error) {
7
8
  }
8
9
  const BAILOUT_TO_CSR_DIGEST = "BAILOUT_TO_CLIENT_SIDE_RENDERING";
9
10
  const DYNAMIC_SERVER_USAGE_DIGEST = "DYNAMIC_SERVER_USAGE";
10
- function isAppRenderAbortError(error) {
11
- if (!error || typeof error !== "object") return false;
12
- const name = Reflect.get(error, "name");
13
- return name === "AbortError" || name === "ResponseAborted";
14
- }
15
11
  /**
16
12
  * vinext's mirror of Next.js's `getDigestForWellKnownError`: returns the digest
17
13
  * string only when the error is a genuine control-flow signal — a redirect,
@@ -85,4 +81,4 @@ function createRscOnErrorHandler(options) {
85
81
  };
86
82
  }
87
83
  //#endregion
88
- export { createRscOnErrorHandler, errorDigest, getDigestForWellKnownError, hasDigest, isAppRenderAbortError, sanitizeErrorForClient };
84
+ export { createRscOnErrorHandler, errorDigest, getDigestForWellKnownError, hasDigest, sanitizeErrorForClient };
@@ -184,6 +184,7 @@ type NavigationContextValue = {
184
184
  searchParams: URLSearchParams;
185
185
  };
186
186
  export type CreateAppRscHandlerOptions<TRoute extends AppRscHandlerRoute> = {
187
+ assetPrefix?: string;
187
188
  basePath: string;
188
189
  buildId: string | null;
189
190
  /**
@@ -4,14 +4,15 @@ import { PRERENDER_REVALIDATE_HEADER, VINEXT_MW_CTX_HEADER, VINEXT_PRERENDER_ROU
4
4
  import { hasMiddlewareRequestHeaderOverrides } from "../utils/middleware-request-headers.js";
5
5
  import { requestContextFromRequest } from "../config/request-context.js";
6
6
  import { isExternalUrl } from "../utils/external-url.js";
7
+ import { assetPrefixPathname, isNextStaticPath } from "../utils/asset-prefix.js";
7
8
  import { normalizePathnameForRouteMatchStrict } from "../routing/utils.js";
8
9
  import { addBasePathToPathname, hasBasePath, stripBasePath } from "../utils/base-path.js";
9
10
  import { patternToNextFormat } from "../routing/route-validation.js";
10
11
  import { getRequestExecutionContext } from "../shims/request-context.js";
11
12
  import "./app-rsc-vary.js";
12
- import { ACTION_REVALIDATED_HEADER, FLIGHT_HEADERS, VINEXT_PARAMS_HEADER, VINEXT_RENDERED_PATH_AND_SEARCH_HEADER } from "./headers.js";
13
+ import { ACTION_REVALIDATED_HEADER, FLIGHT_HEADERS, VINEXT_PARAMS_HEADER, VINEXT_PRERENDER_REWRITTEN_HEADER, VINEXT_RENDERED_PATH_AND_SEARCH_HEADER } from "./headers.js";
13
14
  import { isInterceptionMatchedUrlPath, normalizePath } from "./normalize-path.js";
14
- import { badRequestResponse, notFoundResponse } from "./http-error-responses.js";
15
+ import { badRequestResponse, notFoundResponse, notFoundStaticAssetResponse } from "./http-error-responses.js";
15
16
  import { cloneRequestWithHeaders, cloneRequestWithUrl, filterInternalHeaders, normalizeTrailingSlash, resolvePublicFileRoute } from "./request-pipeline.js";
16
17
  import { normalizeDefaultLocalePathname } from "./pages-i18n.js";
17
18
  import { getCdnCacheAdapter } from "../shims/cdn-cache.js";
@@ -236,7 +237,7 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
236
237
  ...options.configRewrites.fallback,
237
238
  ...options.configHeaders
238
239
  ].some((rule) => rule.basePath === false);
239
- const normalized = normalizeRscRequest(request, options.basePath, canHandleOutsideBasePath);
240
+ const normalized = normalizeRscRequest(request, options.basePath, canHandleOutsideBasePath, options.assetPrefix);
240
241
  if (normalized instanceof Response) {
241
242
  if (request.headers.has("X-Vinext-Interception-Context") || request.headers.has("X-Vinext-Interception-Id")) setInterceptionResponseUncacheable(true);
242
243
  return normalized;
@@ -837,15 +838,18 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
837
838
  if (response) preserveRouteCacheabilityResponsePolicy();
838
839
  if (!response) return null;
839
840
  if (sharedOuterPolicyNeedsReconciliation) reconcileCdnResponseHeadersAfterOuterPolicy(response.headers, await loadOuterResponsePolicy());
840
- if (!pagesDataRequest || resolvedUrl === originalResolvedUrl) return dispatchPagesResponseStage ? markAppRscResponseConfigHeadersApplied(response) : response;
841
+ const isRewritten = resolvedUrl !== originalResolvedUrl;
842
+ const isPrerender = typeof process !== "undefined" && process.env?.VINEXT_PRERENDER === "1";
843
+ if ((!pagesDataRequest || !isRewritten) && !isPrerender) return dispatchPagesResponseStage ? markAppRscResponseConfigHeadersApplied(response) : response;
841
844
  const headers = new Headers(response.headers);
842
- headers.set("x-nextjs-rewrite", resolvedUrl);
843
- const rewrittenResponse = new Response(response.body, {
845
+ if (pagesDataRequest && isRewritten) headers.set("x-nextjs-rewrite", resolvedUrl);
846
+ if (isPrerender) headers.set(VINEXT_PRERENDER_REWRITTEN_HEADER, isRewritten ? "1" : "0");
847
+ const markedResponse = new Response(response.body, {
844
848
  headers,
845
849
  status: response.status,
846
850
  statusText: response.statusText
847
851
  });
848
- return dispatchPagesResponseStage ? markAppRscResponseConfigHeadersApplied(rewrittenResponse) : rewrittenResponse;
852
+ return dispatchPagesResponseStage ? markAppRscResponseConfigHeadersApplied(markedResponse) : markedResponse;
849
853
  };
850
854
  const staticPagesFallbackResponse = await renderPagesForMatchKind("static");
851
855
  if (staticPagesFallbackResponse) {
@@ -943,6 +947,13 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
943
947
  bypassInterceptionContextCache = !hasVerifiedFinalInterceptionSource;
944
948
  setInterceptionResponseUncacheable(bypassInterceptionContextCache);
945
949
  }
950
+ if ((!filesystemRouteEligible || !match) && isNextStaticPath(cleanPathname, "", assetPrefixPathname(options.assetPrefix ?? ""))) {
951
+ options.clearRequestContext();
952
+ const headers = new Headers();
953
+ mergeMiddlewareResponseHeaders(headers, middlewareContext.headers);
954
+ applyCdnResponseHeaders(headers, { cacheControl: NEVER_CACHE_CONTROL });
955
+ return notFoundStaticAssetResponse(headers);
956
+ }
946
957
  if (!filesystemRouteEligible) {
947
958
  options.clearRequestContext();
948
959
  const headers = new Headers();
@@ -55,6 +55,6 @@ export type NormalizedRscRequest = {
55
55
  * @returns A 400 or 404 Response for invalid or out-of-scope inputs,
56
56
  * or a NormalizedRscRequest for valid requests.
57
57
  */
58
- export declare function normalizeRscRequest(request: Request, basePath: string, allowOutsideBasePath?: boolean): Response | NormalizedRscRequest;
58
+ export declare function normalizeRscRequest(request: Request, basePath: string, allowOutsideBasePath?: boolean, assetPrefix?: string): Response | NormalizedRscRequest;
59
59
  //#endregion
60
60
  export { normalizeMountedSlotsHeader };
@@ -1,3 +1,4 @@
1
+ import { assetPrefixPathname, isNextStaticPath } from "../utils/asset-prefix.js";
1
2
  import { normalizePathnameForRouteMatchStrict } from "../routing/utils.js";
2
3
  import { hasBasePath, stripBasePath } from "../utils/base-path.js";
3
4
  import { NEXT_ROUTER_STATE_TREE_HEADER, NEXT_URL_HEADER, VINEXT_INTERCEPTION_CONTEXT_HEADER, VINEXT_INTERCEPTION_ID_HEADER, VINEXT_MOUNTED_SLOTS_HEADER, VINEXT_RSC_RENDER_MODE_HEADER } from "./app-rsc-vary.js";
@@ -88,7 +89,7 @@ function tryNormalizeComparablePathAndSearch(value, basePath, baseUrl) {
88
89
  * @returns A 400 or 404 Response for invalid or out-of-scope inputs,
89
90
  * or a NormalizedRscRequest for valid requests.
90
91
  */
91
- function normalizeRscRequest(request, basePath, allowOutsideBasePath = false) {
92
+ function normalizeRscRequest(request, basePath, allowOutsideBasePath = false, assetPrefix = "") {
92
93
  const url = new URL(request.url);
93
94
  const protoGuard = guardProtocolRelativeUrl(url.pathname);
94
95
  if (protoGuard) return protoGuard;
@@ -103,7 +104,7 @@ function normalizeRscRequest(request, basePath, allowOutsideBasePath = false) {
103
104
  let hadBasePath = true;
104
105
  if (basePath) {
105
106
  hadBasePath = hasBasePath(requestPathname, basePath);
106
- if (!hadBasePath && !pathname.startsWith("/__vinext/") && !allowOutsideBasePath) return notFoundResponse();
107
+ if (!hadBasePath && !pathname.startsWith("/__vinext/") && !allowOutsideBasePath && !isNextStaticPath(pathname, "", assetPrefixPathname(assetPrefix))) return notFoundResponse();
107
108
  if (hadBasePath) {
108
109
  pathname = stripBasePath(pathname, basePath);
109
110
  requestPathname = stripBasePath(requestPathname, basePath);
@@ -15,7 +15,10 @@ const configHeadersAlreadyApplied = /* @__PURE__ */ new WeakSet();
15
15
  function normalizeExplicitNonCacheablePolicy(headers) {
16
16
  if (!hasExplicitNonCacheableResponsePolicy(headers)) return;
17
17
  const cacheControl = headers.get("Cache-Control");
18
- applyCdnResponseHeaders(headers, { cacheControl: cacheControl && isNonCacheableCacheControl(cacheControl) ? cacheControl : NO_STORE_CACHE_CONTROL });
18
+ applyCdnResponseHeaders(headers, {
19
+ cacheControl: cacheControl && isNonCacheableCacheControl(cacheControl) ? cacheControl : NO_STORE_CACHE_CONTROL,
20
+ browserCacheControl: cacheControl ?? void 0
21
+ });
19
22
  }
20
23
  /** Mark a response whose final target pipeline has already applied config headers. */
21
24
  function markAppRscResponseConfigHeadersApplied(response) {
@@ -1,5 +1,5 @@
1
1
  import { decodeMatchedParams, splitPathSegments, splitPathnameForRouteMatch } from "../routing/utils.js";
2
- import { createAppRouteGraphInterceptionId } from "../routing/app-route-graph.js";
2
+ import { createAppRouteGraphInterceptionId } from "../routing/app-route-ids.js";
3
3
  import { buildRouteTrie, trieMatchRaw } from "../routing/route-trie.js";
4
4
  import { extractRawRoutePatternParams, matchRoutePatternPrefix, matchRoutePatternRaw } from "../routing/route-pattern.js";
5
5
  import { canonicalizeAppPageParams } from "./app-page-segment-state.js";
@@ -2,7 +2,8 @@ import { AppRscRenderMode } from "./app-rsc-render-mode.js";
2
2
  import { ActionRevalidationKind } from "../shims/cache-request-state.js";
3
3
  import { AppRenderErrorContextOverrides } from "./app-rsc-error-handler.js";
4
4
  import { FetchCacheMode } from "../shims/fetch-cache.js";
5
- import { HeadersAccessPhase } from "../shims/headers.js";
5
+ import { HeadersAccessPhase } from "../shims/internal/headers-state.js";
6
+ import "../shims/headers.js";
6
7
  import { ReactFormState } from "react-dom/client";
7
8
  //#region src/server/app-server-action-execution.d.ts
8
9
  type AppPageParams = Record<string, string | string[]>;
@@ -4,7 +4,7 @@ import { isOpenRedirectShaped } from "./open-redirect.js";
4
4
  import { AppElementsWire } from "./app-elements-wire.js";
5
5
  import "./app-elements.js";
6
6
  import { isPprFallbackShellAbortError } from "../shims/ppr-fallback-shell.js";
7
- import { onRenderDynamicLatched } from "../shims/headers.js";
7
+ import { onRenderDynamicLatched } from "../shims/internal/headers-state.js";
8
8
  import { AppRouterContext } from "../shims/internal/app-router-context.js";
9
9
  import { appendAssetDeploymentIdQuery } from "../utils/deployment-id.js";
10
10
  import { withScriptNonce } from "../shims/script-nonce-context.js";
@@ -19,10 +19,10 @@ import { BfcacheIdentityMapContext, ElementsContext, Slot } from "../shims/slot.
19
19
  import { getNextErrorDigest } from "./next-error-digest.js";
20
20
  import { createSsrErrorMetaRenderer } from "./app-ssr-error-meta.js";
21
21
  import { createClientPageSsrSearchParamsSource } from "./app-page-search-params-observation.js";
22
- import { isAppRenderAbortError } from "./app-rsc-errors.js";
22
+ import { isAppRenderAbortError } from "./app-render-abort-error.js";
23
+ import { RSC_FORM_STATE_GLOBAL } from "../client/browser-globals.js";
23
24
  import { createNavigationRuntimeRenderedSearchScript, createNavigationRuntimeRscMetadataScript, createRscEmbedTransform, createTickBufferedTransform, waitAtLeastOneReactRenderTask } from "./app-ssr-stream.js";
24
25
  import { createInitialBfcacheMaps } from "./app-bfcache-identity.js";
25
- import { RSC_FORM_STATE_GLOBAL } from "./app-browser-hydration.js";
26
26
  import { createClientReferencePreloader } from "./app-client-reference-preloader.js";
27
27
  import { runWithRootParamsScope } from "../shims/root-params.js";
28
28
  import { runWithNavigationContext } from "../shims/navigation-state.js";
@@ -1,4 +1,4 @@
1
- import { isRenderDynamicLatched, markDynamicUsage, onRenderDynamicLatched } from "../shims/headers.js";
1
+ import { isRenderDynamicLatched, markDynamicUsage, onRenderDynamicLatched } from "../shims/internal/headers-state.js";
2
2
  import { createSearchParamsGate } from "../shims/search-params-gate.js";
3
3
  //#region src/server/app-ssr-search-params-gate.ts
4
4
  /**
@@ -1,6 +1,6 @@
1
1
  import { createInlineScriptTag, escapeHtmlAttr, htmlTokenListContains, safeJsonStringify } from "./html.js";
2
2
  import { bytesToBase64, concatUint8Arrays } from "./app-rsc-embedded-chunks.js";
3
- import { NAVIGATION_RUNTIME_SYMBOL_DESCRIPTION } from "../client/navigation-runtime.js";
3
+ import { NAVIGATION_RUNTIME_SYMBOL_DESCRIPTION } from "../client/browser-globals.js";
4
4
  //#region src/server/app-ssr-stream.ts
5
5
  const RSC_EMBED_TEXT_BATCH_MAX_LENGTH = 65536;
6
6
  function waitAtLeastOneReactRenderTask() {
@@ -91,7 +91,7 @@ function applyCdnResponseHeaders(headers, input) {
91
91
  if (value === "") continue;
92
92
  headers.set(name, value);
93
93
  }
94
- if (useNextDeployPolicy) headers.set("Cache-Control", BROWSER_REVALIDATE_CACHE_CONTROL);
94
+ if (useNextDeployPolicy) headers.set("Cache-Control", input.browserCacheControl ?? "public, max-age=0, must-revalidate");
95
95
  }
96
96
  /**
97
97
  * Reconcile request-stage policy composed above a reusable response artifact.
@@ -106,19 +106,11 @@ function reconcileCdnResponseHeadersAfterOuterPolicy(headers, outerPolicyHeaders
106
106
  return;
107
107
  }
108
108
  const cacheControl = outerPolicyHeaders.get("cache-control");
109
- if (cacheControl !== null) {
110
- applyCdnResponseHeaders(headers, { cacheControl });
111
- for (const [name, value] of outerPolicyHeaders) {
112
- if (name === "cache-control") continue;
113
- if (isCdnResponsePolicyHeader(name)) headers.set(name, value);
114
- }
115
- return;
116
- }
117
- for (const [name, value] of outerPolicyHeaders) if (isCdnResponsePolicyHeader(name) && isNonCacheableCdnResponsePolicy(name, value)) {
109
+ if (cacheControl !== null) headers.set("Cache-Control", cacheControl);
110
+ for (const [name, value] of outerPolicyHeaders) if (name !== "cache-control" && isCdnResponsePolicyHeader(name) && isNonCacheableCdnResponsePolicy(name, value)) {
118
111
  applyCdnResponseHeaders(headers, { cacheControl: NO_STORE_CACHE_CONTROL });
119
112
  return;
120
113
  }
121
- if (hasExplicitNonCacheableResponsePolicy(outerPolicyHeaders)) applyCdnResponseHeaders(headers, { cacheControl: NO_STORE_CACHE_CONTROL });
122
114
  }
123
115
  /** Apply adapter-owned build identity to an HTML or RSC page response. */
124
116
  function applyCdnResponseIdentityHeaders(response, request) {