vinext 1.0.0 → 1.1.0

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 (263) hide show
  1. package/README.md +72 -1
  2. package/THIRD_PARTY_LICENSES.md +26 -0
  3. package/dist/build/app-page-static-eligibility.d.ts +15 -0
  4. package/dist/build/app-page-static-eligibility.js +82 -0
  5. package/dist/build/lifecycle.js +10 -10
  6. package/dist/build/pages-client-assets-module.js +6 -1
  7. package/dist/build/precompress.js +1 -1
  8. package/dist/build/prerender-paths.js +6 -85
  9. package/dist/build/prerender.d.ts +8 -1
  10. package/dist/build/prerender.js +167 -46
  11. package/dist/build/run-prerender.js +4 -3
  12. package/dist/build/server-entry.d.ts +2 -0
  13. package/dist/build/server-entry.js +7 -1
  14. package/dist/build/server-manifest.d.ts +7 -0
  15. package/dist/build/server-manifest.js +11 -1
  16. package/dist/cache/cache-adapters-virtual.d.ts +7 -1
  17. package/dist/cache/cache-adapters-virtual.js +3 -3
  18. package/dist/client/browser-globals.d.ts +4 -0
  19. package/dist/client/browser-globals.js +5 -0
  20. package/dist/client/navigation-runtime.d.ts +11 -1
  21. package/dist/client/navigation-runtime.js +3 -3
  22. package/dist/config/config-matchers.js +3 -1
  23. package/dist/config/dotenv.js +14 -3
  24. package/dist/config/next-config.d.ts +7 -0
  25. package/dist/config/next-config.js +18 -3
  26. package/dist/entries/app-rsc-entry.d.ts +2 -0
  27. package/dist/entries/app-rsc-entry.js +67 -45
  28. package/dist/index.d.ts +4 -1
  29. package/dist/index.js +200 -100
  30. package/dist/init-cloudflare.d.ts +1 -1
  31. package/dist/init-cloudflare.js +6 -6
  32. package/dist/init-platform.js +1 -1
  33. package/dist/init.js +4 -2
  34. package/dist/plugins/cache-flight-codec.d.ts +19 -0
  35. package/dist/plugins/cache-flight-codec.js +68 -0
  36. package/dist/plugins/commonjs-esm-facade.d.ts +35 -0
  37. package/dist/plugins/commonjs-esm-facade.js +80 -0
  38. package/dist/plugins/commonjs-syntax.d.ts +16 -0
  39. package/dist/plugins/commonjs-syntax.js +22 -0
  40. package/dist/plugins/fonts.d.ts +8 -11
  41. package/dist/plugins/fonts.js +71 -34
  42. package/dist/plugins/ignore-dynamic-requests.d.ts +11 -0
  43. package/dist/plugins/ignore-dynamic-requests.js +54 -3
  44. package/dist/plugins/import-meta-url.js +6 -6
  45. package/dist/plugins/og-asset-ownership.d.ts +2 -0
  46. package/dist/plugins/og-asset-ownership.js +24 -13
  47. package/dist/plugins/og-assets.d.ts +18 -0
  48. package/dist/plugins/og-assets.js +50 -8
  49. package/dist/plugins/og-harfbuzz.js +38 -27
  50. package/dist/plugins/optimize-imports.js +2 -1
  51. package/dist/plugins/require-context.d.ts +1 -0
  52. package/dist/plugins/require-context.js +28 -1
  53. package/dist/plugins/scan-build-css.d.ts +12 -0
  54. package/dist/plugins/scan-build-css.js +39 -0
  55. package/dist/plugins/strip-server-exports.d.ts +2 -0
  56. package/dist/plugins/strip-server-exports.js +3 -1
  57. package/dist/plugins/transform-result.d.ts +18 -0
  58. package/dist/plugins/transform-result.js +23 -2
  59. package/dist/plugins/typeof-window.d.ts +10 -0
  60. package/dist/plugins/typeof-window.js +33 -9
  61. package/dist/routing/app-route-graph.d.ts +0 -1
  62. package/dist/routing/app-route-graph.js +2 -4
  63. package/dist/routing/app-route-ids.d.ts +3 -0
  64. package/dist/routing/app-route-ids.js +6 -0
  65. package/dist/routing/file-matcher.d.ts +1 -0
  66. package/dist/routing/file-matcher.js +1 -1
  67. package/dist/server/api-handler.js +17 -7
  68. package/dist/server/app-bfcache-id.d.ts +1 -0
  69. package/dist/server/app-bfcache-id.js +7 -1
  70. package/dist/server/app-bfcache-identity.js +1 -2
  71. package/dist/server/app-browser-entry.js +15 -9
  72. package/dist/server/app-browser-history-controller.d.ts +2 -0
  73. package/dist/server/app-browser-history-controller.js +8 -0
  74. package/dist/server/app-browser-hydration.d.ts +1 -1
  75. package/dist/server/app-browser-hydration.js +2 -2
  76. package/dist/server/app-browser-interception-context.js +26 -2
  77. package/dist/server/app-browser-navigation-controller.d.ts +7 -1
  78. package/dist/server/app-browser-navigation-controller.js +94 -11
  79. package/dist/server/app-browser-state.js +1 -1
  80. package/dist/server/app-browser-stream.d.ts +1 -1
  81. package/dist/server/app-fallback-renderer.d.ts +2 -0
  82. package/dist/server/app-fallback-renderer.js +1 -0
  83. package/dist/server/app-history-state.d.ts +3 -1
  84. package/dist/server/app-history-state.js +9 -5
  85. package/dist/server/app-middleware.js +2 -1
  86. package/dist/server/app-optimistic-routing.js +1 -1
  87. package/dist/server/app-page-boundary-render.d.ts +5 -0
  88. package/dist/server/app-page-boundary-render.js +6 -4
  89. package/dist/server/app-page-cache-finalizer.d.ts +11 -0
  90. package/dist/server/app-page-cache-finalizer.js +41 -7
  91. package/dist/server/app-page-cache-render.d.ts +18 -0
  92. package/dist/server/app-page-cache-render.js +65 -44
  93. package/dist/server/app-page-cache.d.ts +5 -0
  94. package/dist/server/app-page-cache.js +27 -7
  95. package/dist/server/app-page-dispatch.d.ts +9 -1
  96. package/dist/server/app-page-dispatch.js +47 -30
  97. package/dist/server/app-page-element-builder.d.ts +7 -0
  98. package/dist/server/app-page-element-builder.js +27 -42
  99. package/dist/server/app-page-execution.d.ts +15 -12
  100. package/dist/server/app-page-execution.js +30 -40
  101. package/dist/server/app-page-head.d.ts +5 -0
  102. package/dist/server/app-page-head.js +9 -3
  103. package/dist/server/app-page-probe.d.ts +0 -109
  104. package/dist/server/app-page-probe.js +3 -136
  105. package/dist/server/app-page-render-identity.d.ts +0 -1
  106. package/dist/server/app-page-render-identity.js +1 -1
  107. package/dist/server/app-page-render-observation.js +2 -2
  108. package/dist/server/app-page-render.d.ts +13 -5
  109. package/dist/server/app-page-render.js +219 -118
  110. package/dist/server/app-page-request.d.ts +0 -1
  111. package/dist/server/app-page-request.js +1 -2
  112. package/dist/server/app-page-response.d.ts +4 -3
  113. package/dist/server/app-page-response.js +4 -3
  114. package/dist/server/app-page-route-wiring.d.ts +17 -5
  115. package/dist/server/app-page-route-wiring.js +55 -33
  116. package/dist/server/app-page-rsc-render-status.d.ts +48 -0
  117. package/dist/server/app-page-rsc-render-status.js +54 -0
  118. package/dist/server/app-page-search-params-observation.js +1 -1
  119. package/dist/server/app-page-stream.d.ts +15 -8
  120. package/dist/server/app-page-stream.js +7 -1
  121. package/dist/server/app-page-tracing.js +2 -1
  122. package/dist/server/app-pages-bridge.js +3 -2
  123. package/dist/server/app-render-abort-error.d.ts +3 -0
  124. package/dist/server/app-render-abort-error.js +8 -0
  125. package/dist/server/app-request-stage-dispatch.js +1 -1
  126. package/dist/server/app-request-stage-independent-entry.js +8 -11
  127. package/dist/server/app-response-header-provenance.d.ts +2 -0
  128. package/dist/server/app-response-header-provenance.js +10 -4
  129. package/dist/server/app-route-handler-cache.d.ts +2 -1
  130. package/dist/server/app-route-handler-cache.js +11 -7
  131. package/dist/server/app-route-handler-dispatch.js +11 -4
  132. package/dist/server/app-route-handler-execution.d.ts +9 -1
  133. package/dist/server/app-route-handler-execution.js +28 -13
  134. package/dist/server/app-route-handler-policy.js +2 -2
  135. package/dist/server/app-route-handler-response.d.ts +1 -1
  136. package/dist/server/app-route-handler-response.js +14 -5
  137. package/dist/server/app-router-entry.d.ts +2 -1
  138. package/dist/server/app-router-entry.js +8 -12
  139. package/dist/server/app-rsc-errors.d.ts +0 -1
  140. package/dist/server/app-rsc-errors.js +2 -6
  141. package/dist/server/app-rsc-handler.d.ts +5 -0
  142. package/dist/server/app-rsc-handler.js +229 -102
  143. package/dist/server/app-rsc-request-normalization.d.ts +4 -2
  144. package/dist/server/app-rsc-request-normalization.js +7 -4
  145. package/dist/server/app-rsc-response-finalizer.js +4 -1
  146. package/dist/server/app-rsc-response-stage.d.ts +1 -1
  147. package/dist/server/app-rsc-response-stage.js +6 -4
  148. package/dist/server/app-rsc-route-matching.d.ts +9 -1
  149. package/dist/server/app-rsc-route-matching.js +37 -20
  150. package/dist/server/app-server-action-execution.d.ts +2 -1
  151. package/dist/server/app-server-action-execution.js +1 -1
  152. package/dist/server/app-ssr-entry.d.ts +3 -2
  153. package/dist/server/app-ssr-entry.js +9 -7
  154. package/dist/server/app-ssr-search-params-gate.js +1 -1
  155. package/dist/server/app-ssr-stream.d.ts +6 -1
  156. package/dist/server/app-ssr-stream.js +35 -16
  157. package/dist/server/app-worker-stages.d.ts +2 -2
  158. package/dist/server/app-worker-stages.js +3 -3
  159. package/dist/server/cache-control.js +3 -11
  160. package/dist/server/cacheability-request.js +56 -52
  161. package/dist/server/config-headers.js +3 -1
  162. package/dist/server/dev-server.js +23 -5
  163. package/dist/server/headers.d.ts +16 -0
  164. package/dist/server/headers.js +19 -1
  165. package/dist/server/http-error-responses.js +1 -0
  166. package/dist/server/image-optimization.d.ts +16 -0
  167. package/dist/server/image-optimization.js +26 -6
  168. package/dist/server/isr-cache.d.ts +2 -0
  169. package/dist/server/isr-cache.js +8 -3
  170. package/dist/server/metadata-route-response.js +94 -37
  171. package/dist/server/middleware-matcher-pattern.js +8 -4
  172. package/dist/server/middleware-response-headers.js +2 -0
  173. package/dist/server/multi-stage.d.ts +8 -0
  174. package/dist/server/navigation-planner.js +1 -1
  175. package/dist/server/node-response-signal.d.ts +16 -0
  176. package/dist/server/node-response-signal.js +26 -0
  177. package/dist/server/open-redirect.d.ts +47 -0
  178. package/dist/server/open-redirect.js +74 -1
  179. package/dist/server/pages-api-route.js +8 -2
  180. package/dist/server/pages-asset-tags.d.ts +1 -0
  181. package/dist/server/pages-asset-tags.js +73 -22
  182. package/dist/server/pages-client-assets.d.ts +2 -0
  183. package/dist/server/pages-page-data.d.ts +6 -1
  184. package/dist/server/pages-page-data.js +71 -65
  185. package/dist/server/pages-page-handler.js +50 -15
  186. package/dist/server/pages-page-response.js +3 -1
  187. package/dist/server/pages-request-pipeline.d.ts +2 -1
  188. package/dist/server/pages-request-pipeline.js +20 -5
  189. package/dist/server/pages-request-stage-entry.js +14 -8
  190. package/dist/server/prerender-manifest.d.ts +6 -0
  191. package/dist/server/prerender-manifest.js +1 -1
  192. package/dist/server/prod-server.d.ts +8 -7
  193. package/dist/server/prod-server.js +152 -78
  194. package/dist/server/request-pipeline.d.ts +20 -8
  195. package/dist/server/request-pipeline.js +21 -7
  196. package/dist/server/response-compression.d.ts +43 -0
  197. package/dist/server/response-compression.js +111 -0
  198. package/dist/server/response-stage-cacheability.js +1 -1
  199. package/dist/server/seed-cache.js +10 -7
  200. package/dist/server/socket-error-backstop.d.ts +14 -0
  201. package/dist/server/socket-error-backstop.js +27 -4
  202. package/dist/server/worker-revalidation-context.d.ts +2 -1
  203. package/dist/server/worker-revalidation-context.js +1 -0
  204. package/dist/server/workers-tracing.d.ts +17 -0
  205. package/dist/server/workers-tracing.js +48 -8
  206. package/dist/shims/cache-adapter-instantiate.d.ts +50 -0
  207. package/dist/shims/cache-adapter-instantiate.js +118 -0
  208. package/dist/shims/cache-callable-runtime.d.ts +2 -40
  209. package/dist/shims/cache-callable-runtime.js +50 -168
  210. package/dist/shims/cache-flight-arguments.d.ts +22 -0
  211. package/dist/shims/cache-flight-arguments.js +56 -0
  212. package/dist/shims/cache-request-state.d.ts +18 -14
  213. package/dist/shims/cache-request-state.js +33 -21
  214. package/dist/shims/cache-runtime.d.ts +6 -19
  215. package/dist/shims/cache-runtime.js +168 -226
  216. package/dist/shims/cache.d.ts +3 -2
  217. package/dist/shims/cache.js +8 -5
  218. package/dist/shims/cacheability-classification.d.ts +8 -1
  219. package/dist/shims/cacheability-classification.js +2 -2
  220. package/dist/shims/cdn-cache.d.ts +10 -1
  221. package/dist/shims/cdn-cache.js +16 -9
  222. package/dist/shims/error-boundary-navigation.d.ts +7 -0
  223. package/dist/shims/error-boundary-navigation.js +19 -1
  224. package/dist/shims/error-boundary.d.ts +10 -10
  225. package/dist/shims/error-boundary.js +26 -7
  226. package/dist/shims/error.d.ts +4 -18
  227. package/dist/shims/error.js +17 -10
  228. package/dist/shims/error.react-server.d.ts +4 -6
  229. package/dist/shims/error.react-server.js +4 -1
  230. package/dist/shims/fetch-cache.d.ts +6 -0
  231. package/dist/shims/fetch-cache.js +23 -4
  232. package/dist/shims/form.js +1 -1
  233. package/dist/shims/headers.d.ts +19 -69
  234. package/dist/shims/headers.js +82 -183
  235. package/dist/shims/internal/app-page-props-cache-key.d.ts +5 -2
  236. package/dist/shims/internal/app-page-props-cache-key.js +24 -15
  237. package/dist/shims/internal/cache-context-accessor.d.ts +16 -0
  238. package/dist/shims/internal/cache-context-accessor.js +15 -0
  239. package/dist/shims/internal/headers-state.d.ts +73 -0
  240. package/dist/shims/internal/headers-state.js +157 -0
  241. package/dist/shims/metadata.js +3 -3
  242. package/dist/shims/navigation-errors.d.ts +6 -0
  243. package/dist/shims/navigation-errors.js +11 -1
  244. package/dist/shims/navigation.d.ts +7 -0
  245. package/dist/shims/navigation.js +16 -6
  246. package/dist/shims/request-context.d.ts +9 -0
  247. package/dist/shims/request-state-types.d.ts +2 -1
  248. package/dist/shims/root-params.js +1 -1
  249. package/dist/shims/server.js +52 -2
  250. package/dist/shims/thenable-params.d.ts +4 -0
  251. package/dist/shims/thenable-params.js +25 -3
  252. package/dist/shims/unified-request-context.d.ts +1 -1
  253. package/dist/shims/unified-request-context.js +1 -0
  254. package/dist/utils/encode-cache-tag.d.ts +1 -0
  255. package/dist/utils/encode-cache-tag.js +11 -1
  256. package/dist/utils/mdx-scan.d.ts +5 -0
  257. package/dist/utils/mdx-scan.js +8 -1
  258. package/dist/utils/regex-safety.d.ts +10 -0
  259. package/dist/utils/regex-safety.js +70 -18
  260. package/dist/utils/vite-cli-invocation.js +8 -1
  261. package/package.json +8 -4
  262. package/dist/server/metadata-route-cache-policy.d.ts +0 -5
  263. package/dist/server/metadata-route-cache-policy.js +0 -6
package/README.md CHANGED
@@ -158,6 +158,42 @@ Environment variables: `PORT` (default `3000`), `HOST` (default `0.0.0.0`).
158
158
 
159
159
  > **Note:** Next.js standalone uses `HOSTNAME` for the bind address, but vinext uses `HOST` to avoid collision with the system-set `HOSTNAME` variable on Linux. Update your deployment config accordingly.
160
160
 
161
+ #### Custom standalone entries
162
+
163
+ The generated `server.js` is a small wrapper around `startProdServer` from `vinext/server/prod-server`. To control where the server loads the build output from, write your own entry and call `startProdServer` directly. All options are optional:
164
+
165
+ | Option | Default | Description |
166
+ | ----------------- | ---------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
167
+ | `port` | `PORT` env var, otherwise `3000` | Port to listen on. |
168
+ | `host` | `"0.0.0.0"` | Address to bind to. Unlike the generated `server.js`, `startProdServer` doesn't read `HOST`, so pass `process.env.HOST` yourself if you need it. |
169
+ | `outDir` | `dist`, resolved against the current directory | Build output directory containing `client/` and `server/`. Relative paths resolve against the current directory. In standalone output, this is `dist/standalone/dist`. |
170
+ | `serverDir` | `<outDir>/server` | Directory containing the server bundles, manifests, and prerendered output. |
171
+ | `rscEntryPath` | `<serverDir>/index.js` | App Router server entry. If this file exists, the server runs in App Router mode. |
172
+ | `serverEntryPath` | `<serverDir>/entry.js` | Pages Router server entry. Used when there's no App Router entry. |
173
+ | `noCompression` | `false` | Disable response compression. |
174
+
175
+ `ProdServerOptions` also has `purpose` and `silent`, which vinext uses for its own build-time servers. Leave them unset. The returned promise resolves to `{ server, port }` once the server is listening.
176
+
177
+ **Compiled single-file binaries.** A `bun build --compile` binary can't use the generated `server.js`. Bun fixes `import.meta.dirname` when it compiles the binary, so `join(import.meta.dirname, "dist")` doesn't point at the directory the binary runs from. Depending on the Bun version, it points at the build machine's path or at Bun's embedded `/$bunfs/root`. Resolve `outDir` from the executable's location instead:
178
+
179
+ ```js
180
+ // server-bin.mjs, in your project root
181
+ import path from "node:path";
182
+ import { startProdServer } from "vinext/server/prod-server";
183
+
184
+ await startProdServer({
185
+ port: Number.parseInt(process.env.PORT ?? "3000", 10),
186
+ host: process.env.HOST ?? "0.0.0.0",
187
+ outDir: path.join(path.dirname(process.execPath), "dist"),
188
+ });
189
+ ```
190
+
191
+ ```bash
192
+ bun build --compile --compile-autoload-package-json server-bin.mjs --outfile dist/standalone/server
193
+ ```
194
+
195
+ Keep the entry outside `dist/standalone`: each build deletes and recreates that directory. Compile after `vite build`, then ship the whole `dist/standalone` directory, because the `server` binary needs the `dist/` and `node_modules/` directories next to it. The server bundles in `dist/server` still import their dependencies from `node_modules` at runtime. `--compile-autoload-package-json` lets the binary read package `exports` and `main` fields when it resolves them. Under plain Node, `process.execPath` is the Node binary, so use this entry only for compiled builds.
196
+
161
197
  ### Starting a new vinext project
162
198
 
163
199
  Use `create-vinext-app` for new projects. It creates a TypeScript App Router project
@@ -792,7 +828,7 @@ their `env` binding lookups) are instantiated lazily on the first request.
792
828
 
793
829
  Registration is wired into **every router and runtime** — App Router and Pages Router, on Cloudflare Workers as well as the Node.js server (`vinext start`) and dev. It self-guards (instantiated once per isolate) and is resilient: if an adapter can't initialize on a given runtime (e.g. a KV binding doesn't exist on the Node server), vinext logs a warning and falls back to the default handler instead of failing requests.
794
830
 
795
- To write your own adapter, point a slot at any module by path and default-export a factory that receives `{ env, options }` at runtime and returns a data-cache `CacheHandler` (or a CDN adapter):
831
+ To write your own adapter, point a slot at any module by path. Its default export receives one `{ env, options }` argument at runtime and produces a data-cache `CacheHandler` (or a CDN adapter):
796
832
 
797
833
  ```ts
798
834
  vinext({
@@ -805,6 +841,41 @@ vinext({
805
841
  });
806
842
  ```
807
843
 
844
+ The default export can be a factory or a class:
845
+
846
+ ```ts
847
+ // my-adapter.js: a factory
848
+ export default ({ env, options }) => ({
849
+ async get(key) {
850
+ /* … */
851
+ },
852
+ async set(key, data) {
853
+ /* … */
854
+ },
855
+ async revalidateTag(tags) {
856
+ /* … */
857
+ },
858
+ });
859
+
860
+ // my-adapter.js: or a class
861
+ export default class MyAdapter {
862
+ constructor({ env, options }) {
863
+ /* … */
864
+ }
865
+ async get(key) {
866
+ /* … */
867
+ }
868
+ async set(key, data) {
869
+ /* … */
870
+ }
871
+ async revalidateTag(tags) {
872
+ /* … */
873
+ }
874
+ }
875
+ ```
876
+
877
+ vinext invokes class syntax with `new` and calls any other function, so existing factories keep plain-call semantics. A constructor that isn't class syntax (an ES5-compiled, bound, or Proxy-wrapped class) can't be told apart from a factory, so export a factory that constructs it: `export default (args) => new MyAdapter(args)`. The result must be the adapter itself, not a Promise. A data adapter implements `get`, `set`, and `revalidateTag`; a CDN adapter also implements `buildResponseHeaders` and sets `ownsBackgroundRevalidation` to a boolean. If the export isn't a function or the result is missing a member, vinext logs a warning naming the slot and what's wrong, then keeps the default handler.
878
+
808
879
  ## What's NOT supported (and won't be)
809
880
 
810
881
  These are intentional exclusions. For things that are missing today but on the roadmap, see [Known gaps we're working on](#known-gaps-were-working-on) above.
@@ -23,3 +23,29 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23
23
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24
24
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25
25
  SOFTWARE.
26
+
27
+ ## dotenv (parser adapted from version 16.3.1)
28
+
29
+ Copyright (c) 2015, Scott Motte
30
+ All rights reserved.
31
+
32
+ Redistribution and use in source and binary forms, with or without
33
+ modification, are permitted provided that the following conditions are met:
34
+
35
+ - Redistributions of source code must retain the above copyright notice, this
36
+ list of conditions and the following disclaimer.
37
+
38
+ - Redistributions in binary form must reproduce the above copyright notice,
39
+ this list of conditions and the following disclaimer in the documentation
40
+ and/or other materials provided with the distribution.
41
+
42
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
43
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
44
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
45
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
46
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
47
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
48
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
49
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
50
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
51
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,15 @@
1
+ import { AppRoute } from "../routing/app-route-graph.js";
2
+ //#region src/build/app-page-static-eligibility.d.ts
3
+ /**
4
+ * Whether Next.js classifies an App page route as static or SSG, read from its
5
+ * layout, page and parallel-slot sources with the helpers dispatch applies to
6
+ * the loaded modules. Only such a route has listed paths.
7
+ *
8
+ * An MDX source read without the MDX parser has unknown exports, so its route
9
+ * is "unreadable". Its paths are still listed: the built runtime reads the real
10
+ * exports and never stores a route that isn't static, while an unlisted path's
11
+ * render failure would be dropped instead of failing. But no probe renders an
12
+ * unreadable route's fallback, so it never certifies one.
13
+ */
14
+ export declare function classifyAppPageRouteStaticEligibility(route: AppRoute, readMdxEsm: ((source: string) => string) | null): "eligible" | "ineligible" | "unreadable";
15
+ //#endregion
@@ -0,0 +1,82 @@
1
+ import { extractExportConstNumber, extractExportConstString, hasRuntimeExportedName } from "./report.js";
2
+ import { collectAppPageStaticGenerationRuntimes, hasAppPageGenerateStaticParamsAtLastDynamicSegment, isAppPageStaticEligible, isEdgeRuntime, resolveAppPageSegmentConfig, resolveAppPageStaticGenerationRuntime } from "../server/app-segment-config.js";
3
+ import fs from "node:fs";
4
+ //#region src/build/app-page-static-eligibility.ts
5
+ /**
6
+ * Whether Next.js classifies an App page route as static or SSG, read from its
7
+ * layout, page and parallel-slot sources with the helpers dispatch applies to
8
+ * the loaded modules. Only such a route has listed paths.
9
+ *
10
+ * An MDX source read without the MDX parser has unknown exports, so its route
11
+ * is "unreadable". Its paths are still listed: the built runtime reads the real
12
+ * exports and never stores a route that isn't static, while an unlisted path's
13
+ * render failure would be dropped instead of failing. But no probe renders an
14
+ * unreadable route's fallback, so it never certifies one.
15
+ */
16
+ function classifyAppPageRouteStaticEligibility(route, readMdxEsm) {
17
+ let unreadable = false;
18
+ const readSegmentConfig = (filePath) => {
19
+ if (!filePath) return null;
20
+ let code = fs.readFileSync(filePath, "utf8");
21
+ if (filePath.toLowerCase().endsWith(".mdx")) {
22
+ let esm = null;
23
+ try {
24
+ esm = readMdxEsm?.(code) ?? null;
25
+ } catch {}
26
+ unreadable ||= esm === null;
27
+ code = esm ?? "";
28
+ }
29
+ const dynamic = extractExportConstString(code, "dynamic");
30
+ const revalidate = extractExportConstNumber(code, "revalidate");
31
+ const runtime = extractExportConstString(code, "runtime");
32
+ return {
33
+ ...dynamic === null ? {} : { dynamic },
34
+ ...hasRuntimeExportedName(code, "generateStaticParams") ? { generateStaticParams() {} } : {},
35
+ ...revalidate === null ? {} : { revalidate },
36
+ ...runtime === null ? {} : { runtime }
37
+ };
38
+ };
39
+ const layouts = route.layouts.map(readSegmentConfig);
40
+ const page = readSegmentConfig(route.pagePath);
41
+ const parallelBranches = route.parallelSlots.map((slot) => ({
42
+ configLayouts: (slot.configLayoutPaths ?? []).map(readSegmentConfig),
43
+ configLayoutTreePositions: slot.configLayoutTreePositions ?? [],
44
+ isDefault: !slot.pagePath,
45
+ layout: readSegmentConfig(slot.layoutPath),
46
+ name: slot.name,
47
+ ownerTreePosition: slot.ownerTreePosition ?? null,
48
+ page: readSegmentConfig(slot.pagePath ?? slot.defaultPath),
49
+ routeSegments: slot.routeSegments
50
+ }));
51
+ if (unreadable) return "unreadable";
52
+ const segmentConfig = resolveAppPageSegmentConfig({
53
+ layouts,
54
+ layoutTreePositions: route.layoutTreePositions,
55
+ page,
56
+ parallelBranches,
57
+ routeSegments: route.routeSegments
58
+ });
59
+ return isAppPageStaticEligible({
60
+ dynamicConfig: segmentConfig.dynamicConfig,
61
+ hasGenerateStaticParams: hasAppPageGenerateStaticParamsAtLastDynamicSegment({
62
+ childrenSlot: route.childrenSlot ?? null,
63
+ layouts,
64
+ layoutTreePositions: route.layoutTreePositions,
65
+ page,
66
+ parallelBranches,
67
+ routeSegments: route.routeSegments
68
+ }),
69
+ isDynamicRoute: route.isDynamic,
70
+ isStaticGenerationEdgeRuntime: isEdgeRuntime(resolveAppPageStaticGenerationRuntime(collectAppPageStaticGenerationRuntimes({
71
+ childrenSlot: route.childrenSlot ?? null,
72
+ layouts,
73
+ layoutTreePositions: route.layoutTreePositions,
74
+ page,
75
+ parallelBranches,
76
+ routeSegments: route.routeSegments
77
+ }))),
78
+ revalidateSeconds: segmentConfig.revalidateSeconds
79
+ }) ? "eligible" : "ineligible";
80
+ }
81
+ //#endregion
82
+ export { classifyAppPageRouteStaticEligibility };
@@ -141,16 +141,6 @@ async function finalizeBuild(builder, context) {
141
141
  __VINEXT_SHARED_RSC_COMPATIBILITY_ID: context.rscCompatibilityId
142
142
  }, () => runWithPreviewBuildCredentials(() => buildHybridPagesBundle(builder, context), context.previewBuildCredentials));
143
143
  if (context.deferPostBuild) return;
144
- if (context.nextConfig.output === "standalone") {
145
- const { emitStandaloneOutput } = await import("./standalone.js");
146
- const standalone = emitStandaloneOutput({
147
- root: context.root,
148
- outDir: path.resolve(context.root, "dist")
149
- });
150
- console.log(` Generated standalone output in ${path.relative(context.root, standalone.standaloneDir)}/`);
151
- console.log(" Start it with: node dist/standalone/server.js\n");
152
- return;
153
- }
154
144
  const prerenderDecision = resolveVinextPrerenderDecision({
155
145
  prerenderAllFlag: context.prerenderAll,
156
146
  vinextPrerenderConfig: context.prerenderConfig,
@@ -187,6 +177,16 @@ async function finalizeBuild(builder, context) {
187
177
  routeRootConfig: buildOutput
188
178
  });
189
179
  }
180
+ if (context.nextConfig.output === "standalone") {
181
+ const { emitStandaloneOutput } = await import("./standalone.js");
182
+ const standalone = emitStandaloneOutput({
183
+ root: context.root,
184
+ outDir: path.resolve(context.root, "dist")
185
+ });
186
+ console.log(` Generated standalone output in ${path.relative(context.root, standalone.standaloneDir)}/`);
187
+ console.log(" Start it with: node dist/standalone/server.js\n");
188
+ return;
189
+ }
190
190
  const { printBuildReport } = await import("./report.js");
191
191
  await printBuildReport({
192
192
  root: context.root,
@@ -1,9 +1,14 @@
1
1
  import path from "../deps/.pnpm/pathslash@0.1.0/deps/pathslash/dist/index.js";
2
+ import { getSharedChunkFiles } from "../server/pages-asset-tags.js";
2
3
  import fs from "node:fs";
3
4
  //#region src/build/pages-client-assets-module.ts
4
5
  const PAGES_CLIENT_ASSETS_MODULE = "vinext-client-assets.js";
5
6
  function buildPagesClientAssetsModule(assets) {
6
- return `export default ${JSON.stringify(assets)};\n`;
7
+ const prepared = assets.ssrManifest ? {
8
+ ...assets,
9
+ sharedChunks: getSharedChunkFiles(assets.ssrManifest)
10
+ } : assets;
11
+ return `export default ${JSON.stringify(prepared)};\n`;
7
12
  }
8
13
  function writePagesClientAssetsModuleIfMissing(outputDir, moduleSource) {
9
14
  const outputPath = path.join(outputDir, PAGES_CLIENT_ASSETS_MODULE);
@@ -3,9 +3,9 @@ import { ASSET_PREFIX_URL_DIR } from "../utils/asset-prefix.js";
3
3
  import { isPrecompressedVariantBeneficial } from "../utils/precompressed-variant.js";
4
4
  import fsp from "node:fs/promises";
5
5
  import { randomUUID } from "node:crypto";
6
- import { promisify } from "node:util";
7
6
  import os from "node:os";
8
7
  import zlib from "node:zlib";
8
+ import { promisify } from "node:util";
9
9
  //#region src/build/precompress.ts
10
10
  /**
11
11
  * Build-time precompression for hashed static assets.
@@ -10,18 +10,19 @@ import { apiRouter, matchRoute, pagesRouter } from "../routing/pages-router.js";
10
10
  import "../server/headers.js";
11
11
  import { matchesMiddlewarePathname } from "../server/middleware-matcher.js";
12
12
  import { extractLocaleFromUrl, normalizeDefaultLocalePathname } from "../server/pages-i18n.js";
13
- import { classifyAppRoute, classifyAppRouteHandler, classifyPagesRoute, extractExportConstNumber, extractExportConstString, extractMiddlewareMatcherConfig, getAppRouteRenderEntryPath, hasRuntimeExportedName } from "./report.js";
13
+ import { classifyAppRoute, classifyAppRouteHandler, classifyPagesRoute, extractExportConstString, extractMiddlewareMatcherConfig, getAppRouteRenderEntryPath } from "./report.js";
14
14
  import { normalizeStaticPathname, normalizeStaticPathsEntry } from "../routing/route-pattern.js";
15
15
  import { buildPagesDataHref } from "../shims/internal/pages-data-url.js";
16
16
  import { normalizePathTrailingSlash } from "../shims/url-utils.js";
17
+ import { resolveAppPageDynamicConfig } from "../server/app-segment-config.js";
18
+ import { classifyAppPageRouteStaticEligibility } from "./app-page-static-eligibility.js";
17
19
  import { pagesRouteHasPriorityOverAppRoute } from "../server/hybrid-route-priority.js";
18
20
  import { readPrerenderSecret } from "./server-manifest.js";
19
21
  import { loadMdxEsmReader } from "../utils/mdx-scan.js";
20
22
  import { startProdServer } from "../server/prod-server.js";
21
23
  import { enterPrerenderPhase } from "./prerender-phase.js";
22
- import { buildUrlFromParams, layoutOnlyParamSets, resolveParentParams, routeStaticParamSets, validateDiscoveredParams } from "./prerender.js";
23
- import { collectAppPageStaticGenerationRuntimes, hasAppPageGenerateStaticParamsAtLastDynamicSegment, isAppPageStaticEligible, isEdgeRuntime, resolveAppPageDynamicConfig, resolveAppPageSegmentConfig, resolveAppPageStaticGenerationRuntime } from "../server/app-segment-config.js";
24
- import { resolveBuiltRscEntryPath } from "./server-entry.js";
24
+ import { buildUrlFromParams, layoutOnlyParamSets, localizePagesPath, resolveParentParams, routeStaticParamSets, validateDiscoveredParams } from "./prerender.js";
25
+ import { resolveBuiltPagesEntryPath, resolveBuiltRscEntryPath } from "./server-entry.js";
25
26
  import fs from "node:fs";
26
27
  //#region src/build/prerender-paths.ts
27
28
  const PRERENDER_PATH_DISCOVERY_ENV = "__VINEXT_PRERENDER_PATH_DISCOVERY";
@@ -325,10 +326,6 @@ async function resolvePagesWarmRouteMetadata(options) {
325
326
  routePatterns
326
327
  };
327
328
  }
328
- function localizePagesPath(pathname, locale, i18n) {
329
- if (!i18n || !locale || locale === i18n.defaultLocale) return pathname;
330
- return pathname === "/" ? `/${locale}` : `/${locale}${pathname}`;
331
- }
332
329
  /**
333
330
  * Next.js data URLs always carry the locale segment, including the default
334
331
  * locale that is omitted from the corresponding public HTML pathname.
@@ -355,82 +352,6 @@ function extractPagesStaticPathLocale(url, i18n) {
355
352
  url: `${rest || "/"}${query}`
356
353
  };
357
354
  }
358
- /**
359
- * Whether Next.js classifies an App page route as static or SSG, read from its
360
- * layout, page and parallel-slot sources with the helpers dispatch applies to
361
- * the loaded modules. Only such a route has listed paths.
362
- *
363
- * An MDX source read without the MDX parser has unknown exports, so its route
364
- * is "unreadable". Its paths are still listed: the built runtime reads the real
365
- * exports and never stores a route that isn't static, while an unlisted path's
366
- * render failure would be dropped instead of failing. But no probe renders an
367
- * unreadable route's fallback, so it never certifies one.
368
- */
369
- function classifyAppPageRouteStaticEligibility(route, readMdxEsm) {
370
- let unreadable = false;
371
- const readSegmentConfig = (filePath) => {
372
- if (!filePath) return null;
373
- let code = fs.readFileSync(filePath, "utf8");
374
- if (filePath.toLowerCase().endsWith(".mdx")) {
375
- let esm = null;
376
- try {
377
- esm = readMdxEsm?.(code) ?? null;
378
- } catch {}
379
- unreadable ||= esm === null;
380
- code = esm ?? "";
381
- }
382
- const dynamic = extractExportConstString(code, "dynamic");
383
- const revalidate = extractExportConstNumber(code, "revalidate");
384
- const runtime = extractExportConstString(code, "runtime");
385
- return {
386
- ...dynamic === null ? {} : { dynamic },
387
- ...hasRuntimeExportedName(code, "generateStaticParams") ? { generateStaticParams() {} } : {},
388
- ...revalidate === null ? {} : { revalidate },
389
- ...runtime === null ? {} : { runtime }
390
- };
391
- };
392
- const layouts = route.layouts.map(readSegmentConfig);
393
- const page = readSegmentConfig(route.pagePath);
394
- const parallelBranches = route.parallelSlots.map((slot) => ({
395
- configLayouts: (slot.configLayoutPaths ?? []).map(readSegmentConfig),
396
- configLayoutTreePositions: slot.configLayoutTreePositions ?? [],
397
- isDefault: !slot.pagePath,
398
- layout: readSegmentConfig(slot.layoutPath),
399
- name: slot.name,
400
- ownerTreePosition: slot.ownerTreePosition ?? null,
401
- page: readSegmentConfig(slot.pagePath ?? slot.defaultPath),
402
- routeSegments: slot.routeSegments
403
- }));
404
- if (unreadable) return "unreadable";
405
- const segmentConfig = resolveAppPageSegmentConfig({
406
- layouts,
407
- layoutTreePositions: route.layoutTreePositions,
408
- page,
409
- parallelBranches,
410
- routeSegments: route.routeSegments
411
- });
412
- return isAppPageStaticEligible({
413
- dynamicConfig: segmentConfig.dynamicConfig,
414
- hasGenerateStaticParams: hasAppPageGenerateStaticParamsAtLastDynamicSegment({
415
- childrenSlot: route.childrenSlot ?? null,
416
- layouts,
417
- layoutTreePositions: route.layoutTreePositions,
418
- page,
419
- parallelBranches,
420
- routeSegments: route.routeSegments
421
- }),
422
- isDynamicRoute: route.isDynamic,
423
- isStaticGenerationEdgeRuntime: isEdgeRuntime(resolveAppPageStaticGenerationRuntime(collectAppPageStaticGenerationRuntimes({
424
- childrenSlot: route.childrenSlot ?? null,
425
- layouts,
426
- layoutTreePositions: route.layoutTreePositions,
427
- page,
428
- parallelBranches,
429
- routeSegments: route.routeSegments
430
- }))),
431
- revalidateSeconds: segmentConfig.revalidateSeconds
432
- }) ? "eligible" : "ineligible";
433
- }
434
355
  /** Keys a path an App page route lists by the route and the pathname together. */
435
356
  function appPageListingKey(routePattern, pathname) {
436
357
  return `${routePattern}\0${pathname}`;
@@ -795,7 +716,7 @@ async function discoverPrerenderPathManifest(options) {
795
716
  const rscBundlePath = options.rscBundlePath ?? defaultRscBundlePath;
796
717
  const relativeRscEntryPath = path.relative(configuredRscServerDir, rscBundlePath);
797
718
  const rscServerDir = !relativeRscEntryPath.startsWith("../") && !path.isAbsolute(relativeRscEntryPath) ? configuredRscServerDir : path.dirname(rscBundlePath);
798
- const pagesBundlePath = options.pagesBundlePath ?? path.join(root, "dist", "server", "entry.js");
719
+ const pagesBundlePath = options.pagesBundlePath ?? resolveBuiltPagesEntryPath(path.resolve(root, options.routeRootConfig?.ssrOutDir ?? path.join("dist", "server")));
799
720
  const bundleServerDir = fs.existsSync(rscBundlePath) ? rscServerDir : path.dirname(pagesBundlePath);
800
721
  const manifestDir = path.join(root, "dist", "server");
801
722
  const config = options.nextConfig ? { ...options.nextConfig } : { ...await resolveNextConfig(await loadNextConfig(root, PHASE_PRODUCTION_BUILD), root) };
@@ -30,8 +30,14 @@ export type PrerenderRouteResult = {
30
30
  router: "app" | "pages" | "metadata";
31
31
  /** Response headers that must be replayed with the prerendered artifact. */
32
32
  headers?: Record<string, string | string[]>;
33
- /** Original HTTP status for prerendered App Route-style responses. */
33
+ /** Original HTTP status for prerendered route responses. */
34
34
  responseStatus?: number;
35
+ /** Pages source returned notFound, distinct from the custom 404 document. */
36
+ notFound?: true;
37
+ /** Original Pages redirect props, including client navigation semantics. */
38
+ redirectProps?: object;
39
+ /** Pages locale rendered for this public pathname. */
40
+ locale?: string;
35
41
  /** Cache tags collected while rendering this route. */
36
42
  tags?: string[];
37
43
  /** Raw app-tree segments used to derive App Route implicit tags. */
@@ -234,6 +240,7 @@ export declare function routeStaticParamSets(route: Pick<AppRoute, "pattern">, p
234
240
  * sets still go through routeStaticParamSets.
235
241
  */
236
242
  export declare function layoutOnlyParamSets(route: Pick<AppRoute, "params" | "pattern">, parentParamSets: Record<string, string | string[]>[]): Record<string, string | string[]>[] | null;
243
+ export declare function localizePagesPath(pathname: string, locale: string | undefined, i18n: ResolvedNextConfig["i18n"]): string;
237
244
  /**
238
245
  * Run the prerender phase for Pages Router.
239
246
  *