@qzsy/vinext 0.1.11 → 0.1.80

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 (225) hide show
  1. package/README.md +19 -5
  2. package/dist/build/inject-pregenerated-paths.d.ts +4 -0
  3. package/dist/build/inject-pregenerated-paths.js +18 -0
  4. package/dist/build/pages-client-assets-module.d.ts +11 -0
  5. package/dist/build/pages-client-assets-module.js +27 -0
  6. package/dist/build/prerender.d.ts +2 -1
  7. package/dist/build/prerender.js +11 -4
  8. package/dist/build/report.d.ts +2 -1
  9. package/dist/build/report.js +2 -1
  10. package/dist/build/run-prerender.d.ts +7 -0
  11. package/dist/build/run-prerender.js +9 -0
  12. package/dist/build/standalone.js +2 -0
  13. package/dist/check.d.ts +18 -0
  14. package/dist/check.js +77 -19
  15. package/dist/cli-dev-config.d.ts +12 -0
  16. package/dist/cli-dev-config.js +23 -0
  17. package/dist/cli.js +64 -28
  18. package/dist/{server → client}/dev-error-overlay-store.d.ts +1 -1
  19. package/dist/{server → client}/dev-error-overlay-store.js +1 -1
  20. package/dist/{server → client}/dev-error-overlay.d.ts +1 -1
  21. package/dist/{server → client}/dev-error-overlay.js +2 -2
  22. package/dist/cloudflare/deploy-config.d.ts +51 -0
  23. package/dist/cloudflare/deploy-config.js +153 -0
  24. package/dist/cloudflare/index.d.ts +1 -1
  25. package/dist/cloudflare/index.js +1 -1
  26. package/dist/cloudflare/project.d.ts +41 -0
  27. package/dist/cloudflare/project.js +243 -0
  28. package/dist/cloudflare/tpr.js +1 -1
  29. package/dist/config/config-matchers.js +14 -10
  30. package/dist/config/next-config.d.ts +6 -3
  31. package/dist/config/next-config.js +47 -1
  32. package/dist/config/server-external-packages.d.ts +4 -0
  33. package/dist/config/server-external-packages.js +91 -0
  34. package/dist/deploy.d.ts +2 -122
  35. package/dist/deploy.js +20 -793
  36. package/dist/entries/app-rsc-entry.d.ts +2 -1
  37. package/dist/entries/app-rsc-entry.js +70 -12
  38. package/dist/entries/app-rsc-manifest.js +8 -0
  39. package/dist/entries/pages-client-entry.d.ts +1 -0
  40. package/dist/entries/pages-client-entry.js +2 -1
  41. package/dist/entries/pages-server-entry.js +6 -2
  42. package/dist/image/image-adapters-virtual.d.ts +59 -0
  43. package/dist/image/image-adapters-virtual.js +50 -0
  44. package/dist/index.d.ts +12 -0
  45. package/dist/index.js +158 -109
  46. package/dist/init-cloudflare.d.ts +43 -0
  47. package/dist/init-cloudflare.js +1000 -0
  48. package/dist/init-platform.d.ts +38 -0
  49. package/dist/init-platform.js +150 -0
  50. package/dist/init.d.ts +14 -37
  51. package/dist/init.js +205 -95
  52. package/dist/node_modules/.pnpm/am-i-vibing@0.5.0/node_modules/am-i-vibing/dist/detector-1yx2Hoe0.js +294 -0
  53. package/dist/node_modules/.pnpm/process-ancestry@0.1.0/node_modules/process-ancestry/dist/index.js +94 -0
  54. package/dist/{cloudflare → packages/cloudflare}/src/cache/cdn-adapter.runtime.js +1 -1
  55. package/dist/{cloudflare → packages/cloudflare}/src/cache/kv-data-adapter.runtime.d.ts +2 -2
  56. package/dist/{cloudflare → packages/cloudflare}/src/cache/kv-data-adapter.runtime.js +1 -1
  57. package/dist/plugins/ast-scope.d.ts +16 -0
  58. package/dist/plugins/ast-scope.js +62 -0
  59. package/dist/plugins/ast-utils.js +3 -0
  60. package/dist/plugins/css-module-imports.d.ts +14 -0
  61. package/dist/plugins/css-module-imports.js +59 -0
  62. package/dist/plugins/ignore-dynamic-requests.d.ts +11 -0
  63. package/dist/plugins/ignore-dynamic-requests.js +530 -0
  64. package/dist/plugins/middleware-server-only.d.ts +8 -6
  65. package/dist/plugins/middleware-server-only.js +8 -7
  66. package/dist/plugins/optimize-imports.js +1 -1
  67. package/dist/plugins/typeof-window.d.ts +1 -1
  68. package/dist/plugins/typeof-window.js +28 -56
  69. package/dist/routing/app-route-graph.d.ts +13 -2
  70. package/dist/routing/app-route-graph.js +116 -32
  71. package/dist/routing/app-router.d.ts +5 -0
  72. package/dist/routing/app-router.js +5 -0
  73. package/dist/routing/file-matcher.d.ts +8 -0
  74. package/dist/routing/file-matcher.js +10 -1
  75. package/dist/routing/pages-router.js +2 -2
  76. package/dist/server/app-browser-action-result.d.ts +2 -1
  77. package/dist/server/app-browser-action-result.js +5 -1
  78. package/dist/server/app-browser-entry.js +17 -12
  79. package/dist/server/app-browser-history-controller.d.ts +2 -1
  80. package/dist/server/app-browser-history-controller.js +6 -2
  81. package/dist/server/app-browser-interception-context.d.ts +1 -0
  82. package/dist/server/app-browser-interception-context.js +4 -2
  83. package/dist/server/app-browser-navigation-controller.js +1 -0
  84. package/dist/server/app-browser-server-action-client.js +2 -3
  85. package/dist/server/app-browser-state.d.ts +1 -0
  86. package/dist/server/app-browser-state.js +3 -2
  87. package/dist/server/app-fallback-renderer.d.ts +3 -2
  88. package/dist/server/app-fallback-renderer.js +12 -7
  89. package/dist/server/app-middleware.d.ts +2 -3
  90. package/dist/server/app-middleware.js +3 -2
  91. package/dist/server/app-optimistic-routing.js +1 -1
  92. package/dist/server/app-page-boundary-render.d.ts +1 -0
  93. package/dist/server/app-page-boundary-render.js +12 -3
  94. package/dist/server/app-page-cache-finalizer.d.ts +1 -0
  95. package/dist/server/app-page-cache-finalizer.js +10 -3
  96. package/dist/server/app-page-cache-render.d.ts +1 -0
  97. package/dist/server/app-page-cache-render.js +8 -4
  98. package/dist/server/app-page-cache.d.ts +1 -0
  99. package/dist/server/app-page-cache.js +4 -1
  100. package/dist/server/app-page-dispatch.d.ts +11 -3
  101. package/dist/server/app-page-dispatch.js +55 -15
  102. package/dist/server/app-page-element-builder.d.ts +5 -1
  103. package/dist/server/app-page-element-builder.js +57 -20
  104. package/dist/server/app-page-head.d.ts +12 -0
  105. package/dist/server/app-page-head.js +42 -19
  106. package/dist/server/app-page-params.d.ts +2 -1
  107. package/dist/server/app-page-params.js +8 -1
  108. package/dist/server/app-page-probe.d.ts +1 -0
  109. package/dist/server/app-page-probe.js +6 -1
  110. package/dist/server/app-page-render-identity.d.ts +1 -0
  111. package/dist/server/app-page-render-identity.js +1 -1
  112. package/dist/server/app-page-render.d.ts +4 -1
  113. package/dist/server/app-page-render.js +8 -3
  114. package/dist/server/app-page-request.d.ts +22 -1
  115. package/dist/server/app-page-request.js +89 -13
  116. package/dist/server/app-page-route-wiring.d.ts +6 -1
  117. package/dist/server/app-page-route-wiring.js +31 -15
  118. package/dist/server/app-page-search-params-observation.d.ts +4 -2
  119. package/dist/server/app-page-search-params-observation.js +11 -7
  120. package/dist/server/app-page-segment-state.js +2 -0
  121. package/dist/server/app-route-handler-dispatch.js +1 -0
  122. package/dist/server/app-route-handler-execution.js +7 -2
  123. package/dist/server/app-route-handler-response.js +1 -0
  124. package/dist/server/app-route-handler-runtime.js +1 -1
  125. package/dist/server/app-route-module-loader.d.ts +2 -0
  126. package/dist/server/app-route-module-loader.js +1 -0
  127. package/dist/server/app-router-entry.d.ts +12 -0
  128. package/dist/server/app-router-entry.js +22 -8
  129. package/dist/server/app-router-image-optimization.d.ts +37 -0
  130. package/dist/server/app-router-image-optimization.js +40 -0
  131. package/dist/server/app-rsc-errors.js +7 -1
  132. package/dist/server/app-rsc-handler.js +27 -14
  133. package/dist/server/app-rsc-route-matching.d.ts +7 -0
  134. package/dist/server/app-rsc-route-matching.js +36 -3
  135. package/dist/server/app-segment-config.d.ts +12 -0
  136. package/dist/server/app-segment-config.js +91 -5
  137. package/dist/server/app-server-action-execution.d.ts +5 -0
  138. package/dist/server/app-server-action-execution.js +94 -33
  139. package/dist/server/app-ssr-entry.js +12 -1
  140. package/dist/server/app-static-generation.d.ts +1 -0
  141. package/dist/server/app-static-generation.js +1 -0
  142. package/dist/server/client-trace-metadata.js +26 -0
  143. package/dist/server/default-global-not-found-module.d.ts +14 -0
  144. package/dist/server/default-global-not-found-module.js +14 -0
  145. package/dist/server/dev-server.js +8 -15
  146. package/dist/server/dev-stack-sourcemap.d.ts +1 -1
  147. package/dist/server/dev-stack-sourcemap.js +1 -1
  148. package/dist/server/headers.d.ts +5 -15
  149. package/dist/server/headers.js +4 -15
  150. package/dist/server/image-optimization.d.ts +51 -1
  151. package/dist/server/image-optimization.js +52 -2
  152. package/dist/server/isr-cache.d.ts +1 -1
  153. package/dist/server/isr-cache.js +2 -2
  154. package/dist/server/middleware-runtime.js +6 -1
  155. package/dist/server/navigation-planner.d.ts +1 -0
  156. package/dist/server/navigation-planner.js +14 -3
  157. package/dist/server/pages-asset-tags.d.ts +4 -6
  158. package/dist/server/pages-asset-tags.js +12 -12
  159. package/dist/server/pages-client-assets.d.ts +12 -0
  160. package/dist/server/pages-client-assets.js +10 -0
  161. package/dist/server/pages-page-data.d.ts +23 -1
  162. package/dist/server/pages-page-data.js +43 -24
  163. package/dist/server/pages-page-handler.d.ts +2 -1
  164. package/dist/server/pages-page-handler.js +10 -4
  165. package/dist/server/pages-request-pipeline.d.ts +2 -0
  166. package/dist/server/pages-request-pipeline.js +25 -1
  167. package/dist/server/prerender-manifest.d.ts +3 -1
  168. package/dist/server/prerender-route-params.js +1 -1
  169. package/dist/server/prod-server.d.ts +1 -1
  170. package/dist/server/prod-server.js +47 -25
  171. package/dist/server/request-pipeline.js +1 -0
  172. package/dist/server/seed-cache.js +4 -4
  173. package/dist/server/worker-utils.d.ts +2 -1
  174. package/dist/server/worker-utils.js +7 -1
  175. package/dist/shims/app-router-scroll-state.d.ts +1 -0
  176. package/dist/shims/app-router-scroll-state.js +1 -0
  177. package/dist/shims/app-router-scroll.js +2 -1
  178. package/dist/shims/cache.js +19 -15
  179. package/dist/shims/cdn-cache.js +1 -1
  180. package/dist/shims/dynamic-preload-chunks.js +2 -1
  181. package/dist/shims/error-boundary.d.ts +19 -1
  182. package/dist/shims/error-boundary.js +11 -1
  183. package/dist/shims/form.d.ts +3 -1
  184. package/dist/shims/form.js +37 -43
  185. package/dist/shims/headers.d.ts +9 -1
  186. package/dist/shims/headers.js +31 -6
  187. package/dist/shims/image-optimization-url.d.ts +4 -0
  188. package/dist/shims/image-optimization-url.js +33 -1
  189. package/dist/shims/image.js +46 -13
  190. package/dist/shims/internal/app-route-detection.d.ts +2 -17
  191. package/dist/shims/internal/app-route-detection.js +4 -17
  192. package/dist/shims/internal/hybrid-client-route-owner-direct.d.ts +23 -0
  193. package/dist/shims/internal/hybrid-client-route-owner-direct.js +51 -0
  194. package/dist/shims/internal/hybrid-client-route-owner.d.ts +2 -5
  195. package/dist/shims/internal/hybrid-client-route-owner.js +9 -60
  196. package/dist/shims/internal/pages-router-components.d.ts +7 -0
  197. package/dist/shims/internal/pages-router-components.js +13 -0
  198. package/dist/shims/link.js +23 -16
  199. package/dist/shims/metadata.d.ts +3 -2
  200. package/dist/shims/metadata.js +8 -4
  201. package/dist/shims/navigation.js +4 -2
  202. package/dist/shims/root-params.d.ts +15 -1
  203. package/dist/shims/root-params.js +21 -1
  204. package/dist/shims/router.d.ts +2 -5
  205. package/dist/shims/router.js +41 -22
  206. package/dist/shims/server.js +3 -2
  207. package/dist/typegen.js +6 -5
  208. package/dist/utils/client-runtime-metadata.d.ts +2 -18
  209. package/dist/utils/client-runtime-metadata.js +31 -22
  210. package/dist/utils/dev-stack-sourcemap-endpoint.d.ts +4 -0
  211. package/dist/{server → utils}/dev-stack-sourcemap-endpoint.js +1 -1
  212. package/dist/utils/domain-locale.d.ts +6 -3
  213. package/dist/{server → utils}/middleware-request-headers.d.ts +1 -1
  214. package/dist/{server → utils}/middleware-request-headers.js +2 -2
  215. package/dist/utils/path.d.ts +2 -1
  216. package/dist/utils/path.js +1 -1
  217. package/dist/utils/project.d.ts +9 -1
  218. package/dist/utils/project.js +21 -4
  219. package/dist/utils/protocol-headers.d.ts +17 -0
  220. package/dist/utils/protocol-headers.js +17 -0
  221. package/dist/utils/react-version.d.ts +4 -0
  222. package/dist/utils/react-version.js +44 -0
  223. package/package.json +28 -24
  224. package/dist/server/dev-stack-sourcemap-endpoint.d.ts +0 -4
  225. /package/dist/{cloudflare → packages/cloudflare}/src/utils/cache-control-metadata.js +0 -0
package/README.md CHANGED
@@ -72,7 +72,10 @@ Options: `-p / --port <port>`, `-H / --hostname <host>`, `--turbopack` (accepted
72
72
 
73
73
  `vinext deploy` options: `--preview`, `--env <name>`, `--name <name>`, `--skip-build`, `--dry-run`, `--experimental-tpr`.
74
74
 
75
- `vinext init` options: `--port <port>` (default: 3001), `--skip-check`, `--force`.
75
+ `vinext init` prompts for a deployment target, defaulting to Cloudflare. Agents must ask the
76
+ user which target they want, then pass `--platform=cloudflare` or `--platform=node`.
77
+
78
+ Other options: `--port <port>` (default: 3001), `--skip-check`, `--force`.
76
79
 
77
80
  If your `next.config.*` sets `output: "standalone"`, `vinext build` emits a self-hosting bundle at `dist/standalone/`. Start it with:
78
81
 
@@ -105,7 +108,9 @@ This will:
105
108
  3. Rename CJS config files (e.g. `postcss.config.js` -> `.cjs`) to avoid ESM conflicts
106
109
  4. Add `"type": "module"` to `package.json`
107
110
  5. Add `dev:vinext`, `build:vinext`, and `start:vinext` scripts to `package.json`
108
- 6. Generate a minimal `vite.config.ts`
111
+ 6. Prompt for a deployment platform (Cloudflare by default, or Node)
112
+ 7. Generate the matching `vite.config.ts`
113
+ 8. For Cloudflare, generate `wrangler.jsonc` and `worker/index.ts`
109
114
 
110
115
  The migration is non-destructive -- your existing Next.js setup continues to work alongside vinext. It does not modify `next.config`, `tsconfig.json`, or any source files, and it does not remove Next.js dependencies.
111
116
 
@@ -118,7 +123,10 @@ npm run start:vinext # Start vinext production server
118
123
  npm run dev # Still runs Next.js as before
119
124
  ```
120
125
 
121
- Use `--force` to overwrite an existing `vite.config.ts`, or `--skip-check` to skip the compatibility report.
126
+ Use `--platform=cloudflare` or `--platform=node` to skip the platform prompt. Cloudflare init
127
+ updates an existing JavaScript or TypeScript Vite config using its AST, preserving unrelated
128
+ settings. Use `--force` to replace an existing Node-target Vite config, or `--skip-check` to skip
129
+ the compatibility report.
122
130
 
123
131
  ## Why
124
132
 
@@ -208,7 +216,13 @@ Find your account ID in the Cloudflare dashboard URL (`dash.cloudflare.com/<acco
208
216
 
209
217
  Alternatively, set the `CLOUDFLARE_ACCOUNT_ID` environment variable instead of hardcoding it in the config file.
210
218
 
211
- `vinext deploy` auto-generates the necessary configuration files (`vite.config.ts`, `wrangler.jsonc`, `worker/index.ts`) if they don't exist, builds the application, and deploys to Workers.
219
+ Run `vinext init --platform=cloudflare` first to install dependencies and create or AST-update
220
+ `vite.config.*`, `wrangler.jsonc`, and `worker/index.ts`. `vinext deploy` then validates that setup,
221
+ builds the application, and deploys to Workers without rewriting project configuration.
222
+
223
+ Cloudflare init can also configure image optimization declaratively in the Vite config with
224
+ `imagesOptimizer()` and add the matching Wrangler Images binding. The generated Worker entry remains a
225
+ thin request forwarder; image optimization is not implemented or generated by `vinext deploy`.
212
226
 
213
227
  ```bash
214
228
  vinext deploy
@@ -217,7 +231,7 @@ vinext deploy --env staging
217
231
 
218
232
  Use `--env <name>` to target `wrangler.jsonc` `env.<name>`. `--preview` is shorthand for `--env preview`.
219
233
 
220
- The deploy command also auto-detects and fixes common migration issues:
234
+ The init command also auto-detects and fixes common migration issues:
221
235
 
222
236
  - Adds `"type": "module"` to package.json if missing
223
237
  - Resolves tsconfig.json path aliases automatically (via `vite-tsconfig-paths`)
@@ -0,0 +1,4 @@
1
+ //#region src/build/inject-pregenerated-paths.d.ts
2
+ declare function injectPregeneratedConcretePaths(root: string): void;
3
+ //#endregion
4
+ export { injectPregeneratedConcretePaths };
@@ -0,0 +1,18 @@
1
+ import { escapeRegExp } from "../utils/regex.js";
2
+ import { readPrerenderManifest } from "../server/prerender-manifest.js";
3
+ import fs from "node:fs";
4
+ import path from "node:path";
5
+ //#region src/build/inject-pregenerated-paths.ts
6
+ const VINEXT_PREGEN_START = "/* __VINEXT_PREGENERATED_CONCRETE_PATHS_START__ */";
7
+ const VINEXT_PREGEN_END = "/* __VINEXT_PREGENERATED_CONCRETE_PATHS_END__ */";
8
+ const VINEXT_PREGEN_RE = new RegExp(`${escapeRegExp(VINEXT_PREGEN_START)}[\\s\\S]*?${escapeRegExp(VINEXT_PREGEN_END)}\\n?`, "g");
9
+ function injectPregeneratedConcretePaths(root) {
10
+ const workerEntry = path.resolve(root, "dist", "server", "index.js");
11
+ if (!fs.existsSync(workerEntry)) return;
12
+ let code = fs.readFileSync(workerEntry, "utf-8").replace(VINEXT_PREGEN_RE, "");
13
+ const table = readPrerenderManifest(path.join(root, "dist", "server", "vinext-prerender.json"))?.pregeneratedConcretePaths ?? [];
14
+ if (table.length > 0) code = `${VINEXT_PREGEN_START}\nglobalThis.__VINEXT_PREGENERATED_CONCRETE_PATHS = ${JSON.stringify(table)};\n${VINEXT_PREGEN_END}\n` + code;
15
+ fs.writeFileSync(workerEntry, code);
16
+ }
17
+ //#endregion
18
+ export { injectPregeneratedConcretePaths };
@@ -0,0 +1,11 @@
1
+ import { PagesClientAssets } from "../server/pages-client-assets.js";
2
+
3
+ //#region src/build/pages-client-assets-module.d.ts
4
+ declare const PAGES_CLIENT_ASSETS_MODULE = "vinext-client-assets.js";
5
+ declare function buildPagesClientAssetsModule(assets: PagesClientAssets): string;
6
+ declare function writePagesClientAssetsModuleIfMissing(outputDir: string, moduleSource: string): void;
7
+ declare function setPagesClientAssetsBuildMetadata(buildSession: string, moduleSource: string): void;
8
+ declare function takePagesClientAssetsBuildMetadata(buildSession: string): string | null;
9
+ declare function clearPagesClientAssetsBuildMetadata(buildSession: string): void;
10
+ //#endregion
11
+ export { PAGES_CLIENT_ASSETS_MODULE, buildPagesClientAssetsModule, clearPagesClientAssetsBuildMetadata, setPagesClientAssetsBuildMetadata, takePagesClientAssetsBuildMetadata, writePagesClientAssetsModuleIfMissing };
@@ -0,0 +1,27 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ //#region src/build/pages-client-assets-module.ts
4
+ const PAGES_CLIENT_ASSETS_MODULE = "vinext-client-assets.js";
5
+ const pagesClientAssetsByBuildSession = /* @__PURE__ */ new Map();
6
+ function buildPagesClientAssetsModule(assets) {
7
+ return `export default ${JSON.stringify(assets)};\n`;
8
+ }
9
+ function writePagesClientAssetsModuleIfMissing(outputDir, moduleSource) {
10
+ const outputPath = path.join(outputDir, PAGES_CLIENT_ASSETS_MODULE);
11
+ if (fs.existsSync(outputPath)) return;
12
+ fs.mkdirSync(outputDir, { recursive: true });
13
+ fs.writeFileSync(outputPath, moduleSource);
14
+ }
15
+ function setPagesClientAssetsBuildMetadata(buildSession, moduleSource) {
16
+ pagesClientAssetsByBuildSession.set(buildSession, moduleSource);
17
+ }
18
+ function takePagesClientAssetsBuildMetadata(buildSession) {
19
+ const moduleSource = pagesClientAssetsByBuildSession.get(buildSession) ?? null;
20
+ pagesClientAssetsByBuildSession.delete(buildSession);
21
+ return moduleSource;
22
+ }
23
+ function clearPagesClientAssetsBuildMetadata(buildSession) {
24
+ pagesClientAssetsByBuildSession.delete(buildSession);
25
+ }
26
+ //#endregion
27
+ export { PAGES_CLIENT_ASSETS_MODULE, buildPagesClientAssetsModule, clearPagesClientAssetsBuildMetadata, setPagesClientAssetsBuildMetadata, takePagesClientAssetsBuildMetadata, writePagesClientAssetsModuleIfMissing };
@@ -22,7 +22,8 @@ type PrerenderRouteResult = {
22
22
  * Omitted for non-dynamic routes where pattern === path.
23
23
  */
24
24
  path?: string; /** Which router produced this route. Used by cache seeding. */
25
- router: "app" | "pages"; /** Set to true when this is a PPR fallback shell. */
25
+ router: "app" | "pages"; /** Response headers that must be replayed with the prerendered artifact. */
26
+ headers?: Record<string, string>; /** Set to true when this is a PPR fallback shell. */
26
27
  fallback?: boolean;
27
28
  } | {
28
29
  route: string;
@@ -1,16 +1,17 @@
1
1
  import { createValidFileMatcher, findFileWithExtensions } from "../routing/file-matcher.js";
2
- import { VINEXT_PRERENDER_ROUTE_PARAMS_HEADER, VINEXT_PRERENDER_SECRET_HEADER } from "../server/headers.js";
3
- import { normalizeStaticPathsEntry } from "../routing/route-pattern.js";
2
+ import { VINEXT_PRERENDER_ROUTE_PARAMS_HEADER, VINEXT_PRERENDER_SECRET_HEADER } from "../utils/protocol-headers.js";
4
3
  import { NoOpCacheHandler, getCacheHandler, setCacheHandler } from "../shims/cache-handler.js";
5
4
  import { headersContextFromRequest, runWithHeadersContext } from "../shims/headers.js";
6
5
  import { _consumeRequestScopedCacheLife } from "../shims/cache-request-state.js";
6
+ import { normalizeStaticPathsEntry } from "../routing/route-pattern.js";
7
7
  import { classifyAppRoute, classifyPagesRoute, getAppRouteRenderEntryPath } from "./report.js";
8
8
  import { BLOCKED_PAGES } from "../shims/constants.js";
9
+ import { buildPregeneratedConcretePathTable } from "../server/prerender-manifest.js";
9
10
  import { concatUint8Arrays, decodeRscEmbeddedChunk } from "../server/app-rsc-embedded-chunks.js";
10
11
  import { navigationRuntimeRscBootstrapExpression } from "../server/app-ssr-stream.js";
11
- import { createAppPprFallbackShells, markAppPprDynamicFallbackShellHtml } from "../server/app-ppr-fallback-shell.js";
12
12
  import { encodePrerenderRouteParams, serializePrerenderRouteParamsHeader } from "../server/prerender-route-params.js";
13
13
  import { readPrerenderSecret } from "./server-manifest.js";
14
+ import { createAppPprFallbackShells, markAppPprDynamicFallbackShellHtml } from "../server/app-ppr-fallback-shell.js";
14
15
  import { getOutputPath, getRscOutputPath } from "../utils/prerender-output-paths.js";
15
16
  import { startProdServer } from "../server/prod-server.js";
16
17
  import fs from "node:fs";
@@ -721,10 +722,12 @@ async function prerenderApp({ routes, metadataRoutes = [], outDir, config, mode,
721
722
  const htmlRender = await runWithHeadersContext(headersContextFromRequest(htmlRequest), async () => {
722
723
  const response = await rscHandler(htmlRequest);
723
724
  const cacheControl = response.headers.get("cache-control") ?? "";
725
+ const linkHeader = response.headers.get("link");
724
726
  if (!response.ok || isSpeculative && cacheControl.includes("no-store")) {
725
727
  await response.body?.cancel();
726
728
  return {
727
729
  cacheControl,
730
+ linkHeader,
728
731
  html: null,
729
732
  ok: response.ok,
730
733
  requestCacheLife: null,
@@ -733,6 +736,7 @@ async function prerenderApp({ routes, metadataRoutes = [], outDir, config, mode,
733
736
  }
734
737
  return {
735
738
  cacheControl,
739
+ linkHeader,
736
740
  html: await response.text(),
737
741
  ok: true,
738
742
  requestCacheLife: _consumeRequestScopedCacheLife(),
@@ -800,6 +804,7 @@ async function prerenderApp({ routes, metadataRoutes = [], outDir, config, mode,
800
804
  revalidate: renderedRevalidate,
801
805
  ...typeof renderedRevalidate === "number" ? { expire: renderedCacheControl.expire } : {},
802
806
  router: "app",
807
+ ...htmlRender.linkHeader ? { headers: { link: htmlRender.linkHeader } } : {},
803
808
  ...urlPath !== routePattern ? { path: urlPath } : {},
804
809
  ...isFallback ? { fallback: true } : {}
805
810
  };
@@ -907,6 +912,7 @@ function writePrerenderIndex(routes, outDir, options) {
907
912
  revalidate: r.revalidate,
908
913
  ...typeof r.revalidate === "number" ? { expire: r.expire } : {},
909
914
  router: r.router,
915
+ ...r.headers ? { headers: r.headers } : {},
910
916
  ...r.path ? { path: r.path } : {},
911
917
  ...r.fallback ? { fallback: true } : {}
912
918
  };
@@ -924,7 +930,8 @@ function writePrerenderIndex(routes, outDir, options) {
924
930
  const index = {
925
931
  ...buildId ? { buildId } : {},
926
932
  ...typeof trailingSlash === "boolean" ? { trailingSlash } : {},
927
- routes: indexRoutes
933
+ routes: indexRoutes,
934
+ pregeneratedConcretePaths: buildPregeneratedConcretePathTable({ routes: indexRoutes })
928
935
  };
929
936
  fs.writeFileSync(path.join(outDir, "vinext-prerender.json"), JSON.stringify(index, null, 2), "utf-8");
930
937
  }
@@ -121,7 +121,8 @@ declare function formatBuildReport(rows: RouteRow[], routerLabel?: string): stri
121
121
  * Scans the project at `root`, classifies all routes, and prints the
122
122
  * Next.js-style build report to stdout.
123
123
  *
124
- * Called at the end of `vinext build` in cli.ts.
124
+ * `root` must be forward-slash it is passed to `findDir`. The caller (the
125
+ * `vinext build` entry in cli.ts) normalizes it.
125
126
  */
126
127
  declare function printBuildReport(options: {
127
128
  root: string;
@@ -474,7 +474,8 @@ function formatBuildReport(rows, routerLabel = "app") {
474
474
  * Scans the project at `root`, classifies all routes, and prints the
475
475
  * Next.js-style build report to stdout.
476
476
  *
477
- * Called at the end of `vinext build` in cli.ts.
477
+ * `root` must be forward-slash it is passed to `findDir`. The caller (the
478
+ * `vinext build` entry in cli.ts) normalizes it.
478
479
  */
479
480
  async function printBuildReport(options) {
480
481
  const { root } = options;
@@ -56,6 +56,13 @@ type RunPrerenderOptions = {
56
56
  * `output: 'export'`. Exported for direct unit testing. Refs cloudflare/vinext#1982
57
57
  */
58
58
  declare function assertNoFatalPrerenderRoutes(routes: readonly PrerenderRouteResult[]): void;
59
+ /**
60
+ * Statically generate routes and return the prerender result.
61
+ *
62
+ * `options.root` must be forward-slash — it is passed to `findDir` and flows
63
+ * into the route model. The caller (the `vinext build` entry in cli.ts)
64
+ * normalizes it.
65
+ */
59
66
  declare function runPrerender(options: RunPrerenderOptions): Promise<PrerenderResult | null>;
60
67
  //#endregion
61
68
  export { assertNoFatalPrerenderRoutes, runPrerender };
@@ -6,6 +6,7 @@ import { loadNextConfig, resolveNextConfig } from "../config/next-config.js";
6
6
  import { readPrerenderSecret } from "./server-manifest.js";
7
7
  import { startProdServer } from "../server/prod-server.js";
8
8
  import { prerenderApp, prerenderPages, writePrerenderIndex } from "./prerender.js";
9
+ import { injectPregeneratedConcretePaths } from "./inject-pregenerated-paths.js";
9
10
  import fs from "node:fs";
10
11
  import path from "node:path";
11
12
  //#region src/build/run-prerender.ts
@@ -95,6 +96,13 @@ function assertNoFatalPrerenderRoutes(routes) {
95
96
  const fatalList = fatalRoutes.map((r) => ` ${r.route}: ${r.error}`).join("\n");
96
97
  throw new Error(`Prerender failed: ${fatalRoutes.length} route${fatalRoutes.length !== 1 ? "s" : ""} errored during static generation.\n${fatalList}`);
97
98
  }
99
+ /**
100
+ * Statically generate routes and return the prerender result.
101
+ *
102
+ * `options.root` must be forward-slash — it is passed to `findDir` and flows
103
+ * into the route model. The caller (the `vinext build` entry in cli.ts)
104
+ * normalizes it.
105
+ */
98
106
  async function runPrerender(options) {
99
107
  const { root } = options;
100
108
  const appDir = findDir(root, "app", "src/app");
@@ -215,6 +223,7 @@ async function runPrerender(options) {
215
223
  const errorRoutes = allRoutes.filter((r) => r.status === "error").map((r) => ` ${r.route}: ${r.error}`).join("\n");
216
224
  throw new Error(`Static export failed: ${errors} route${errors !== 1 ? "s" : ""} cannot be statically exported.\n${errorRoutes}\n\nRemove server-side data fetching (getServerSideProps, force-dynamic, revalidate) from these routes, or remove \`output: "export"\` from next.config.js.`);
217
225
  }
226
+ injectPregeneratedConcretePaths(root);
218
227
  return {
219
228
  routes: allRoutes,
220
229
  ...allOutputFiles.length > 0 ? { outputFiles: allOutputFiles } : {}
@@ -167,6 +167,8 @@ function emitStandaloneOutput(options) {
167
167
  dereference: true,
168
168
  filter: (src) => !path.relative(serverDir, src).split(path.sep).includes("node_modules")
169
169
  });
170
+ const clientAssetsSidecar = path.join(outDir, "vinext-client-assets.js");
171
+ if (fs.existsSync(clientAssetsSidecar)) fs.copyFileSync(clientAssetsSidecar, path.join(standaloneDistDir, "vinext-client-assets.js"));
170
172
  const publicDir = path.join(root, "public");
171
173
  if (fs.existsSync(publicDir)) fs.cpSync(publicDir, path.join(standaloneDir, "public"), {
172
174
  recursive: true,
package/dist/check.d.ts CHANGED
@@ -59,22 +59,40 @@ type CheckResult = {
59
59
  declare function hasFreeCjsGlobal(content: string): boolean;
60
60
  /**
61
61
  * Scan source files for `import ... from 'next/...'` statements.
62
+ *
63
+ * `root` must be forward-slash: it is passed to `findSourceFiles` (which
64
+ * requires it) and used as the base of `path.posix.relative`, which only yields
65
+ * a canonical relative path when both operands are forward-slash.
62
66
  */
63
67
  declare function scanImports(root: string): CheckItem[];
64
68
  /**
65
69
  * Analyze next.config.js/mjs/ts for supported and unsupported options.
70
+ *
71
+ * `root` must be forward-slash — joined with `path.posix.join`. Only called
72
+ * from `runCheck`, which normalizes it.
66
73
  */
67
74
  declare function analyzeConfig(root: string): CheckItem[];
68
75
  /**
69
76
  * Check package.json dependencies for known libraries.
77
+ *
78
+ * `root` must be forward-slash — joined with `path.posix.join`. Only called
79
+ * from `runCheck`, which normalizes it.
70
80
  */
71
81
  declare function checkLibraries(root: string): CheckItem[];
72
82
  /**
73
83
  * Check file conventions (pages, app directory, middleware, etc.)
84
+ *
85
+ * `root` must be forward-slash — joined with `path.posix.join`, passed to
86
+ * `findDir`, and used as the base of `path.posix.relative`. Only called from
87
+ * `runCheck`, which normalizes it.
74
88
  */
75
89
  declare function checkConventions(root: string): CheckItem[];
76
90
  /**
77
91
  * Run the full compatibility check.
92
+ *
93
+ * `root` must be forward-slash — callers normalize it at the CLI entry, and it
94
+ * is forwarded to `scanImports` / `checkConventions` / `findDir`, which build
95
+ * paths with `path.posix.*`.
78
96
  */
79
97
  declare function runCheck(root: string): CheckResult;
80
98
  /**
package/dist/check.js CHANGED
@@ -1,5 +1,4 @@
1
1
  import { detectPackageManager, findDir } from "./utils/project.js";
2
- import { normalizePathSeparators } from "./utils/path.js";
3
2
  import fs from "node:fs";
4
3
  import path from "node:path";
5
4
  import { parseAst } from "vite";
@@ -193,7 +192,7 @@ const CONFIG_SUPPORT = {
193
192
  env: { status: "supported" },
194
193
  images: {
195
194
  status: "partial",
196
- detail: "remotePatterns validated, no local optimization"
195
+ detail: "remotePatterns validated; on-the-fly optimization via images.optimizer (Cloudflare Images), passthrough otherwise"
197
196
  },
198
197
  allowedDevOrigins: {
199
198
  status: "supported",
@@ -259,6 +258,42 @@ const CONFIG_SUPPORT = {
259
258
  status: "partial",
260
259
  detail: "config recognized; vinext does not implement navigation result caching"
261
260
  },
261
+ "experimental.middlewarePrefetch": {
262
+ status: "unsupported",
263
+ detail: "not recognized; use of this option is ignored"
264
+ },
265
+ "experimental.proxyPrefetch": {
266
+ status: "unsupported",
267
+ detail: "not recognized; use of this option is ignored"
268
+ },
269
+ "experimental.middlewareClientMaxBodySize": {
270
+ status: "unsupported",
271
+ detail: "not recognized; use of this option is ignored"
272
+ },
273
+ "experimental.proxyClientMaxBodySize": {
274
+ status: "unsupported",
275
+ detail: "not recognized; use of this option is ignored"
276
+ },
277
+ "experimental.externalMiddlewareRewritesResolve": {
278
+ status: "unsupported",
279
+ detail: "not recognized; use of this option is ignored"
280
+ },
281
+ "experimental.externalProxyRewritesResolve": {
282
+ status: "unsupported",
283
+ detail: "not recognized; use of this option is ignored"
284
+ },
285
+ "experimental.instrumentationHook": {
286
+ status: "unsupported",
287
+ detail: "not recognized; instrumentation files are enabled automatically"
288
+ },
289
+ skipMiddlewareUrlNormalize: {
290
+ status: "unsupported",
291
+ detail: "not recognized; use of this option is ignored"
292
+ },
293
+ skipProxyUrlNormalize: {
294
+ status: "unsupported",
295
+ detail: "not recognized; use of this option is ignored"
296
+ },
262
297
  "i18n.domains": {
263
298
  status: "partial",
264
299
  detail: "supported for Pages Router; App Router unchanged"
@@ -331,6 +366,11 @@ const LIBRARY_SUPPORT = {
331
366
  };
332
367
  /**
333
368
  * Recursively find all source files in a directory.
369
+ *
370
+ * `dir` must be forward-slash, and the returned paths are forward-slash too:
371
+ * each entry is joined with `path.posix.join`, which only stays canonical when
372
+ * the base already is. This keeps downstream substring checks (e.g.
373
+ * `f.includes("/api/")`) and reported paths consistent across platforms.
334
374
  */
335
375
  function findSourceFiles(dir, extensions = [
336
376
  ".ts",
@@ -343,7 +383,7 @@ function findSourceFiles(dir, extensions = [
343
383
  if (!fs.existsSync(dir)) return results;
344
384
  const entries = fs.readdirSync(dir, { withFileTypes: true });
345
385
  for (const entry of entries) {
346
- const fullPath = normalizePathSeparators(path.join(dir, entry.name));
386
+ const fullPath = path.posix.join(dir, entry.name);
347
387
  if (entry.isDirectory()) {
348
388
  if (entry.name === "node_modules" || entry.name === ".next" || entry.name === "dist" || entry.name === ".git") continue;
349
389
  results.push(...findSourceFiles(fullPath, extensions));
@@ -547,6 +587,10 @@ function hasFreeCjsGlobal(content) {
547
587
  }
548
588
  /**
549
589
  * Scan source files for `import ... from 'next/...'` statements.
590
+ *
591
+ * `root` must be forward-slash: it is passed to `findSourceFiles` (which
592
+ * requires it) and used as the base of `path.posix.relative`, which only yields
593
+ * a canonical relative path when both operands are forward-slash.
550
594
  */
551
595
  function scanImports(root) {
552
596
  const files = findSourceFiles(root);
@@ -564,7 +608,7 @@ function scanImports(root) {
564
608
  if (mod.startsWith("next/") || mod === "next" || mod === "server-only" || mod === "client-only") {
565
609
  const normalized = mod === "next" ? "next" : mod;
566
610
  if (!importUsage.has(normalized)) importUsage.set(normalized, []);
567
- const relFile = normalizePathSeparators(path.relative(root, file));
611
+ const relFile = path.posix.relative(root, file);
568
612
  const usedInFiles = importUsage.get(normalized) ?? [];
569
613
  if (!usedInFiles.includes(relFile)) usedInFiles.push(relFile);
570
614
  }
@@ -691,6 +735,9 @@ function collectConfigKeys(source) {
691
735
  }
692
736
  /**
693
737
  * Analyze next.config.js/mjs/ts for supported and unsupported options.
738
+ *
739
+ * `root` must be forward-slash — joined with `path.posix.join`. Only called
740
+ * from `runCheck`, which normalizes it.
694
741
  */
695
742
  function analyzeConfig(root) {
696
743
  const configFiles = [
@@ -702,7 +749,7 @@ function analyzeConfig(root) {
702
749
  ];
703
750
  let configPath = null;
704
751
  for (const f of configFiles) {
705
- const p = path.join(root, f);
752
+ const p = path.posix.join(root, f);
706
753
  if (fs.existsSync(p)) {
707
754
  configPath = p;
708
755
  break;
@@ -729,7 +776,9 @@ function analyzeConfig(root) {
729
776
  "transpilePackages",
730
777
  "webpack",
731
778
  "reactStrictMode",
732
- "poweredByHeader"
779
+ "poweredByHeader",
780
+ "skipMiddlewareUrlNormalize",
781
+ "skipProxyUrlNormalize"
733
782
  ]) {
734
783
  if (!present.top.has(opt)) continue;
735
784
  const support = CONFIG_SUPPORT[opt];
@@ -757,9 +806,12 @@ function analyzeConfig(root) {
757
806
  }
758
807
  /**
759
808
  * Check package.json dependencies for known libraries.
809
+ *
810
+ * `root` must be forward-slash — joined with `path.posix.join`. Only called
811
+ * from `runCheck`, which normalizes it.
760
812
  */
761
813
  function checkLibraries(root) {
762
- const pkgPath = path.join(root, "package.json");
814
+ const pkgPath = path.posix.join(root, "package.json");
763
815
  if (!fs.existsSync(pkgPath)) return [];
764
816
  const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
765
817
  const allDeps = {
@@ -777,17 +829,19 @@ function checkLibraries(root) {
777
829
  }
778
830
  /**
779
831
  * Check file conventions (pages, app directory, middleware, etc.)
832
+ *
833
+ * `root` must be forward-slash — joined with `path.posix.join`, passed to
834
+ * `findDir`, and used as the base of `path.posix.relative`. Only called from
835
+ * `runCheck`, which normalizes it.
780
836
  */
781
837
  function checkConventions(root) {
782
838
  const items = [];
783
- const pagesDir = findDir(root, "pages", path.join("src", "pages"));
784
- const appDirPath = findDir(root, "app", path.join("src", "app"));
785
- const hasPages = pagesDir !== null;
786
- const hasApp = appDirPath !== null;
787
- const hasProxy = fs.existsSync(path.join(root, "proxy.ts")) || fs.existsSync(path.join(root, "proxy.js"));
788
- const hasMiddleware = fs.existsSync(path.join(root, "middleware.ts")) || fs.existsSync(path.join(root, "middleware.js"));
839
+ const pagesDir = findDir(root, "pages", "src/pages");
840
+ const appDirPath = findDir(root, "app", "src/app");
841
+ const hasProxy = fs.existsSync(path.posix.join(root, "proxy.ts")) || fs.existsSync(path.posix.join(root, "proxy.js"));
842
+ const hasMiddleware = fs.existsSync(path.posix.join(root, "middleware.ts")) || fs.existsSync(path.posix.join(root, "middleware.js"));
789
843
  if (pagesDir !== null) {
790
- const isSrc = pagesDir.includes(path.join("src", "pages"));
844
+ const isSrc = pagesDir.includes("src/pages");
791
845
  items.push({
792
846
  name: isSrc ? "Pages Router (src/pages/)" : "Pages Router (pages/)",
793
847
  status: "supported"
@@ -813,7 +867,7 @@ function checkConventions(root) {
813
867
  });
814
868
  }
815
869
  if (appDirPath !== null) {
816
- const isSrc = appDirPath.includes(path.join("src", "app"));
870
+ const isSrc = appDirPath.includes("src/app");
817
871
  items.push({
818
872
  name: isSrc ? "App Router (src/app/)" : "App Router (app/)",
819
873
  status: "supported"
@@ -858,12 +912,12 @@ function checkConventions(root) {
858
912
  name: "middleware.ts (deprecated in Next.js 16)",
859
913
  status: "supported"
860
914
  });
861
- if (!hasPages && !hasApp) items.push({
915
+ if (pagesDir === null && appDirPath === null) items.push({
862
916
  name: "No pages/ or app/ directory found",
863
917
  status: "unsupported",
864
918
  detail: "vinext requires a pages/ or app/ directory"
865
919
  });
866
- const pkgPath = path.join(root, "package.json");
920
+ const pkgPath = path.posix.join(root, "package.json");
867
921
  if (fs.existsSync(pkgPath)) {
868
922
  if (JSON.parse(fs.readFileSync(pkgPath, "utf-8")).type !== "module") items.push({
869
923
  name: "Missing \"type\": \"module\" in package.json",
@@ -877,7 +931,7 @@ function checkConventions(root) {
877
931
  const cjsGlobalFiles = [];
878
932
  for (const file of allSourceFiles) {
879
933
  const content = fs.readFileSync(file, "utf-8");
880
- const rel = normalizePathSeparators(path.relative(root, file));
934
+ const rel = path.posix.relative(root, file);
881
935
  if (viewTransitionRegex.test(content)) viewTransitionFiles.push(rel);
882
936
  if (hasFreeCjsGlobal(content)) cjsGlobalFiles.push(rel);
883
937
  }
@@ -892,7 +946,7 @@ function checkConventions(root) {
892
946
  "postcss.config.js",
893
947
  "postcss.config.cjs"
894
948
  ]) {
895
- const configPath = path.join(root, configFile);
949
+ const configPath = path.posix.join(root, configFile);
896
950
  if (fs.existsSync(configPath)) {
897
951
  const content = fs.readFileSync(configPath, "utf-8");
898
952
  if (/plugins\s*:\s*\[\s*['"]/.test(content)) items.push({
@@ -913,6 +967,10 @@ function checkConventions(root) {
913
967
  }
914
968
  /**
915
969
  * Run the full compatibility check.
970
+ *
971
+ * `root` must be forward-slash — callers normalize it at the CLI entry, and it
972
+ * is forwarded to `scanImports` / `checkConventions` / `findDir`, which build
973
+ * paths with `path.posix.*`.
916
974
  */
917
975
  function runCheck(root) {
918
976
  const imports = scanImports(root);
@@ -0,0 +1,12 @@
1
+ import { Plugin, ServerOptions } from "vite";
2
+
3
+ //#region src/cli-dev-config.d.ts
4
+ type DevServerCliOptions = {
5
+ port?: number;
6
+ hostname?: string;
7
+ };
8
+ declare function applyDevServerDefaults(server: ServerOptions, options: DevServerCliOptions): void;
9
+ declare function createDevServerConfigPlugin(options: DevServerCliOptions): Plugin;
10
+ declare function normalizeDevServerHostname(host: string | boolean | undefined): string;
11
+ //#endregion
12
+ export { DevServerCliOptions, applyDevServerDefaults, createDevServerConfigPlugin, normalizeDevServerHostname };
@@ -0,0 +1,23 @@
1
+ //#region src/cli-dev-config.ts
2
+ function applyDevServerDefaults(server, options) {
3
+ server.port = options.port ?? server.port ?? 3e3;
4
+ server.host = options.hostname ?? server.host ?? "localhost";
5
+ }
6
+ function createDevServerConfigPlugin(options) {
7
+ return {
8
+ name: "vinext:dev-server-config",
9
+ enforce: "post",
10
+ config: {
11
+ order: "post",
12
+ handler(config) {
13
+ applyDevServerDefaults(config.server ??= {}, options);
14
+ }
15
+ }
16
+ };
17
+ }
18
+ function normalizeDevServerHostname(host) {
19
+ if (typeof host === "string") return host;
20
+ return host === true ? "0.0.0.0" : "localhost";
21
+ }
22
+ //#endregion
23
+ export { applyDevServerDefaults, createDevServerConfigPlugin, normalizeDevServerHostname };