vinext 1.2.0 → 1.3.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 (283) hide show
  1. package/README.md +13 -10
  2. package/dist/build/client-build-config.d.ts +64 -3
  3. package/dist/build/client-build-config.js +131 -4
  4. package/dist/build/client-reference-groups.d.ts +163 -0
  5. package/dist/build/client-reference-groups.js +534 -0
  6. package/dist/build/module-dependency-cache.d.ts +31 -0
  7. package/dist/build/module-dependency-cache.js +51 -1
  8. package/dist/build/next-client-runtime-manifests.d.ts +10 -1
  9. package/dist/build/next-client-runtime-manifests.js +19 -4
  10. package/dist/build/nitro-public-files.d.ts +24 -0
  11. package/dist/build/nitro-public-files.js +60 -0
  12. package/dist/build/output-root-externals.d.ts +21 -0
  13. package/dist/build/output-root-externals.js +40 -0
  14. package/dist/build/pages-client-assets-module.js +1 -1
  15. package/dist/build/prerender-paths.js +6 -3
  16. package/dist/build/prerender.js +1 -1
  17. package/dist/build/server-actions-encryption-key.d.ts +23 -0
  18. package/dist/build/server-actions-encryption-key.js +101 -0
  19. package/dist/build/ssr-manifest.d.ts +3 -0
  20. package/dist/build/ssr-manifest.js +10 -1
  21. package/dist/check.js +5 -6
  22. package/dist/cli-dev-config.js +3 -3
  23. package/dist/cli.js +1 -1
  24. package/dist/client/client-rewrite-params.d.ts +9 -0
  25. package/dist/client/client-rewrite-params.js +20 -0
  26. package/dist/client/dev-error-overlay.js +2 -1
  27. package/dist/client/navigation-runtime.d.ts +25 -2
  28. package/dist/client/navigation-runtime.js +42 -11
  29. package/dist/client/vinext-next-data.d.ts +0 -1
  30. package/dist/config/config-matchers.d.ts +15 -40
  31. package/dist/config/config-matchers.js +195 -262
  32. package/dist/config/config-source.d.ts +34 -0
  33. package/dist/config/config-source.js +141 -0
  34. package/dist/config/header-params.d.ts +29 -0
  35. package/dist/config/header-params.js +106 -0
  36. package/dist/config/next-config.d.ts +7 -5
  37. package/dist/config/next-config.js +120 -7
  38. package/dist/entries/app-browser-entry.d.ts +14 -1
  39. package/dist/entries/app-browser-entry.js +26 -36
  40. package/dist/entries/app-rsc-entry.d.ts +2 -0
  41. package/dist/entries/app-rsc-entry.js +92 -57
  42. package/dist/entries/app-rsc-manifest.d.ts +10 -0
  43. package/dist/entries/app-rsc-manifest.js +20 -1
  44. package/dist/entries/app-ssr-entry.d.ts +4 -1
  45. package/dist/entries/app-ssr-entry.js +9 -2
  46. package/dist/entries/pages-client-entry.d.ts +1 -0
  47. package/dist/entries/pages-client-entry.js +6 -6
  48. package/dist/entries/pages-server-entry.js +17 -14
  49. package/dist/index.d.ts +11 -0
  50. package/dist/index.js +350 -175
  51. package/dist/init.d.ts +1 -1
  52. package/dist/init.js +103 -6
  53. package/dist/plugins/ast-utils.d.ts +53 -2
  54. package/dist/plugins/ast-utils.js +90 -2
  55. package/dist/plugins/cloudflare-dev-module-urls.d.ts +41 -0
  56. package/dist/plugins/cloudflare-dev-module-urls.js +271 -0
  57. package/dist/plugins/commonjs-esm-facade.js +2 -2
  58. package/dist/plugins/css-module-imports.js +13 -20
  59. package/dist/plugins/dynamic-preload-metadata.js +2 -3
  60. package/dist/plugins/extensionless-dynamic-import.js +2 -3
  61. package/dist/plugins/fonts.d.ts +1 -1
  62. package/dist/plugins/fonts.js +3 -3
  63. package/dist/plugins/ignore-dynamic-requests.js +2 -3
  64. package/dist/plugins/import-meta-url.js +3 -4
  65. package/dist/plugins/instrumentation-client.js +3 -2
  66. package/dist/plugins/middleware-export-validation.js +2 -3
  67. package/dist/plugins/og-harfbuzz.js +2 -3
  68. package/dist/plugins/optimize-imports.d.ts +25 -2
  69. package/dist/plugins/optimize-imports.js +109 -24
  70. package/dist/plugins/pages-node-externals.js +2 -3
  71. package/dist/plugins/remove-console.js +2 -18
  72. package/dist/plugins/require-condition-resolution.js +3 -3
  73. package/dist/plugins/require-context.js +2 -3
  74. package/dist/plugins/rsc-client-reference-loaders.d.ts +45 -1
  75. package/dist/plugins/rsc-client-reference-loaders.js +336 -18
  76. package/dist/plugins/strip-server-exports.js +3 -4
  77. package/dist/plugins/styled-jsx.js +2 -3
  78. package/dist/plugins/use-cache-callable.d.ts +26 -2
  79. package/dist/plugins/use-cache-callable.js +101 -36
  80. package/dist/plugins/worker-image-imports.d.ts +1 -0
  81. package/dist/plugins/worker-image-imports.js +31 -34
  82. package/dist/plugins/worker-use-server.js +38 -14
  83. package/dist/routing/app-route-graph.d.ts +1 -1
  84. package/dist/routing/browser-route-manifest.d.ts +43 -0
  85. package/dist/routing/browser-route-manifest.js +195 -0
  86. package/dist/routing/hashed-route-patterns.d.ts +4 -0
  87. package/dist/routing/hashed-route-patterns.js +22 -0
  88. package/dist/routing/optimistic-route-trie.d.ts +27 -0
  89. package/dist/routing/optimistic-route-trie.js +102 -0
  90. package/dist/routing/route-validation.d.ts +6 -1
  91. package/dist/routing/route-validation.js +26 -10
  92. package/dist/server/api-handler.js +1 -1
  93. package/dist/server/app-action-forwarding.d.ts +8 -0
  94. package/dist/server/app-action-forwarding.js +17 -3
  95. package/dist/server/app-browser-entry.js +149 -62
  96. package/dist/server/app-browser-error.d.ts +3 -1
  97. package/dist/server/app-browser-error.js +7 -2
  98. package/dist/server/app-browser-interception-context.d.ts +2 -2
  99. package/dist/server/app-browser-interception-context.js +1 -1
  100. package/dist/server/app-browser-mpa-navigation.d.ts +1 -0
  101. package/dist/server/app-browser-mpa-navigation.js +6 -5
  102. package/dist/server/app-browser-navigation-controller.d.ts +17 -6
  103. package/dist/server/app-browser-navigation-controller.js +88 -26
  104. package/dist/server/app-browser-prefetch-response.js +2 -2
  105. package/dist/server/app-browser-state.d.ts +2 -2
  106. package/dist/server/app-browser-state.js +1 -1
  107. package/dist/server/app-browser-supplemental-refresh.js +1 -1
  108. package/dist/server/app-browser-visible-commit.d.ts +4 -4
  109. package/dist/server/app-client-reference-preloader.d.ts +23 -0
  110. package/dist/server/app-client-reference-preloader.js +30 -7
  111. package/dist/server/app-fallback-renderer.js +2 -1
  112. package/dist/server/app-middleware.d.ts +6 -0
  113. package/dist/server/app-middleware.js +8 -10
  114. package/dist/server/app-optimistic-routing.d.ts +8 -10
  115. package/dist/server/app-optimistic-routing.js +4 -95
  116. package/dist/server/app-page-boundary-render.js +8 -1
  117. package/dist/server/app-page-cache-render.js +1 -0
  118. package/dist/server/app-page-dispatch.js +3 -1
  119. package/dist/server/app-page-render.js +4 -2
  120. package/dist/server/app-page-rsc-render-status.d.ts +1 -0
  121. package/dist/server/app-page-rsc-render-status.js +1 -0
  122. package/dist/server/app-page-search-params-observation.d.ts +1 -4
  123. package/dist/server/app-page-search-params-observation.js +8 -10
  124. package/dist/server/app-page-stream.d.ts +7 -0
  125. package/dist/server/app-page-stream.js +1 -0
  126. package/dist/server/app-pages-bridge.d.ts +2 -1
  127. package/dist/server/app-pages-bridge.js +12 -8
  128. package/dist/server/app-prerender-endpoints.js +1 -1
  129. package/dist/server/app-prerender-static-params.js +3 -2
  130. package/dist/server/app-render-abort-error.d.ts +19 -0
  131. package/dist/server/app-render-abort-error.js +31 -1
  132. package/dist/server/app-render-dependency.js +42 -2
  133. package/dist/server/app-request-stage-independent-entry.js +7 -7
  134. package/dist/server/app-response-stage-entry.js +5 -5
  135. package/dist/server/app-route-handler-dispatch.js +3 -1
  136. package/dist/server/app-route-handler-execution.d.ts +2 -0
  137. package/dist/server/app-route-handler-execution.js +9 -2
  138. package/dist/server/app-route-handler-middleware-context.d.ts +2 -1
  139. package/dist/server/app-route-handler-middleware-context.js +3 -3
  140. package/dist/server/app-route-handler-response.d.ts +2 -1
  141. package/dist/server/app-route-handler-response.js +2 -2
  142. package/dist/server/app-route-handler-runtime.d.ts +2 -0
  143. package/dist/server/app-route-handler-runtime.js +21 -4
  144. package/dist/server/app-route-module-loader.js +7 -6
  145. package/dist/server/app-route-tree.d.ts +20 -0
  146. package/dist/server/app-route-tree.js +18 -0
  147. package/dist/server/app-router-entry.js +7 -7
  148. package/dist/server/app-rsc-cache-busting.d.ts +16 -0
  149. package/dist/server/app-rsc-cache-busting.js +29 -12
  150. package/dist/server/app-rsc-combined-handler.js +8 -1
  151. package/dist/server/app-rsc-errors.d.ts +7 -0
  152. package/dist/server/app-rsc-errors.js +9 -2
  153. package/dist/server/app-rsc-handler.d.ts +4 -1
  154. package/dist/server/app-rsc-handler.js +151 -135
  155. package/dist/server/app-rsc-request-normalization.js +3 -3
  156. package/dist/server/app-rsc-response-finalizer.d.ts +5 -0
  157. package/dist/server/app-rsc-response-finalizer.js +4 -1
  158. package/dist/server/app-rsc-response-stage.js +5 -3
  159. package/dist/server/app-rsc-route-matching.d.ts +1 -0
  160. package/dist/server/app-rsc-route-matching.js +1 -1
  161. package/dist/server/app-server-action-execution.d.ts +23 -6
  162. package/dist/server/app-server-action-execution.js +51 -57
  163. package/dist/server/app-ssr-entry.d.ts +6 -0
  164. package/dist/server/app-ssr-entry.js +21 -11
  165. package/dist/server/app-ssr-stream.d.ts +7 -0
  166. package/dist/server/app-ssr-stream.js +13 -1
  167. package/dist/server/app-visited-response-cache.js +2 -2
  168. package/dist/server/config-headers.js +13 -4
  169. package/dist/server/defer-until-stream-consumed.d.ts +2 -1
  170. package/dist/server/defer-until-stream-consumed.js +3 -1
  171. package/dist/server/dev-server.js +1 -1
  172. package/dist/server/image-optimization.js +1 -0
  173. package/dist/server/isolate-shared-promise.d.ts +10 -0
  174. package/dist/server/isolate-shared-promise.js +33 -0
  175. package/dist/server/isr-cache.js +3 -2
  176. package/dist/server/metadata-route-response.js +2 -2
  177. package/dist/server/middleware-matcher-pattern.d.ts +0 -1
  178. package/dist/server/middleware-matcher-pattern.js +11 -140
  179. package/dist/server/middleware-matcher.js +5 -6
  180. package/dist/server/middleware-response-headers.d.ts +31 -0
  181. package/dist/server/middleware-response-headers.js +57 -1
  182. package/dist/server/middleware-runtime.js +30 -17
  183. package/dist/server/navigation-planner.d.ts +2 -2
  184. package/dist/server/navigation-planner.js +1 -1
  185. package/dist/server/nitro-public-files-plugin.d.ts +38 -0
  186. package/dist/server/nitro-public-files-plugin.js +106 -0
  187. package/dist/server/nitro-public-files.d.ts +21 -0
  188. package/dist/server/nitro-public-files.js +39 -0
  189. package/dist/server/open-redirect.d.ts +11 -4
  190. package/dist/server/open-redirect.js +11 -4
  191. package/dist/server/pages-api-route.js +2 -2
  192. package/dist/server/pages-asset-tags.d.ts +5 -0
  193. package/dist/server/pages-asset-tags.js +9 -2
  194. package/dist/server/pages-client-assets.d.ts +4 -1
  195. package/dist/server/pages-data-route.js +2 -1
  196. package/dist/server/pages-i18n.d.ts +18 -0
  197. package/dist/server/pages-i18n.js +18 -2
  198. package/dist/server/pages-node-compat.d.ts +5 -3
  199. package/dist/server/pages-node-compat.js +35 -16
  200. package/dist/server/pages-page-data.js +1 -1
  201. package/dist/server/pages-page-handler.js +1 -1
  202. package/dist/server/pages-page-response.js +1 -1
  203. package/dist/server/pages-request-pipeline.d.ts +6 -1
  204. package/dist/server/pages-request-pipeline.js +35 -39
  205. package/dist/server/pages-request-stage-entry.js +20 -10
  206. package/dist/server/pages-response-stage-entry.js +1 -1
  207. package/dist/server/pages-revalidate.js +3 -2
  208. package/dist/server/pages-router-entry.js +2 -2
  209. package/dist/server/prod-server.d.ts +2 -2
  210. package/dist/server/prod-server.js +74 -36
  211. package/dist/server/proxy-trust.d.ts +6 -0
  212. package/dist/server/proxy-trust.js +12 -6
  213. package/dist/server/request-pipeline.d.ts +5 -0
  214. package/dist/server/request-pipeline.js +12 -1
  215. package/dist/server/rsc-stream-hints.d.ts +1 -1
  216. package/dist/server/rsc-stream-hints.js +21 -3
  217. package/dist/server/server-reference-loader.js +10 -1
  218. package/dist/server/static-file-cache.js +15 -3
  219. package/dist/server/worker-image-optimization.js +19 -6
  220. package/dist/server/worker-utils.js +1 -1
  221. package/dist/shims/cache-handler.js +3 -2
  222. package/dist/shims/cache-request-state.d.ts +40 -3
  223. package/dist/shims/cache-request-state.js +70 -5
  224. package/dist/shims/cache-runtime.js +47 -19
  225. package/dist/shims/cache.d.ts +2 -2
  226. package/dist/shims/cache.js +17 -8
  227. package/dist/shims/cdn-purge-routes.d.ts +24 -0
  228. package/dist/shims/cdn-purge-routes.js +77 -0
  229. package/dist/shims/dynamic.js +17 -4
  230. package/dist/shims/form.js +8 -3
  231. package/dist/shims/head.js +1 -1
  232. package/dist/shims/headers.js +2 -2
  233. package/dist/shims/image-props.d.ts +93 -0
  234. package/dist/shims/image-props.js +323 -0
  235. package/dist/shims/image.d.ts +4 -18
  236. package/dist/shims/image.js +4 -319
  237. package/dist/shims/internal/headers-state.d.ts +7 -0
  238. package/dist/shims/internal/headers-state.js +14 -2
  239. package/dist/shims/internal/hybrid-client-route-owner-direct.d.ts +4 -1
  240. package/dist/shims/internal/hybrid-client-route-owner-direct.js +32 -15
  241. package/dist/shims/internal/hybrid-client-route-owner.js +9 -8
  242. package/dist/shims/link-prefetch.js +5 -4
  243. package/dist/shims/link.js +7 -5
  244. package/dist/shims/navigation.d.ts +1 -1
  245. package/dist/shims/navigation.js +21 -10
  246. package/dist/shims/og.js +35 -10
  247. package/dist/shims/request-context.d.ts +13 -0
  248. package/dist/shims/router.js +28 -52
  249. package/dist/shims/server.d.ts +42 -8
  250. package/dist/shims/server.js +99 -15
  251. package/dist/shims/thenable-params.d.ts +6 -1
  252. package/dist/shims/thenable-params.js +11 -2
  253. package/dist/shims/unified-request-context.d.ts +5 -0
  254. package/dist/shims/unified-request-context.js +2 -0
  255. package/dist/shims/url-utils.d.ts +7 -0
  256. package/dist/shims/url-utils.js +12 -3
  257. package/dist/utils/asset-prefix.d.ts +7 -0
  258. package/dist/utils/asset-prefix.js +10 -1
  259. package/dist/utils/client-build-manifest.js +12 -5
  260. package/dist/utils/client-runtime-metadata.d.ts +1 -0
  261. package/dist/utils/client-runtime-metadata.js +15 -2
  262. package/dist/utils/domain-locale.js +1 -1
  263. package/dist/utils/lazy-chunks.d.ts +4 -0
  264. package/dist/utils/manifest-paths.d.ts +14 -0
  265. package/dist/utils/manifest-paths.js +22 -1
  266. package/dist/utils/path-to-regexp.d.ts +21 -0
  267. package/dist/{server/middleware-path-to-regexp.js → utils/path-to-regexp.js} +14 -11
  268. package/dist/utils/plugin-react-version.d.ts +15 -0
  269. package/dist/utils/plugin-react-version.js +64 -0
  270. package/dist/utils/plugin-rsc-version.d.ts +2 -0
  271. package/dist/utils/plugin-rsc-version.js +28 -2
  272. package/dist/utils/public-routes.d.ts +2 -0
  273. package/dist/utils/public-routes.js +18 -7
  274. package/dist/utils/react-version.d.ts +7 -0
  275. package/dist/utils/react-version.js +39 -16
  276. package/package.json +6 -6
  277. package/dist/build/nitro-route-rules.d.ts +0 -47
  278. package/dist/build/nitro-route-rules.js +0 -79
  279. package/dist/plugins/cache-flight-codec.d.ts +0 -19
  280. package/dist/plugins/cache-flight-codec.js +0 -68
  281. package/dist/server/middleware-path-to-regexp.d.ts +0 -13
  282. package/dist/utils/regex-safety.d.ts +0 -17
  283. package/dist/utils/regex-safety.js +0 -789
package/dist/init.d.ts CHANGED
@@ -70,7 +70,7 @@ export type InitDependencyGroups = {
70
70
  dependencies: string[];
71
71
  devDependencies: string[];
72
72
  };
73
- export declare function getInitDependencyGroups(isAppRouter: boolean, platform: InitPlatform, cloudflare?: CloudflareInitOptions, hasCssModules?: boolean): InitDependencyGroups;
73
+ export declare function getInitDependencyGroups(isAppRouter: boolean, platform: InitPlatform, cloudflare?: CloudflareInitOptions, hasCssModules?: boolean, tailwindPostcss?: boolean): InitDependencyGroups;
74
74
  export declare function getInitDeps(isAppRouter: boolean, platform: InitPlatform, cloudflare?: CloudflareInitOptions, hasCssModules?: boolean): string[];
75
75
  export declare function isDepInstalled(root: string, dep: string): boolean;
76
76
  /**
package/dist/init.js CHANGED
@@ -2,6 +2,7 @@ import path, { toSlash } from "./deps/.pnpm/pathslash@0.1.0/deps/pathslash/dist/
2
2
  import { detectPackageManager, detectPackageManagerName, detectProject, ensureESModule, findViteConfigPath, hasViteConfig, renameCJSConfigs } from "./utils/project.js";
3
3
  import { compactResourceName, cssModulesConfigSource, findConfigKeepingWorkerName, setupCloudflarePlatform, updateViteConfigForCssModules, usesCommonJsViteConfig, validateCloudflarePlatformSetup } from "./init-cloudflare.js";
4
4
  import { getReactUpgradeDeps } from "./utils/react-version.js";
5
+ import { getPluginReactUpgradeDeps } from "./utils/plugin-react-version.js";
5
6
  import fs from "node:fs";
6
7
  import { spawn, spawnSync } from "node:child_process";
7
8
  //#region src/init.ts
@@ -14,7 +15,8 @@ import { spawn, spawnSync } from "node:child_process";
14
15
  * 2. Add "type": "module" to package.json
15
16
  * 3. Rename CJS config files to .cjs
16
17
  * 4. Add vinext scripts to package.json
17
- * 5. Generate vite.config.ts and platform files
18
+ * 5. Generate vite.config.ts and platform files, plus a Tailwind PostCSS
19
+ * config when Tailwind is only set up as a Turbopack loader
18
20
  * 6. Update .gitignore to include /dist/ and .vinext/
19
21
  * 7. Install dependencies (vite, @vitejs/plugin-react, and App Router deps)
20
22
  * 8. Print summary
@@ -94,6 +96,77 @@ function scanCssModuleFiles(root) {
94
96
  exclude: (entry) => entry.isDirectory() && (CSS_MODULE_IGNORES.has(entry.name) || toSlash(entry.parentPath) === canonicalRoot && CSS_MODULE_ROOT_IGNORES.has(entry.name))
95
97
  }).some((entry) => /\.module\.(css|scss|sass)$/.test(entry.name));
96
98
  }
99
+ const NEXT_CONFIG_FILES = [
100
+ "next.config.ts",
101
+ "next.config.mts",
102
+ "next.config.mjs",
103
+ "next.config.js",
104
+ "next.config.cjs"
105
+ ];
106
+ const TAILWIND_LOADERS = ["@tailwindcss/turbopack", "@tailwindcss/webpack"];
107
+ const TAILWIND_POSTCSS_CONFIG = `const config = {
108
+ plugins: {
109
+ "@tailwindcss/postcss": {},
110
+ },
111
+ };
112
+
113
+ export default config;
114
+ `;
115
+ /**
116
+ * Whether the project gets Tailwind from a Turbopack loader (as create-next-app
117
+ * 16.4+ sets up in `turbopack.rules`) rather than from PostCSS, which is the
118
+ * only way vinext compiles Tailwind. The config is not evaluated: a Next config
119
+ * that names the loader, or a declared loader package, is enough.
120
+ */
121
+ function usesTailwindTurbopackLoader(root) {
122
+ for (const file of NEXT_CONFIG_FILES) {
123
+ const configPath = path.join(root, file);
124
+ if (!fs.existsSync(configPath)) continue;
125
+ const source = fs.readFileSync(configPath, "utf-8");
126
+ if (TAILWIND_LOADERS.some((loader) => source.includes(loader))) return true;
127
+ }
128
+ return TAILWIND_LOADERS.some((loader) => isDepInstalled(root, loader));
129
+ }
130
+ const POSTCSS_CONFIG_SEARCH_ORDER = [
131
+ ".postcssrc",
132
+ ".postcssrc.json",
133
+ ".postcssrc.yaml",
134
+ ".postcssrc.yml",
135
+ ".postcssrc.ts",
136
+ ".postcssrc.cts",
137
+ ".postcssrc.mts",
138
+ ".postcssrc.js",
139
+ ".postcssrc.cjs",
140
+ ".postcssrc.mjs",
141
+ "postcss.config.ts",
142
+ "postcss.config.cts",
143
+ "postcss.config.mts",
144
+ "postcss.config.js",
145
+ "postcss.config.cjs",
146
+ "postcss.config.mjs"
147
+ ];
148
+ /** The source of the PostCSS config Vite would load, which init never replaces. */
149
+ function readPostcssConfig(root) {
150
+ try {
151
+ const pkg = JSON.parse(fs.readFileSync(path.join(root, "package.json"), "utf-8"));
152
+ if (pkg.postcss) return JSON.stringify(pkg.postcss);
153
+ } catch {}
154
+ for (const file of POSTCSS_CONFIG_SEARCH_ORDER) {
155
+ const configPath = path.join(root, file);
156
+ if (!fs.existsSync(configPath)) continue;
157
+ const source = fs.readFileSync(configPath, "utf-8");
158
+ if (source.trim() !== "") return source;
159
+ }
160
+ }
161
+ function getTailwindPostcssSetup(root, viteConfigPath) {
162
+ if (!usesTailwindTurbopackLoader(root)) return "none";
163
+ const viteConfig = viteConfigPath ? fs.readFileSync(viteConfigPath, "utf-8") : "";
164
+ const config = /postcss|lightningcss|tailwindcss/.test(viteConfig) ? viteConfig : readPostcssConfig(root);
165
+ if (config === void 0) return "generate";
166
+ if (/lightningcss/.test(config) && !config.includes("@tailwindcss/vite")) return "manual";
167
+ if (config.includes("@tailwindcss/postcss")) return "install";
168
+ return config.includes("tailwindcss") ? "none" : "manual";
169
+ }
97
170
  /**
98
171
  * Add Vite scripts to package.json without overwriting custom scripts.
99
172
  * Exact scripts generated by older vinext versions are migrated in place.
@@ -133,7 +206,7 @@ function addScripts(root, port, platform = "node", options = {}) {
133
206
  return [];
134
207
  }
135
208
  }
136
- function getInitDependencyGroups(isAppRouter, platform, cloudflare, hasCssModules = false) {
209
+ function getInitDependencyGroups(isAppRouter, platform, cloudflare, hasCssModules = false, tailwindPostcss = false) {
137
210
  const dependencies = ["vinext"];
138
211
  const devDependencies = ["vite", "@vitejs/plugin-react"];
139
212
  if (isAppRouter) {
@@ -149,6 +222,7 @@ function getInitDependencyGroups(isAppRouter, platform, cloudflare, hasCssModule
149
222
  } else devDependencies.push("@cloudflare/vite-plugin@1", "wrangler");
150
223
  }
151
224
  if (hasCssModules) devDependencies.push("vite-css-modules", "postcss");
225
+ if (tailwindPostcss) devDependencies.push("@tailwindcss/postcss");
152
226
  return {
153
227
  dependencies,
154
228
  devDependencies
@@ -227,7 +301,7 @@ function addDependencyEntries(root, deps, { dev }) {
227
301
  * Check if react/react-dom need upgrading for react-server-dom-webpack compatibility.
228
302
  *
229
303
  * react-server-dom-webpack versions are pinned to match their React version
230
- * (e.g. rsdw@19.2.6 requires react@^19.2.6). When a project has an older
304
+ * (e.g. rsdw@19.3.1 requires react@^19.3.1). When a project has an older
231
305
  * React (e.g. create-next-app ships react@19.2.3), we need to upgrade
232
306
  * react/react-dom BEFORE installing rsdw to avoid peer-dep conflicts.
233
307
  *
@@ -445,6 +519,7 @@ async function init(options) {
445
519
  const viteConfigExists = hasViteConfig(root);
446
520
  const isApp = detectProject(root).isAppRouter;
447
521
  const hasCssModules = !options.skipCssModules && scanCssModuleFiles(root);
522
+ const tailwindPostcssSetup = getTailwindPostcssSetup(root, platform === "node" && options.force ? void 0 : existingViteConfigPath);
448
523
  const pmName = detectPackageManagerName(root);
449
524
  const shouldInstall = options.install ?? true;
450
525
  const isStaticExport = platform === "cloudflare" && await resolvesToStaticExport(root, existingViteConfigPath);
@@ -495,15 +570,19 @@ async function init(options) {
495
570
  };
496
571
  const platformSetup = platform === "cloudflare" ? setupCloudflarePlatform(setupContext, cloudflareOptions) : setupNodePlatform(setupContext);
497
572
  const { generatedViteConfig, skippedViteConfig, generatedPlatformFiles } = platformSetup;
573
+ if (tailwindPostcssSetup === "generate") fs.writeFileSync(path.join(root, "postcss.config.mjs"), TAILWIND_POSTCSS_CONFIG, "utf-8");
498
574
  const updatedGitignore = updateGitignore(root, platform, options.cloudflare?.legacyWrangler);
499
- const neededDeps = getInitDependencyGroups(isApp, platform, options.cloudflare, hasCssModules);
575
+ const neededDeps = getInitDependencyGroups(isApp, platform, options.cloudflare, hasCssModules, tailwindPostcssSetup === "generate" || tailwindPostcssSetup === "install");
500
576
  const missingDependencies = neededDeps.dependencies.filter((dep) => !isDepInstalled(root, dep));
501
577
  const missingDevDependencies = neededDeps.devDependencies.filter((dep) => !isDepInstalled(root, dep));
502
578
  let dependencyInstallNeedsApproval = false;
503
579
  const dependencyEntriesAdded = [];
504
580
  const devDependencyEntriesAdded = [];
505
- if (isApp && (!shouldInstall || missingDependencies.includes("react-server-dom-webpack"))) {
506
- const reactUpgrade = getReactUpgradeDeps(root, { fromManifest: !shouldInstall });
581
+ if (isApp) {
582
+ const reactUpgrade = shouldInstall ? [.../* @__PURE__ */ new Set([...getReactUpgradeDeps(root), ...getReactUpgradeDeps(root, {
583
+ fromManifest: true,
584
+ installing: true
585
+ })])] : getReactUpgradeDeps(root, { fromManifest: true });
507
586
  if (reactUpgrade.length > 0) {
508
587
  console.log(` ${terminalStyle.cyan(terminalStyle.bold("Upgrading dependencies:"))}`);
509
588
  console.log(formatList(reactUpgrade.map((dep) => dep.replace(/@latest$/, "")), " "));
@@ -520,6 +599,22 @@ async function init(options) {
520
599
  }
521
600
  }
522
601
  }
602
+ const pluginReactUpgrade = getPluginReactUpgradeDeps(root);
603
+ if (pluginReactUpgrade.length > 0) {
604
+ console.log(` ${terminalStyle.cyan(terminalStyle.bold("Upgrading devDependencies:"))}`);
605
+ console.log(formatList(pluginReactUpgrade.map((dep) => dep.replace(/@latest$/, "")), " "));
606
+ try {
607
+ if (shouldInstall) {
608
+ if (isApproveBuildsError(await installDeps(root, pluginReactUpgrade, exec))) dependencyInstallNeedsApproval = true;
609
+ } else {
610
+ const added = addDependencyEntries(root, pluginReactUpgrade, { dev: true });
611
+ devDependencyEntriesAdded.push(...added);
612
+ }
613
+ } catch (error) {
614
+ if (pmName !== "pnpm" || !isApproveBuildsError(error)) throw error;
615
+ dependencyInstallNeedsApproval = true;
616
+ }
617
+ }
523
618
  if (missingDependencies.length > 0) {
524
619
  console.log(` ${terminalStyle.cyan(terminalStyle.bold("Installing dependencies:"))}`);
525
620
  console.log(formatList(missingDependencies, " "));
@@ -576,6 +671,8 @@ async function init(options) {
576
671
  if (skippedViteConfig) console.log(` ${terminalStyle.yellow("-")} Skipped vite.config.ts (already exists, use --force to overwrite)`);
577
672
  if (updatedGitignore) console.log(` ${terminalStyle.green("✓")} Added vinext output directories to .gitignore`);
578
673
  if (hasCssModules) console.log(` ${terminalStyle.green("✓")} Configured vite-css-modules for CSS Modules`);
674
+ if (tailwindPostcssSetup === "generate") console.log(` ${terminalStyle.green("✓")} Generated postcss.config.mjs for Tailwind CSS (vinext does not run turbopack.rules loaders)`);
675
+ else if (tailwindPostcssSetup === "manual") console.log(` ${terminalStyle.yellow("!")} Tailwind CSS is set up as a Turbopack loader, which vinext does not run; set up "@tailwindcss/postcss" or "@tailwindcss/vite" for vinext`);
579
676
  if (configKeepingWorkerName) console.log(` ${terminalStyle.yellow("!")} Kept the Worker name in the existing ${configKeepingWorkerName}; --name was not applied, so update it there if it should be "${cloudflareOptions.name}"`);
580
677
  if (platformSetup.preservedExistingGenerateScopedName) console.log(` ${terminalStyle.yellow("!")} Preserved existing css.modules.generateScopedName; verify it produces identical class names in SSR and client builds`);
581
678
  const nextSteps = [...platformSetup.nextSteps];
@@ -1,4 +1,4 @@
1
- import { ESTree } from "vite";
1
+ import { ESTree, ParseResult, ParserOptions } from "vite";
2
2
  //#region src/plugins/ast-utils.d.ts
3
3
  export type ScriptParserLanguage = "js" | "jsx" | "ts" | "tsx";
4
4
  export declare const SCRIPT_MODULE_ID_RE: RegExp;
@@ -8,7 +8,7 @@ export declare const SCRIPT_MODULE_ID_RE: RegExp;
8
8
  * Static imports — `import x from "..."`, `import { ... } from "..."`,
9
9
  * `import "..."` — never place a `(` (nor a comment leading to one) immediately
10
10
  * after the `import` keyword. Plugins that act only on dynamic `import(...)` use
11
- * this to skip `parseAst` for the overwhelming majority of modules in a large
11
+ * this to skip parsing for the overwhelming majority of modules in a large
12
12
  * app: at ~5k routes, where almost every module is a static-import-only page,
13
13
  * it removes most of the build's AST-parse/GC cost. This is a deliberate,
14
14
  * measured performance filter — keep it a regex, never a parse.
@@ -36,6 +36,57 @@ export declare function mayContainDynamicImport(code: string): boolean;
36
36
  * necessarily been lowered.
37
37
  */
38
38
  export declare function scriptParserLanguage(id: string): ScriptParserLanguage | null;
39
+ /** The import/export record oxc builds alongside the AST. */
40
+ export type ModuleRecord = ParseResult["module"];
41
+ /**
42
+ * Parse `code` into an ESTree program, throwing on syntax errors.
43
+ *
44
+ * Replaces Vite's deprecated `parseAst` with the same defaults and contract.
45
+ * Callers that only need import/export declarations should use
46
+ * {@link parseModuleRecord}, which skips building the JS AST.
47
+ */
48
+ export declare function parseProgram(code: string, options?: ParserOptions): ESTree.Program;
49
+ /** Async {@link parseProgram}; replaces Vite's deprecated `parseAstAsync`. */
50
+ export declare function parseProgramAsync(code: string, options?: ParserOptions): Promise<ESTree.Program>;
51
+ /**
52
+ * Parse `code` and return only its static import/export and dynamic import
53
+ * record, or `null` when it has syntax errors.
54
+ *
55
+ * Reading the record never deserializes the JS AST, which is most of the cost
56
+ * of a parse (about 4x cheaper than {@link parseProgram} on large modules).
57
+ * The record omits import attributes; see {@link hasImportAttributes}.
58
+ */
59
+ export declare function parseModuleRecord(code: string, lang: ParserOptions["lang"]): ModuleRecord | null;
60
+ /**
61
+ * One whitespace character or comment. Each alternative can only match one
62
+ * way (a block comment stops at the first `*\/`, a line comment runs to the
63
+ * line end), so repeating it cannot backtrack exponentially.
64
+ */
65
+ export declare const TRIVIA_PATTERN: string;
66
+ /** Leading whitespace and comments. */
67
+ export declare const LEADING_TRIVIA_RE: RegExp;
68
+ /**
69
+ * Whether the static import/export statement ending at `statementEnd` has
70
+ * `with { ... }` (or legacy `assert { ... }`) attributes after its source
71
+ * string, which ends at `sourceEnd`. The module record does not report
72
+ * attributes.
73
+ */
74
+ export declare function hasImportAttributes(code: string, sourceEnd: number, statementEnd: number): boolean;
75
+ /**
76
+ * Whether a static import is erased by TypeScript: every binding is
77
+ * type-only, or it is `import type {} from "x"`, which the module record
78
+ * reports with no entries (like a runtime `import {} from "x"`).
79
+ */
80
+ export declare function isTypeOnlyImport(code: string, statement: ModuleRecord["staticImports"][number]): boolean;
81
+ /**
82
+ * The value of the string literal or expression-free template literal spanning
83
+ * `span`, or `null` for any other expression. The module record gives only the
84
+ * span of a dynamic import's source.
85
+ */
86
+ export declare function quotedStringAt(code: string, span: {
87
+ start: number;
88
+ end: number;
89
+ }): string | null;
39
90
  export declare function isIdentifierNamed(value: ESTree.Node | null | undefined, name: string): boolean;
40
91
  export declare function getAstName(node: ESTree.Node | null | undefined): string | null;
41
92
  /** Remove syntax-only wrappers while preserving the underlying expression. */
@@ -1,3 +1,4 @@
1
+ import { parse, parseSync } from "vite";
1
2
  //#region src/plugins/ast-utils.ts
2
3
  const SCRIPT_MODULE_EXTENSION_RE = /^\.(?:[cm]?[jt]s|[jt]sx)$/i;
3
4
  const SCRIPT_MODULE_ID_RE = /\.(?:[cm]?[jt]s|[jt]sx)(?:[?#].*)?$/i;
@@ -7,7 +8,7 @@ const SCRIPT_MODULE_ID_RE = /\.(?:[cm]?[jt]s|[jt]sx)(?:[?#].*)?$/i;
7
8
  * Static imports — `import x from "..."`, `import { ... } from "..."`,
8
9
  * `import "..."` — never place a `(` (nor a comment leading to one) immediately
9
10
  * after the `import` keyword. Plugins that act only on dynamic `import(...)` use
10
- * this to skip `parseAst` for the overwhelming majority of modules in a large
11
+ * this to skip parsing for the overwhelming majority of modules in a large
11
12
  * app: at ~5k routes, where almost every module is a static-import-only page,
12
13
  * it removes most of the build's AST-parse/GC cost. This is a deliberate,
13
14
  * measured performance filter — keep it a regex, never a parse.
@@ -46,6 +47,93 @@ function scriptParserLanguage(id) {
46
47
  if (extension === ".tsx") return "tsx";
47
48
  return "jsx";
48
49
  }
50
+ const PROGRAM_PARSER_DEFAULTS = {
51
+ lang: "js",
52
+ preserveParens: false
53
+ };
54
+ const PARSE_FILENAME = "file.js";
55
+ function programOrThrow(result) {
56
+ if (result.errors.length > 0) {
57
+ const frames = result.errors.slice(0, 5).map((error) => error.codeframe ?? error.message);
58
+ throw new SyntaxError(`Parse failed with ${result.errors.length} error${result.errors.length === 1 ? "" : "s"}:\n${frames.join("\n")}`);
59
+ }
60
+ return result.program;
61
+ }
62
+ /**
63
+ * Parse `code` into an ESTree program, throwing on syntax errors.
64
+ *
65
+ * Replaces Vite's deprecated `parseAst` with the same defaults and contract.
66
+ * Callers that only need import/export declarations should use
67
+ * {@link parseModuleRecord}, which skips building the JS AST.
68
+ */
69
+ function parseProgram(code, options) {
70
+ return programOrThrow(parseSync(PARSE_FILENAME, code, {
71
+ ...PROGRAM_PARSER_DEFAULTS,
72
+ ...options
73
+ }));
74
+ }
75
+ /** Async {@link parseProgram}; replaces Vite's deprecated `parseAstAsync`. */
76
+ async function parseProgramAsync(code, options) {
77
+ return programOrThrow(await parse(PARSE_FILENAME, code, {
78
+ ...PROGRAM_PARSER_DEFAULTS,
79
+ ...options
80
+ }));
81
+ }
82
+ /**
83
+ * Parse `code` and return only its static import/export and dynamic import
84
+ * record, or `null` when it has syntax errors.
85
+ *
86
+ * Reading the record never deserializes the JS AST, which is most of the cost
87
+ * of a parse (about 4x cheaper than {@link parseProgram} on large modules).
88
+ * The record omits import attributes; see {@link hasImportAttributes}.
89
+ */
90
+ function parseModuleRecord(code, lang) {
91
+ const result = parseSync(PARSE_FILENAME, code, { lang });
92
+ return result.errors.length > 0 ? null : result.module;
93
+ }
94
+ /**
95
+ * One whitespace character or comment. Each alternative can only match one
96
+ * way (a block comment stops at the first `*\/`, a line comment runs to the
97
+ * line end), so repeating it cannot backtrack exponentially.
98
+ */
99
+ const TRIVIA_PATTERN = String.raw`(?:\s|\/\*(?:[^*]|\*(?!\/))*\*\/|\/\/[^\n\r\u2028\u2029]*(?![^\n\r\u2028\u2029]))`;
100
+ /** Leading whitespace and comments. */
101
+ const LEADING_TRIVIA_RE = new RegExp(`^${TRIVIA_PATTERN}*`);
102
+ /**
103
+ * Whether the static import/export statement ending at `statementEnd` has
104
+ * `with { ... }` (or legacy `assert { ... }`) attributes after its source
105
+ * string, which ends at `sourceEnd`. The module record does not report
106
+ * attributes.
107
+ */
108
+ function hasImportAttributes(code, sourceEnd, statementEnd) {
109
+ const afterSource = code.slice(sourceEnd, statementEnd);
110
+ const triviaLength = LEADING_TRIVIA_RE.exec(afterSource)?.[0].length ?? 0;
111
+ return /^(?:with|assert)\b/.test(afterSource.slice(triviaLength));
112
+ }
113
+ const EMPTY_TYPE_IMPORT_RE = new RegExp(String.raw`^import${TRIVIA_PATTERN}*type${TRIVIA_PATTERN}*\{`);
114
+ /**
115
+ * Whether a static import is erased by TypeScript: every binding is
116
+ * type-only, or it is `import type {} from "x"`, which the module record
117
+ * reports with no entries (like a runtime `import {} from "x"`).
118
+ */
119
+ function isTypeOnlyImport(code, statement) {
120
+ if (statement.entries.length > 0) return statement.entries.every((entry) => entry.isType);
121
+ return EMPTY_TYPE_IMPORT_RE.test(code.slice(statement.start, statement.moduleRequest.start));
122
+ }
123
+ /**
124
+ * The value of the string literal or expression-free template literal spanning
125
+ * `span`, or `null` for any other expression. The module record gives only the
126
+ * span of a dynamic import's source.
127
+ */
128
+ function quotedStringAt(code, span) {
129
+ const text = code.slice(span.start, span.end);
130
+ const match = /^(?:"([^"\\\r\n]*)"|'([^'\\\r\n]*)'|`([^`\\$]*)`)$/.exec(text);
131
+ if (match) return match[1] ?? match[2] ?? match[3];
132
+ if (!/^["'`]/.test(text)) return null;
133
+ const result = parseSync(PARSE_FILENAME, `(${text})`, PROGRAM_PARSER_DEFAULTS);
134
+ const statement = result.errors.length > 0 ? void 0 : result.program.body[0];
135
+ return statement?.type === "ExpressionStatement" ? staticStringValue(statement.expression) : null;
136
+ }
49
137
  const SKIP_CHILD_KEYS = /* @__PURE__ */ new Set([
50
138
  "type",
51
139
  "parent",
@@ -137,4 +225,4 @@ function collectBindingNames(node, target) {
137
225
  }
138
226
  }
139
227
  //#endregion
140
- export { DYNAMIC_IMPORT_PRESCAN, SCRIPT_MODULE_ID_RE, booleanLiteralValue, collectBindingNames, forEachAstChild, getAstName, isIdentifierNamed, mayContainDynamicImport, scriptParserLanguage, staticStringValue, stringLiteralValue, unwrapExpression, walkAst };
228
+ export { DYNAMIC_IMPORT_PRESCAN, LEADING_TRIVIA_RE, SCRIPT_MODULE_ID_RE, TRIVIA_PATTERN, booleanLiteralValue, collectBindingNames, forEachAstChild, getAstName, hasImportAttributes, isIdentifierNamed, isTypeOnlyImport, mayContainDynamicImport, parseModuleRecord, parseProgram, parseProgramAsync, quotedStringAt, scriptParserLanguage, staticStringValue, stringLiteralValue, unwrapExpression, walkAst };
@@ -0,0 +1,41 @@
1
+ import { Plugin } from "vite";
2
+ //#region src/plugins/cloudflare-dev-module-urls.d.ts
3
+ /**
4
+ * Vite's internal middlewares that serve module requests (`/@vite/client`,
5
+ * `/@id/*`, JS and CSS source files) and `/@fs/*` paths, preceded by the one
6
+ * that strips a non-root `base` from the URL and the one that answers the HMR
7
+ * client's reconnect ping (`Accept: text/x-vite-ping`) with a 204 instead of
8
+ * the Worker rendering a page for it. If Vite renames them, none are found and
9
+ * every request falls through, which is the behavior without this plugin.
10
+ *
11
+ * `viteServePublicMiddleware` is deliberately excluded so that `public/` files
12
+ * reach the Worker and middleware, as they do in production. Without it, the
13
+ * transform middleware reports a public `.js` or `.css` file as an
14
+ * `ERR_LOAD_PUBLIC_URL` error, which is treated as a fall-through.
15
+ */
16
+ export declare const VITE_MODULE_MIDDLEWARE_NAMES: Set<string>;
17
+ /**
18
+ * Vite's internal middleware that serves files under the project root. Vite
19
+ * gives imported assets root-relative URLs (`import logo from "./logo.svg"`
20
+ * and CSS `url(./bg.png)` both resolve to paths like `/app/logo.svg`), and only
21
+ * this middleware serves them. It also serves every other project file, and a
22
+ * Worker route can share its path with one (e.g. an `api/` directory and an
23
+ * `/api/*` route handler), so it only runs for referenced assets. See
24
+ * `isReferencedAsset`. Navigations to a referenced asset
25
+ * are served too: in production its URL is under `/_next/static/`, which never
26
+ * reaches the Worker.
27
+ */
28
+ export declare const VITE_STATIC_MIDDLEWARE_NAME = "viteServeStaticMiddleware";
29
+ type CloudflareDevModuleUrlsOptions = {
30
+ /** Whether the Cloudflare Vite plugin is present. Read when the dev server starts. */
31
+ isEnabled: () => boolean;
32
+ };
33
+ /**
34
+ * Creates the plugin that lets Vite serve its module URLs before the Cloudflare
35
+ * plugin's `runWorkerFirst` routing in dev.
36
+ *
37
+ * @param options - Plugin options
38
+ * @returns The Vite plugin
39
+ */
40
+ export declare function createCloudflareDevModuleUrlsPlugin(options: CloudflareDevModuleUrlsOptions): Plugin;
41
+ //#endregion