vinext 0.2.1 → 1.0.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (236) hide show
  1. package/README.md +67 -30
  2. package/dist/build/assets-ignore.js +1 -1
  3. package/dist/build/clean-output.js +1 -1
  4. package/dist/build/client-build-config.d.ts +13 -92
  5. package/dist/build/client-build-config.js +23 -99
  6. package/dist/build/css-url-assets.js +3 -3
  7. package/dist/build/google-fonts/fallback-metrics.js +1 -1
  8. package/dist/build/google-fonts/font-metadata.js +1 -1
  9. package/dist/build/inject-pregenerated-paths.js +1 -1
  10. package/dist/build/inline-css.js +2 -5
  11. package/dist/build/module-dependency-cache.d.ts +4 -0
  12. package/dist/build/module-dependency-cache.js +13 -0
  13. package/dist/build/next-client-runtime-manifests.js +1 -1
  14. package/dist/build/pages-client-assets-module.js +1 -1
  15. package/dist/build/precompress.js +7 -7
  16. package/dist/build/prerender-paths.d.ts +23 -0
  17. package/dist/build/prerender-paths.js +291 -0
  18. package/dist/build/prerender-server-pool.js +2 -2
  19. package/dist/build/prerender.d.ts +12 -1
  20. package/dist/build/prerender.js +2 -2
  21. package/dist/build/preview-credentials.d.ts +11 -0
  22. package/dist/build/preview-credentials.js +19 -0
  23. package/dist/build/report.d.ts +0 -3
  24. package/dist/build/report.js +2 -4
  25. package/dist/build/run-prerender.d.ts +2 -11
  26. package/dist/build/run-prerender.js +2 -10
  27. package/dist/build/server-manifest.js +1 -1
  28. package/dist/build/ssr-manifest.d.ts +4 -0
  29. package/dist/build/ssr-manifest.js +10 -6
  30. package/dist/build/standalone.js +37 -37
  31. package/dist/cache/cache-adapters-virtual.d.ts +7 -17
  32. package/dist/cache/cache-adapters-virtual.js +35 -2
  33. package/dist/check.d.ts +0 -16
  34. package/dist/check.js +17 -34
  35. package/dist/cli.js +86 -101
  36. package/dist/client/instrumentation-client-inject.js +1 -1
  37. package/dist/client/pages-router-link-navigation.js +1 -1
  38. package/dist/config/config-matchers.js +2 -2
  39. package/dist/config/dotenv.js +1 -1
  40. package/dist/config/next-config.d.ts +4 -1
  41. package/dist/config/next-config.js +82 -16
  42. package/dist/config/prerender.d.ts +12 -2
  43. package/dist/config/prerender.js +22 -12
  44. package/dist/config/server-external-packages.js +1 -1
  45. package/dist/config/tsconfig-paths.js +7 -3
  46. package/dist/{node_modules/.pnpm/am-i-vibing@0.5.0/node_modules → deps/.pnpm/am-i-vibing@0.5.0/deps}/am-i-vibing/dist/detector-1yx2Hoe0.js +2 -2
  47. package/dist/deps/.pnpm/pathslash@0.1.0/deps/pathslash/dist/index.js +50 -0
  48. package/dist/entries/app-rsc-entry.js +12 -5
  49. package/dist/entries/app-rsc-manifest.js +4 -4
  50. package/dist/entries/pages-client-entry.js +6 -5
  51. package/dist/entries/pages-server-entry.js +15 -26
  52. package/dist/entries/runtime-entry-module.js +2 -2
  53. package/dist/image/image-adapters-virtual.js +1 -0
  54. package/dist/index.d.ts +1 -1
  55. package/dist/index.js +500 -338
  56. package/dist/init-cloudflare.js +13 -4
  57. package/dist/init-platform.d.ts +10 -1
  58. package/dist/init-platform.js +79 -13
  59. package/dist/init.d.ts +11 -3
  60. package/dist/init.js +133 -35
  61. package/dist/plugins/ast-utils.js +1 -1
  62. package/dist/plugins/dynamic-preload-metadata.js +7 -7
  63. package/dist/plugins/extensionless-dynamic-import.js +1 -1
  64. package/dist/plugins/fonts.js +3 -3
  65. package/dist/plugins/ignore-dynamic-requests.js +13 -8
  66. package/dist/plugins/import-meta-url.js +16 -17
  67. package/dist/plugins/middleware-export-validation.js +1 -1
  68. package/dist/plugins/middleware-server-only.js +2 -2
  69. package/dist/plugins/og-asset-ownership.js +7 -6
  70. package/dist/plugins/og-assets.js +4 -5
  71. package/dist/plugins/optimize-imports.js +12 -13
  72. package/dist/plugins/postcss.js +1 -1
  73. package/dist/plugins/remove-console.js +1 -1
  74. package/dist/plugins/require-context.js +1 -1
  75. package/dist/plugins/sass.js +2 -2
  76. package/dist/plugins/server-externals-manifest.js +1 -1
  77. package/dist/plugins/strip-server-exports.js +1 -1
  78. package/dist/plugins/styled-jsx.js +3 -2
  79. package/dist/plugins/typeof-window.js +1 -1
  80. package/dist/routing/app-route-graph.d.ts +3 -10
  81. package/dist/routing/app-route-graph.js +28 -76
  82. package/dist/routing/app-router.d.ts +0 -5
  83. package/dist/routing/app-router.js +0 -5
  84. package/dist/routing/file-matcher.d.ts +2 -6
  85. package/dist/routing/file-matcher.js +10 -11
  86. package/dist/routing/pages-router.js +3 -3
  87. package/dist/server/api-handler.js +41 -33
  88. package/dist/server/app-browser-entry.js +15 -11
  89. package/dist/server/app-browser-navigation-controller.js +9 -4
  90. package/dist/server/app-browser-server-action-client.js +1 -1
  91. package/dist/server/app-elements-wire.d.ts +2 -1
  92. package/dist/server/app-fallback-renderer.d.ts +8 -0
  93. package/dist/server/app-fallback-renderer.js +13 -1
  94. package/dist/server/app-layout-param-observation.d.ts +1 -1
  95. package/dist/server/app-page-boundary-render.d.ts +14 -1
  96. package/dist/server/app-page-boundary-render.js +107 -54
  97. package/dist/server/app-page-cache-render.d.ts +1 -1
  98. package/dist/server/app-page-dispatch.d.ts +2 -1
  99. package/dist/server/app-page-dispatch.js +29 -40
  100. package/dist/server/app-page-element-builder.d.ts +2 -1
  101. package/dist/server/app-page-element-builder.js +3 -3
  102. package/dist/server/app-page-execution.d.ts +3 -1
  103. package/dist/server/app-page-execution.js +31 -39
  104. package/dist/server/app-page-render.d.ts +1 -1
  105. package/dist/server/app-page-request.js +1 -1
  106. package/dist/server/app-page-route-wiring.js +4 -4
  107. package/dist/server/app-route-handler-execution.d.ts +1 -1
  108. package/dist/server/app-route-tree-prefetch.js +1 -1
  109. package/dist/server/app-rsc-cache-busting.js +1 -2
  110. package/dist/server/app-rsc-handler.js +2 -2
  111. package/dist/server/app-rsc-redirect-flight.d.ts +66 -0
  112. package/dist/server/app-rsc-redirect-flight.js +71 -0
  113. package/dist/server/app-rsc-render-mode.d.ts +2 -5
  114. package/dist/server/app-rsc-render-mode.js +2 -12
  115. package/dist/server/app-segment-config.js +2 -2
  116. package/dist/server/app-server-action-execution.js +3 -3
  117. package/dist/server/app-ssr-entry.js +4 -1
  118. package/dist/server/app-ssr-stream.d.ts +2 -1
  119. package/dist/server/app-ssr-stream.js +4 -1
  120. package/dist/server/cache-proof.js +1 -1
  121. package/dist/server/default-global-error-module.d.ts +3 -1
  122. package/dist/server/default-not-found-module.d.ts +3 -1
  123. package/dist/server/dev-lockfile.js +2 -3
  124. package/dist/server/dev-module-runner.js +1 -1
  125. package/dist/server/dev-origin-check.d.ts +2 -2
  126. package/dist/server/dev-origin-check.js +2 -2
  127. package/dist/server/dev-route-files.js +1 -1
  128. package/dist/server/dev-server.js +256 -164
  129. package/dist/server/dev-stack-sourcemap.js +4 -3
  130. package/dist/server/headers.d.ts +3 -1
  131. package/dist/server/headers.js +3 -1
  132. package/dist/server/image-optimization.d.ts +12 -1
  133. package/dist/server/image-optimization.js +15 -3
  134. package/dist/server/implicit-tags.js +2 -1
  135. package/dist/server/instrumentation.js +2 -2
  136. package/dist/server/isr-cache.d.ts +12 -4
  137. package/dist/server/isr-cache.js +3 -3
  138. package/dist/server/metadata-routes.js +4 -4
  139. package/dist/server/middleware-response-headers.js +1 -1
  140. package/dist/server/middleware-runtime.js +1 -1
  141. package/dist/server/middleware.d.ts +1 -0
  142. package/dist/server/middleware.js +1 -1
  143. package/dist/server/navigation-planner.d.ts +2 -0
  144. package/dist/server/navigation-planner.js +8 -2
  145. package/dist/server/next-error-digest.d.ts +9 -24
  146. package/dist/server/next-error-digest.js +23 -15
  147. package/dist/server/operation-token.js +1 -1
  148. package/dist/server/pages-body-parser-config.js +2 -1
  149. package/dist/server/pages-dev-hydration.d.ts +14 -0
  150. package/dist/server/pages-dev-hydration.js +83 -0
  151. package/dist/server/pages-dev-module-url.js +2 -2
  152. package/dist/server/pages-node-compat.d.ts +13 -6
  153. package/dist/server/pages-node-compat.js +44 -45
  154. package/dist/server/pages-page-data.d.ts +1 -1
  155. package/dist/server/pages-page-data.js +5 -4
  156. package/dist/server/pages-page-handler.js +61 -29
  157. package/dist/server/pages-page-response.d.ts +2 -2
  158. package/dist/server/pages-page-response.js +2 -2
  159. package/dist/server/pages-preview.d.ts +26 -0
  160. package/dist/server/pages-preview.js +165 -0
  161. package/dist/server/pages-readiness.d.ts +2 -1
  162. package/dist/server/pages-readiness.js +4 -2
  163. package/dist/server/pages-request-pipeline.js +1 -1
  164. package/dist/server/prerender-manifest.d.ts +15 -1
  165. package/dist/server/prerender-manifest.js +29 -1
  166. package/dist/server/prod-server.d.ts +6 -5
  167. package/dist/server/prod-server.js +15 -15
  168. package/dist/server/request-pipeline.js +1 -1
  169. package/dist/server/seed-cache.js +1 -1
  170. package/dist/server/socket-error-backstop.js +1 -1
  171. package/dist/server/static-file-cache.js +8 -9
  172. package/dist/server/worker-utils.js +1 -1
  173. package/dist/shims/cache.d.ts +1 -1
  174. package/dist/shims/cache.js +2 -1
  175. package/dist/shims/cdn-cache.d.ts +2 -7
  176. package/dist/shims/cdn-cache.js +2 -14
  177. package/dist/shims/constants.js +1 -1
  178. package/dist/shims/error-boundary.d.ts +4 -4
  179. package/dist/shims/error.d.ts +21 -5
  180. package/dist/shims/error.js +52 -14
  181. package/dist/shims/fetch-cache.js +1 -1
  182. package/dist/shims/font-utils.js +1 -1
  183. package/dist/shims/form.d.ts +1 -1
  184. package/dist/shims/head.js +3 -3
  185. package/dist/shims/headers.js +6 -4
  186. package/dist/shims/internal/pages-data-fetch-dedup.js +5 -3
  187. package/dist/shims/layout-segment-context.d.ts +1 -1
  188. package/dist/shims/link.d.ts +3 -1
  189. package/dist/shims/link.js +6 -3
  190. package/dist/shims/navigation-errors.d.ts +2 -1
  191. package/dist/shims/navigation-errors.js +9 -13
  192. package/dist/shims/navigation.d.ts +1 -1
  193. package/dist/shims/navigation.js +5 -5
  194. package/dist/shims/request-state-types.d.ts +2 -2
  195. package/dist/shims/router-state.d.ts +1 -0
  196. package/dist/shims/router.d.ts +2 -1
  197. package/dist/shims/router.js +18 -11
  198. package/dist/shims/script.js +1 -1
  199. package/dist/shims/server.js +2 -2
  200. package/dist/shims/slot.d.ts +1 -1
  201. package/dist/shims/thenable-params.js +1 -1
  202. package/dist/shims/unified-request-context.d.ts +1 -1
  203. package/dist/typegen.js +9 -11
  204. package/dist/utils/client-build-manifest.js +2 -2
  205. package/dist/utils/client-entry-manifest.js +1 -1
  206. package/dist/utils/client-runtime-metadata.js +1 -1
  207. package/dist/utils/commonjs-loader.js +3 -3
  208. package/dist/utils/mdx-scan.js +1 -1
  209. package/dist/utils/path.d.ts +1 -13
  210. package/dist/utils/path.js +1 -15
  211. package/dist/utils/plugin-options.d.ts +4 -0
  212. package/dist/utils/plugin-options.js +8 -0
  213. package/dist/utils/project.d.ts +1 -7
  214. package/dist/utils/project.js +2 -8
  215. package/dist/utils/public-routes.js +2 -2
  216. package/dist/utils/react-version.js +1 -1
  217. package/dist/utils/redirect-digest.d.ts +9 -0
  218. package/dist/utils/redirect-digest.js +25 -0
  219. package/dist/utils/vinext-root.js +1 -1
  220. package/dist/utils/vite-version.d.ts +6 -13
  221. package/dist/utils/vite-version.js +68 -34
  222. package/package.json +33 -14
  223. package/dist/cloudflare/index.d.ts +0 -3
  224. package/dist/cloudflare/index.js +0 -3
  225. package/dist/packages/cloudflare/src/cache/cdn-adapter.runtime.js +0 -102
  226. package/dist/packages/cloudflare/src/cache/kv-data-adapter.runtime.d.ts +0 -126
  227. package/dist/packages/cloudflare/src/cache/kv-data-adapter.runtime.js +0 -442
  228. package/dist/packages/cloudflare/src/deploy-config.js +0 -150
  229. package/dist/packages/cloudflare/src/deploy-help.js +0 -55
  230. package/dist/packages/cloudflare/src/deploy.js +0 -272
  231. package/dist/packages/cloudflare/src/tpr.d.ts +0 -45
  232. package/dist/packages/cloudflare/src/tpr.js +0 -582
  233. package/dist/packages/cloudflare/src/utils/cache-control-metadata.js +0 -20
  234. /package/dist/build/google-fonts/{fallback-metrics-data.js → fallback-metrics-data.json.js} +0 -0
  235. /package/dist/build/google-fonts/{font-data.js → font-data.json.js} +0 -0
  236. /package/dist/{node_modules/.pnpm/process-ancestry@0.1.0/node_modules → deps/.pnpm/process-ancestry@0.1.0/deps}/process-ancestry/dist/index.js +0 -0
package/README.md CHANGED
@@ -1,14 +1,54 @@
1
1
  # vinext
2
2
 
3
- The Next.js API surface, reimplemented on Vite.
3
+ Run Next.js applications on Vite, with Cloudflare Workers as the primary deployment target.
4
4
 
5
5
  > **Read the announcement:** [How we rebuilt Next.js with AI in one week](https://blog.cloudflare.com/vinext/)
6
6
 
7
- > 🚧 **Experimental under heavy development.** This project is an experiment in AI-driven software development. The vast majority of the code, tests, and documentation are written by AI, with humans steering throughout: setting architecture and priorities, making design decisions, reviewing changes, triaging complex problems, and shipping fixes. There may be bugs, rough edges, or things that don't work. Use at your own risk.
7
+ > **Under active development.** vinext supports substantial Next.js applications today, but it is not yet a drop-in replacement for every application or production workload. Expect compatibility gaps, especially in newer App Router features, and evaluate it against your own application before adopting it.
8
+
9
+ vinext reimplements the Next.js API surface on Vite rather than consuming `next build` output. It supports both the App Router and Pages Router, React Server Components, Server Actions, middleware, route handlers, ISR, static export, and the most commonly used `next/*` modules. Cloudflare Workers has the deepest integration; Node.js and other platforms are available with different levels of support.
10
+
11
+ ## Project status
12
+
13
+ ### What works today
14
+
15
+ - **App Router and Pages Router** in development and production builds
16
+ - **React Server Components, Server Actions, route handlers, and middleware**
17
+ - **Static generation, ISR, `output: "export"`, and standalone Node.js output**
18
+ - **Core Next.js APIs and modules**, including `next/link`, `next/image`, `next/navigation`, `next/headers`, `next/cache`, and the Metadata API
19
+ - **Cloudflare Workers deployment** with bindings, cache adapters, and image optimization support
20
+ - **Migration tooling** through `vinext check`, `vinext init`, and the vinext Agent Skill
21
+
22
+ ### Known gaps we're working on
23
+
24
+ These are active compatibility areas, not permanent exclusions:
25
+
26
+ - **Cache Components and Partial Prerendering:** `"use cache"` is partially implemented, but full `cacheComponents` behavior is still incomplete. Cache profiles, tags, partial shells, resume behavior, prefetching, and some dev/build cache semantics do not yet match Next.js in every case.
27
+ - **Build-time image and font optimization:** images can be optimized at request time on Cloudflare, but vinext does not yet reproduce Next.js's complete build-time image pipeline. Google Fonts are loaded from the CDN, and local font CSS is injected at runtime rather than extracted during the build.
28
+ - **Native modules in App Router development:** packages such as `sharp`, `resvg`, `satori`, `lightningcss`, and `@napi-rs/canvas` can fail in Vite's RSC development environment. Production builds support more of these cases than development mode.
29
+ - **Platform-specific and advanced Next.js behavior:** `runtime` and `preferredRegion` route config are currently ignored, and some recently introduced or undocumented Next.js behavior may not yet be reproduced.
30
+
31
+ Run `vinext check` against an existing application before migrating. If a gap is not listed here, check the [open issues](https://github.com/cloudflare/vinext/issues) or file a focused reproduction.
8
32
 
9
33
  ## Quick start
10
34
 
11
- vinext includes an [Agent Skill](https://agentskills.io/home) that handles migration for you. It works with Claude Code, OpenCode, Cursor, Codex, and dozens of other AI coding tools. Install it, open your Next.js project, and tell the AI to migrate:
35
+ **Use the official setup commands below.** They are the recommended way to create or migrate a vinext project because they configure dependencies, scripts, Vite, and your deployment target for you.
36
+
37
+ Start a new project with `create-vinext-app`:
38
+
39
+ ```bash
40
+ pnpm create vinext-app@latest my-app
41
+ ```
42
+
43
+ Migrate an existing Next.js project with `vinext init`:
44
+
45
+ ```bash
46
+ npx vinext init
47
+ ```
48
+
49
+ ### Optional: migrate with an AI agent
50
+
51
+ Prefer `vinext init` for a direct, repeatable migration. If you want an AI agent to investigate compatibility issues and guide the migration, vinext also includes an optional [Agent Skill](https://agentskills.io/home). It works with Claude Code, OpenCode, Cursor, Codex, and dozens of other AI coding tools:
12
52
 
13
53
  ```sh
14
54
  npx skills add cloudflare/vinext
@@ -25,13 +65,15 @@ The skill handles compatibility checking, dependency installation, config genera
25
65
  ### Or do it manually
26
66
 
27
67
  ```bash
28
- npm install -D vinext vite @vitejs/plugin-react
68
+ npm install vinext
69
+ npm install -D vite @vitejs/plugin-react
29
70
  ```
30
71
 
31
72
  If you're using the App Router, also install:
32
73
 
33
74
  ```bash
34
- npm install -D @vitejs/plugin-rsc react-server-dom-webpack
75
+ npm install react-server-dom-webpack
76
+ npm install -D @vitejs/plugin-rsc
35
77
  ```
36
78
 
37
79
  Replace `next` with `vinext` in your scripts:
@@ -93,9 +135,15 @@ Environment variables: `PORT` (default `3000`), `HOST` (default `0.0.0.0`).
93
135
 
94
136
  ### Starting a new vinext project
95
137
 
96
- Run `npm create next-app@latest` to create a new Next.js project, and then follow these instructions to migrate it to vinext.
138
+ Use `create-vinext-app` for new projects. It creates a TypeScript App Router project
139
+ with Tailwind CSS and then runs the same vinext init setup used for existing apps:
97
140
 
98
- In the future, we will have a proper `npm create vinext` new project workflow.
141
+ ```bash
142
+ pnpm create vinext-app@latest my-app
143
+ ```
144
+
145
+ The generated project is Cloudflare Workers-ready by default. Pass
146
+ `--platform=node` if you want the Node target instead.
99
147
 
100
148
  ### Migrating an existing Next.js project
101
149
 
@@ -108,7 +156,7 @@ npx vinext init
108
156
  This will:
109
157
 
110
158
  1. Run `vinext check` to scan for compatibility issues
111
- 2. Install `vite`, `@vitejs/plugin-react`, and App Router-only deps (`@vitejs/plugin-rsc`, `react-server-dom-webpack`) as devDependencies
159
+ 2. Install vinext runtime packages as dependencies and Vite/plugin tooling as devDependencies
112
160
  3. Rename CJS config files (e.g. `postcss.config.js` -> `.cjs`) to avoid ESM conflicts
113
161
  4. Add `"type": "module"` to `package.json`
114
162
  5. Add `dev:vinext`, `build:vinext`, and `start:vinext` scripts to `package.json`
@@ -136,7 +184,7 @@ the compatibility report.
136
184
 
137
185
  Vite has become the default build tool for modern web frameworks — fast HMR, a clean plugin API, native ESM, and a growing ecosystem. With [`@vitejs/plugin-rsc`](https://github.com/vitejs/vite-plugin-react/tree/main/packages/plugin-rsc) adding React Server Components support, it's now possible to build a full RSC framework on Vite.
138
186
 
139
- vinext is an experiment: can we reimplement the Next.js API surface on Vite, so that existing Next.js applications can run on a completely different toolchain? The answer, so far, is mostly yes.
187
+ vinext reimplements the Next.js API surface on Vite so existing Next.js applications can run on a different toolchain. The answer, so far, is that substantial applications can.
140
188
 
141
189
  vinext works everywhere. It natively supports Cloudflare Workers (with `npx @vinext/cloudflare deploy` or `vp exec vinext-cloudflare deploy`, bindings, KV caching), and can be deployed to Vercel, Netlify, AWS, Deno Deploy, and more via the [Nitro](https://v3.nitro.build/) Vite plugin. Native support for additional platforms is [planned](https://github.com/cloudflare/vinext/issues/80).
142
190
 
@@ -158,13 +206,13 @@ vinext works everywhere. It natively supports Cloudflare Workers (with `npx @vin
158
206
  vinext is a Vite plugin that reimplements the public Next.js API — routing, server rendering, `next/*` module imports, the CLI — so you can run Next.js applications on Vite instead of the Next.js compiler toolchain. It can be deployed anywhere: Cloudflare Workers is the first natively supported target, with other platforms available via Nitro. Native adapters for more platforms are [planned](https://github.com/cloudflare/vinext/issues/80).
159
207
 
160
208
  **Is this a fork of Next.js?**
161
- No. vinext is an alternative implementation of the Next.js API surface built on Vite. It does import some Next.js types and utilities, but the core is written from scratch. The goal is not to create a competing framework or add features beyond what Next.js offers it's an experiment in how far AI-driven development and Vite's toolchain can go in replicating an existing, well-defined API surface.
209
+ No. vinext is an alternative implementation of the Next.js API surface built on Vite. It does import some Next.js types and utilities, but the core is written from scratch. The goal is not to create a competing framework or add features beyond what Next.js offers; it is to provide the same well-defined API surface on Vite's toolchain.
162
210
 
163
211
  **How is this different from OpenNext?**
164
- [OpenNext](https://opennext.js.org/) adapts the _output_ of a standard `next build` to run on various platforms. Because it builds on Next.js's own output, it inherits broad API coverage and has been well-tested for much longer. vinext takes a different approach: it reimplements the Next.js APIs on Vite from scratch, which means faster builds and smaller bundles, but less coverage of the long tail of Next.js features. If you need a mature, well-tested way to run Next.js outside Vercel, OpenNext is the safer choice. If you're interested in experimenting with a lighter toolchain and don't need every Next.js API, vinext might be worth a look.
212
+ [OpenNext](https://opennext.js.org/) adapts the _output_ of a standard `next build` to run on various platforms. Because it builds on Next.js's own output, it inherits broad API coverage and has been well-tested for much longer. vinext takes a different approach: it reimplements the Next.js APIs on Vite from scratch, which means faster builds and smaller bundles, but less coverage of the long tail of Next.js features. If you need a mature, well-tested way to run Next.js outside Vercel, OpenNext is the safer choice. If you want a lighter Vite-based toolchain and do not need every Next.js API, vinext may be a good fit.
165
213
 
166
214
  **Can I use this in production?**
167
- You can, with caution. This is experimental software with known bugs. It works well enough for demos and exploration, but it hasn't been battle-tested with real production traffic.
215
+ You can, with caution. vinext has known compatibility gaps and has not yet been battle-tested across the full range of production Next.js workloads. Evaluate the features and deployment target your application relies on before adopting it.
168
216
 
169
217
  **Can I just self-host Next.js?**
170
218
  Yes. Next.js supports [self-hosting](https://nextjs.org/docs/app/building-your-application/deploying#self-hosting) on Node.js servers, Docker containers, and static exports. If you're happy with the Next.js toolchain and just want to run it somewhere other than Vercel, self-hosting is the simplest path.
@@ -176,7 +224,7 @@ The test suite has over 1,700 Vitest tests and 380 Playwright E2E tests. This in
176
224
  A mix of humans and AI agents. Humans review PRs before they merge, focused on behavior, structure, and long-term direction. We lean heavily on agent-driven code review to catch issues at PR time and across the codebase. The test suite is the primary quality gate. Outside contributions and deeper human code review are very welcome.
177
225
 
178
226
  **Why Vite?**
179
- Vite is an excellent build tool with a rich plugin ecosystem, first-class ESM support, and fast HMR. The [`@vitejs/plugin-rsc`](https://github.com/vitejs/vite-plugin-react/tree/main/packages/plugin-rsc) plugin adds React Server Components support with multi-environment builds. This project is an experiment to see how much of the Next.js developer experience can be replicated on top of Vite's infrastructure.
227
+ Vite is an excellent build tool with a rich plugin ecosystem, first-class ESM support, and fast HMR. The [`@vitejs/plugin-rsc`](https://github.com/vitejs/vite-plugin-react/tree/main/packages/plugin-rsc) plugin adds React Server Components support with multi-environment builds. vinext builds the Next.js developer experience on top of that infrastructure.
180
228
 
181
229
  **Does this support the Pages Router, App Router, or both?**
182
230
  Both. File-system routing, SSR, client hydration, and deployment to Cloudflare Workers work for both routers.
@@ -240,7 +288,7 @@ Use `--env <name>` to target `wrangler.jsonc` `env.<name>`. `--preview` is short
240
288
  The init command also auto-detects and fixes common migration issues:
241
289
 
242
290
  - Adds `"type": "module"` to package.json if missing
243
- - Resolves tsconfig.json path aliases automatically (via `vite-tsconfig-paths`)
291
+ - Resolves tsconfig.json path aliases automatically with Vite's native resolver
244
292
  - Detects MDX usage and configures `@mdx-js/rollup`
245
293
  - Renames CJS config files (postcss.config.js, etc.) to `.cjs` when needed
246
294
  - Detects native Node.js modules (sharp, resvg, satori, lightningcss, @napi-rs/canvas) and auto-stubs them for Workers. If you encounter others that need stubbing, PRs are welcome.
@@ -600,27 +648,16 @@ vinext({
600
648
 
601
649
  ## What's NOT supported (and won't be)
602
650
 
603
- These are intentional exclusions. For things that are missing today but on the roadmap, see [Known limitations](#known-limitations) below.
651
+ 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.
604
652
 
605
653
  - **Vercel-specific features** — `@vercel/og` edge runtime, Vercel Analytics integration, Vercel KV/Blob/Postgres bindings. Use platform equivalents.
606
654
  - **AMP** — Deprecated since Next.js 13. `useAmp()` returns `false`.
607
655
  - **`next export` (legacy)** — Use `output: 'export'` in config instead.
608
656
  - **Turbopack/webpack configuration** — This runs on Vite. Use Vite plugins instead of webpack loaders/plugins.
609
657
  - **`next/jest`** — Use Vitest.
610
- - **`create-next-app` scaffolding** — Not a goal.
658
+ - **`create-next-app` scaffolding** — Use `create-vinext-app` for new vinext projects.
611
659
  - **Bug-for-bug parity with undocumented behavior** — If it's not in the Next.js docs, we probably don't replicate it.
612
660
 
613
- ## Known limitations
614
-
615
- These are gaps we'd like to close — distinct from the [intentional exclusions](#whats-not-supported-and-wont-be) above.
616
-
617
- - **Image optimization doesn't happen at build time.** Remote images work via `@unpic/react` (auto-detects 28 CDN providers). Local images are routed through a `/_next/image` endpoint that can resize and transcode on Cloudflare Workers (via the Images binding) in production, but no build-time optimization or static resizing occurs.
618
- - **Google Fonts are loaded from the CDN, not self-hosted.** No `size-adjust` fallback font metrics. Local fonts work but `@font-face` CSS is injected at runtime, not extracted at build time.
619
- - **Route segment config** — `runtime` and `preferredRegion` are ignored (everything runs in the same environment).
620
- - **Node.js production server (`vinext start`)** works for testing but is less complete than Workers deployment. Cloudflare Workers is the primary target.
621
- - **Native Node modules (sharp, resvg, satori, lightningcss, @napi-rs/canvas)** crash Vite's RSC dev environment. Dynamic OG image/icon routes using these work in production builds but not in dev mode. These are auto-stubbed during `@vinext/cloudflare deploy`.
622
- - **`next.config.ts` `baseUrl` bare imports require Vite 8.** A `next.config.ts` that imports a bare specifier resolved through `tsconfig.json`'s `compilerOptions.baseUrl` (e.g. `import { bar } from "bar"` resolving to a local `bar.ts`) relies on Vite 8's native `resolve.tsconfigPaths` (Rolldown/oxc-resolver). On Vite 7 there is no native equivalent, so these imports are not resolved. `compilerOptions.paths` aliases (e.g. `@/foo`) work on both Vite 7 and 8. Note that if a bare import matches both a `baseUrl`-local file and an installed package of the same name, the installed package wins (vinext keeps packages externalized so CJS config plugins like `@next/mdx` keep working).
623
-
624
661
  ## Benchmarks
625
662
 
626
663
  > **Caveat:** Benchmarks are hard to get right and these are early results. Take them as directional, not definitive.
@@ -642,7 +679,7 @@ Benchmarks run on GitHub CI runners (2-core Ubuntu) on every merge to `main`. Se
642
679
 
643
680
  Analysis of the build output shows two main factors:
644
681
 
645
- 1. **Tree-shaking**: Vite/Rollup produces a smaller React+ReactDOM bundle than Next.js/Turbopack. Rollup's more aggressive dead-code elimination accounts for roughly half the overall difference.
682
+ 1. **Tree-shaking**: Vite/Rolldown produces a smaller React+ReactDOM bundle than Next.js/Turbopack. Rolldown's more aggressive dead-code elimination accounts for roughly half the overall difference.
646
683
  2. **Framework overhead**: Next.js ships more client-side infrastructure (router, Turbopack runtime loader, prefetching, error handling) than vinext's lighter client runtime.
647
684
 
648
685
  Both frameworks ship the same app code and the same RSC client runtime (`react-server-dom-webpack`). The difference is in how much of React's internals survive tree-shaking and how much framework plumbing each tool adds.
@@ -769,11 +806,11 @@ Or add it to your `package.json` as a file dependency:
769
806
  }
770
807
  ```
771
808
 
772
- vinext has peer dependencies on `react ^19.2.6`, `react-dom ^19.2.6`, `react-server-dom-webpack ^19.2.6`, and `vite ^7.0.0 || ^8.0.0`. Then replace `next` with `vinext` in your scripts and run as normal.
809
+ vinext has peer dependencies on `react ^19.2.6`, `react-dom ^19.2.6`, `react-server-dom-webpack ^19.2.6`, and `vite ^8.0.0`. Then replace `next` with `vinext` in your scripts and run as normal.
773
810
 
774
811
  ## Contributing
775
812
 
776
- This project is experimental and under active development. Issues and PRs are welcome.
813
+ This project is under active development. Issues and PRs are welcome.
777
814
 
778
815
  ### CI
779
816
 
@@ -1,5 +1,5 @@
1
+ import path from "../deps/.pnpm/pathslash@0.1.0/deps/pathslash/dist/index.js";
1
2
  import fs from "node:fs";
2
- import path from "node:path";
3
3
  //#region src/build/assets-ignore.ts
4
4
  /**
5
5
  * Build metadata that must never be served by the Cloudflare ASSETS binding.
@@ -1,5 +1,5 @@
1
+ import path from "../deps/.pnpm/pathslash@0.1.0/deps/pathslash/dist/index.js";
1
2
  import fs from "node:fs";
2
- import path from "node:path";
3
3
  //#region src/build/clean-output.ts
4
4
  function resolveOutDir(root, outDir) {
5
5
  const resolvedRoot = path.resolve(root);
@@ -7,13 +7,6 @@ type ClientAssetFileNameInfo = {
7
7
  readonly originalFileName?: string;
8
8
  readonly originalFileNames?: readonly string[];
9
9
  };
10
- type RscFrameworkModuleInfo = {
11
- importers: string[];
12
- isEntry: boolean;
13
- };
14
- type RscFrameworkManualChunksMeta = {
15
- getModuleInfo(id: string): RscFrameworkModuleInfo | null;
16
- };
17
10
  /**
18
11
  * Routes client assets into Next-compatible subtrees: `.css` sources go to
19
12
  * `<assetsDir>/css/`, everything else to `<assetsDir>/media/`. Returned as a
@@ -42,31 +35,15 @@ declare function createClientAssetFileNames(assetsDir: string): (assetInfo: Clie
42
35
  * mobile devices.
43
36
  * - No major Vite-based framework (Remix, SvelteKit, Astro, TanStack)
44
37
  * uses per-package splitting. Next.js only isolates packages >160KB.
45
- * - Rollup's graph-based splitting already handles the common case
38
+ * - The bundler's graph-based splitting already handles the common case
46
39
  * well: shared dependencies between routes get their own chunks,
47
40
  * and route-specific code stays in route chunks.
48
41
  */
49
42
  declare function createClientManualChunks(shimsDir: string, preserveRouteBoundaries?: boolean): (id: string) => string | undefined;
50
- /**
51
- * Rollup output config with manualChunks for client code-splitting.
52
- * Used by both CLI builds and multi-environment builds.
53
- *
54
- * experimentalMinChunkSize merges tiny shared chunks (< 10KB) back into
55
- * their importers. This reduces HTTP request count and improves gzip
56
- * compression efficiency — small files restart the compression dictionary,
57
- * adding ~5-15% wire overhead vs fewer larger chunks.
58
- */
59
43
  declare function createClientFileNameConfig(assetsDir: string): {
60
44
  entryFileNames: string;
61
45
  chunkFileNames: string;
62
46
  };
63
- declare function createClientOutputConfig(clientManualChunks: (id: string) => string | undefined, assetsDir: string): {
64
- assetFileNames: (assetInfo: ClientAssetFileNameInfo) => string;
65
- manualChunks: (id: string) => string | undefined;
66
- experimentalMinChunkSize: number;
67
- entryFileNames: string;
68
- chunkFileNames: string;
69
- };
70
47
  declare function createClientCodeSplittingConfig(clientManualChunks: (id: string) => string | undefined): {
71
48
  minSize: number;
72
49
  groups: {
@@ -82,13 +59,12 @@ declare const RSC_FRAMEWORK_CHUNK_TEST: RegExp;
82
59
  declare function isRscFrameworkModule(id: string): boolean;
83
60
  /**
84
61
  * Output config that isolates React (and the RSC flight runtime) into a
85
- * dedicated "framework" chunk in the RSC server build. Returns the bundler-
86
- * appropriate shape: rolldown's `codeSplitting` for Vite 8+, Rollup's
87
- * `manualChunks` for Vite 7. See {@link RSC_FRAMEWORK_CHUNK_TEST} for the
88
- * motivation (issue #1549). Framework modules that are only reachable through
89
- * dynamic imports must stay out of the eager framework chunk (issue #2073).
62
+ * dedicated "framework" chunk in the RSC server build. See
63
+ * {@link RSC_FRAMEWORK_CHUNK_TEST} for the motivation (issue #1549). Framework
64
+ * modules that are only reachable through dynamic imports must stay out of the
65
+ * eager framework chunk (issue #2073).
90
66
  */
91
- declare function createRscFrameworkChunkOutputConfig(viteMajorVersion: number): {
67
+ declare function createRscFrameworkChunkOutputConfig(): {
92
68
  codeSplitting: {
93
69
  groups: {
94
70
  name: string;
@@ -96,76 +72,21 @@ declare function createRscFrameworkChunkOutputConfig(viteMajorVersion: number):
96
72
  entriesAware: boolean;
97
73
  }[];
98
74
  };
99
- manualChunks?: undefined;
100
- } | {
101
- manualChunks(id: string, meta: RscFrameworkManualChunksMeta): string | undefined;
102
- codeSplitting?: undefined;
103
- };
104
- /**
105
- * Rollup treeshake configuration for production client builds.
106
- *
107
- * Uses the 'recommended' preset as a safe base, then overrides
108
- * moduleSideEffects to strip unused re-exports from npm packages.
109
- *
110
- * The 'no-external' value for moduleSideEffects means:
111
- * - Local project modules: preserve side effects (CSS imports, polyfills)
112
- * - node_modules packages: treat as side-effect-free unless exports are used
113
- *
114
- * This is the single highest-impact optimization for large barrel-exporting
115
- * libraries like mermaid, @mui/material, lucide-react, etc. These libraries
116
- * re-export hundreds of sub-modules through barrel files. Without this,
117
- * Rollup preserves every sub-module even when only a few exports are consumed.
118
- *
119
- * Why 'no-external' instead of false (global side-effect-free)?
120
- * - User code may rely on import-time side effects (e.g., `import './global.css'`)
121
- * - 'no-external' is safe for app code while still enabling aggressive DCE for deps
122
- *
123
- * Why not the 'smallest' preset?
124
- * - 'smallest' also sets propertyReadSideEffects: false and
125
- * tryCatchDeoptimization: false, which can break specific libraries
126
- * that rely on property access side effects or try/catch for feature detection
127
- * - 'recommended' + 'no-external' gives most of the benefit with less risk
128
- *
129
- * @deprecated Use getClientTreeshakeConfigForVite(viteMajorVersion) instead
130
- * for Vite version compatibility. Kept for backward compatibility.
131
- */
132
- declare const clientTreeshakeConfig: {
133
- preset: "recommended";
134
- moduleSideEffects: "no-external";
135
75
  };
136
76
  /**
137
- * Returns treeshake configuration appropriate for the Vite version.
138
- *
139
- * Rollup (Vite 7) supports presets like "recommended" which set multiple
140
- * treeshake options at once. Rolldown (Vite 8+) doesn't support presets,
141
- * so we only return moduleSideEffects for Vite 8+.
142
- *
143
- * The Rollup "recommended" preset sets:
144
- * - annotations: true (Rolldown default is also true)
145
- * - manualPureFunctions: [] (Rolldown default is also [])
146
- * - propertyReadSideEffects: true (Rolldown equivalent is 'always', the default)
147
- * - unknownGlobalSideEffects: false (Rolldown default is true — this is a known acceptable
148
- * divergence. Slightly less aggressive DCE on unknown globals, acceptable for client bundles)
149
- * - correctVarValueBeforeDeclaration and tryCatchDeoptimization (Rolldown handles these differently)
77
+ * Returns Rolldown treeshake configuration for production client builds.
150
78
  *
151
79
  * The key optimization is moduleSideEffects: "no-external", which is supported
152
- * by both bundlers and provides the DCE benefits for barrel-exporting libraries.
153
- * It treats node_modules as side-effect-free (enabling aggressive DCE) while
154
- * preserving side effects in local code.
80
+ * by Rolldown and provides the DCE benefits for barrel-exporting libraries. It
81
+ * treats node_modules as side-effect-free while preserving side effects in
82
+ * local code.
155
83
  */
156
- declare function getClientTreeshakeConfigForVite(viteMajorVersion: number): {
157
- moduleSideEffects: "no-external";
158
- preset?: undefined;
159
- } | {
160
- preset: "recommended";
84
+ declare function getClientTreeshakeConfig(): {
161
85
  moduleSideEffects: "no-external";
162
86
  };
163
87
  type VinextBuildConfig = NonNullable<UserConfig["build"]>;
164
88
  type VinextBuildBundlerOptions = NonNullable<VinextBuildConfig["rolldownOptions"]>;
165
- type VinextBuildConfigWithLegacy = VinextBuildConfig & {
166
- rollupOptions?: VinextBuildBundlerOptions;
167
- };
168
89
  declare function getBuildBundlerOptions(build: UserConfig["build"] | undefined): VinextBuildBundlerOptions | undefined;
169
- declare function withBuildBundlerOptions(viteMajorVersion: number, bundlerOptions: VinextBuildBundlerOptions): Partial<VinextBuildConfigWithLegacy>;
90
+ declare function withBuildBundlerOptions(bundlerOptions: VinextBuildBundlerOptions): Partial<VinextBuildConfig>;
170
91
  //#endregion
171
- export { RSC_FRAMEWORK_CHUNK_TEST, clientTreeshakeConfig, createClientAssetFileNames, createClientCodeSplittingConfig, createClientFileNameConfig, createClientManualChunks, createClientOutputConfig, createRscFrameworkChunkOutputConfig, getBuildBundlerOptions, getClientTreeshakeConfigForVite, isRscFrameworkModule, withBuildBundlerOptions };
92
+ export { RSC_FRAMEWORK_CHUNK_TEST, createClientAssetFileNames, createClientCodeSplittingConfig, createClientFileNameConfig, createClientManualChunks, createRscFrameworkChunkOutputConfig, getBuildBundlerOptions, getClientTreeshakeConfig, isRscFrameworkModule, withBuildBundlerOptions };
@@ -1,5 +1,6 @@
1
+ import { toSlash } from "../deps/.pnpm/pathslash@0.1.0/deps/pathslash/dist/index.js";
1
2
  //#region src/build/client-build-config.ts
2
- const ROUTE_OWNED_CLIENT_SHIMS = new Set([
3
+ const ROUTE_OWNED_CLIENT_SHIMS = /* @__PURE__ */ new Set([
3
4
  "compat-router",
4
5
  "dynamic",
5
6
  "dynamic-preload-chunks",
@@ -47,7 +48,7 @@ function createClientAssetFileNames(assetsDir) {
47
48
  * (node_modules/.pnpm/pkg@ver/node_modules/pkg).
48
49
  */
49
50
  function getPackageName(id) {
50
- const normalizedId = id.replaceAll("\\", "/");
51
+ const normalizedId = toSlash(id);
51
52
  const nmIdx = normalizedId.lastIndexOf("node_modules/");
52
53
  if (nmIdx === -1) return null;
53
54
  const rest = normalizedId.slice(nmIdx + 13);
@@ -78,7 +79,7 @@ function getPackageName(id) {
78
79
  * mobile devices.
79
80
  * - No major Vite-based framework (Remix, SvelteKit, Astro, TanStack)
80
81
  * uses per-package splitting. Next.js only isolates packages >160KB.
81
- * - Rollup's graph-based splitting already handles the common case
82
+ * - The bundler's graph-based splitting already handles the common case
82
83
  * well: shared dependencies between routes get their own chunks,
83
84
  * and route-specific code stays in route chunks.
84
85
  */
@@ -90,9 +91,10 @@ function createClientManualChunks(shimsDir, preserveRouteBoundaries = false) {
90
91
  if (pkg === "react" || pkg === "react-dom" || pkg === "scheduler") return "framework";
91
92
  return;
92
93
  }
93
- if (id.startsWith(shimsDir)) {
94
+ const slashedId = toSlash(id);
95
+ if (slashedId.startsWith(shimsDir)) {
94
96
  if (preserveRouteBoundaries) {
95
- const relativeId = id.slice(shimsDir.length).split("?", 1)[0] ?? "";
97
+ const relativeId = slashedId.slice(shimsDir.length).split("?", 1)[0] ?? "";
96
98
  const extensionIndex = relativeId.lastIndexOf(".");
97
99
  const shimName = extensionIndex === -1 ? relativeId : relativeId.slice(0, extensionIndex);
98
100
  if (ROUTE_OWNED_CLIENT_SHIMS.has(shimName)) return void 0;
@@ -101,15 +103,6 @@ function createClientManualChunks(shimsDir, preserveRouteBoundaries = false) {
101
103
  }
102
104
  };
103
105
  }
104
- /**
105
- * Rollup output config with manualChunks for client code-splitting.
106
- * Used by both CLI builds and multi-environment builds.
107
- *
108
- * experimentalMinChunkSize merges tiny shared chunks (< 10KB) back into
109
- * their importers. This reduces HTTP request count and improves gzip
110
- * compression efficiency — small files restart the compression dictionary,
111
- * adding ~5-15% wire overhead vs fewer larger chunks.
112
- */
113
106
  function createClientFileNameConfig(assetsDir) {
114
107
  const chunksDir = `${assetsDir}/chunks`;
115
108
  return {
@@ -117,14 +110,6 @@ function createClientFileNameConfig(assetsDir) {
117
110
  chunkFileNames: `${chunksDir}/[name]-[hash].js`
118
111
  };
119
112
  }
120
- function createClientOutputConfig(clientManualChunks, assetsDir) {
121
- return {
122
- ...createClientFileNameConfig(assetsDir),
123
- assetFileNames: createClientAssetFileNames(assetsDir),
124
- manualChunks: clientManualChunks,
125
- experimentalMinChunkSize: 1e4
126
- };
127
- }
128
113
  function createClientCodeSplittingConfig(clientManualChunks) {
129
114
  return {
130
115
  minSize: 1e4,
@@ -174,97 +159,36 @@ function isRscFrameworkModule(id) {
174
159
  const pkg = getPackageName(id);
175
160
  return pkg !== null && FRAMEWORK_PACKAGES.includes(pkg);
176
161
  }
177
- function isStaticallyReachableFromEntry(id, meta, visited = /* @__PURE__ */ new Set()) {
178
- if (visited.has(id)) return false;
179
- visited.add(id);
180
- const moduleInfo = meta.getModuleInfo(id);
181
- if (!moduleInfo) return false;
182
- if (moduleInfo.isEntry) return true;
183
- return moduleInfo.importers.some((importer) => isStaticallyReachableFromEntry(importer, meta, visited));
184
- }
185
162
  /**
186
163
  * Output config that isolates React (and the RSC flight runtime) into a
187
- * dedicated "framework" chunk in the RSC server build. Returns the bundler-
188
- * appropriate shape: rolldown's `codeSplitting` for Vite 8+, Rollup's
189
- * `manualChunks` for Vite 7. See {@link RSC_FRAMEWORK_CHUNK_TEST} for the
190
- * motivation (issue #1549). Framework modules that are only reachable through
191
- * dynamic imports must stay out of the eager framework chunk (issue #2073).
164
+ * dedicated "framework" chunk in the RSC server build. See
165
+ * {@link RSC_FRAMEWORK_CHUNK_TEST} for the motivation (issue #1549). Framework
166
+ * modules that are only reachable through dynamic imports must stay out of the
167
+ * eager framework chunk (issue #2073).
192
168
  */
193
- function createRscFrameworkChunkOutputConfig(viteMajorVersion) {
194
- if (viteMajorVersion >= 8) return { codeSplitting: { groups: [{
169
+ function createRscFrameworkChunkOutputConfig() {
170
+ return { codeSplitting: { groups: [{
195
171
  name: "framework",
196
172
  test: RSC_FRAMEWORK_CHUNK_TEST,
197
173
  entriesAware: true
198
174
  }] } };
199
- return { manualChunks(id, meta) {
200
- return isRscFrameworkModule(id) && isStaticallyReachableFromEntry(id, meta) ? "framework" : void 0;
201
- } };
202
175
  }
203
176
  /**
204
- * Rollup treeshake configuration for production client builds.
205
- *
206
- * Uses the 'recommended' preset as a safe base, then overrides
207
- * moduleSideEffects to strip unused re-exports from npm packages.
208
- *
209
- * The 'no-external' value for moduleSideEffects means:
210
- * - Local project modules: preserve side effects (CSS imports, polyfills)
211
- * - node_modules packages: treat as side-effect-free unless exports are used
212
- *
213
- * This is the single highest-impact optimization for large barrel-exporting
214
- * libraries like mermaid, @mui/material, lucide-react, etc. These libraries
215
- * re-export hundreds of sub-modules through barrel files. Without this,
216
- * Rollup preserves every sub-module even when only a few exports are consumed.
217
- *
218
- * Why 'no-external' instead of false (global side-effect-free)?
219
- * - User code may rely on import-time side effects (e.g., `import './global.css'`)
220
- * - 'no-external' is safe for app code while still enabling aggressive DCE for deps
221
- *
222
- * Why not the 'smallest' preset?
223
- * - 'smallest' also sets propertyReadSideEffects: false and
224
- * tryCatchDeoptimization: false, which can break specific libraries
225
- * that rely on property access side effects or try/catch for feature detection
226
- * - 'recommended' + 'no-external' gives most of the benefit with less risk
227
- *
228
- * @deprecated Use getClientTreeshakeConfigForVite(viteMajorVersion) instead
229
- * for Vite version compatibility. Kept for backward compatibility.
230
- */
231
- const clientTreeshakeConfig = {
232
- preset: "recommended",
233
- moduleSideEffects: "no-external"
234
- };
235
- /**
236
- * Returns treeshake configuration appropriate for the Vite version.
237
- *
238
- * Rollup (Vite 7) supports presets like "recommended" which set multiple
239
- * treeshake options at once. Rolldown (Vite 8+) doesn't support presets,
240
- * so we only return moduleSideEffects for Vite 8+.
241
- *
242
- * The Rollup "recommended" preset sets:
243
- * - annotations: true (Rolldown default is also true)
244
- * - manualPureFunctions: [] (Rolldown default is also [])
245
- * - propertyReadSideEffects: true (Rolldown equivalent is 'always', the default)
246
- * - unknownGlobalSideEffects: false (Rolldown default is true — this is a known acceptable
247
- * divergence. Slightly less aggressive DCE on unknown globals, acceptable for client bundles)
248
- * - correctVarValueBeforeDeclaration and tryCatchDeoptimization (Rolldown handles these differently)
177
+ * Returns Rolldown treeshake configuration for production client builds.
249
178
  *
250
179
  * The key optimization is moduleSideEffects: "no-external", which is supported
251
- * by both bundlers and provides the DCE benefits for barrel-exporting libraries.
252
- * It treats node_modules as side-effect-free (enabling aggressive DCE) while
253
- * preserving side effects in local code.
180
+ * by Rolldown and provides the DCE benefits for barrel-exporting libraries. It
181
+ * treats node_modules as side-effect-free while preserving side effects in
182
+ * local code.
254
183
  */
255
- function getClientTreeshakeConfigForVite(viteMajorVersion) {
256
- if (viteMajorVersion >= 8) return { moduleSideEffects: "no-external" };
257
- return {
258
- preset: "recommended",
259
- moduleSideEffects: "no-external"
260
- };
184
+ function getClientTreeshakeConfig() {
185
+ return { moduleSideEffects: "no-external" };
261
186
  }
262
187
  function getBuildBundlerOptions(build) {
263
- const buildConfig = build;
264
- return buildConfig?.rolldownOptions ?? buildConfig?.rollupOptions;
188
+ return build?.rolldownOptions;
265
189
  }
266
- function withBuildBundlerOptions(viteMajorVersion, bundlerOptions) {
267
- return viteMajorVersion >= 8 ? { rolldownOptions: bundlerOptions } : { rollupOptions: bundlerOptions };
190
+ function withBuildBundlerOptions(bundlerOptions) {
191
+ return { rolldownOptions: bundlerOptions };
268
192
  }
269
193
  //#endregion
270
- export { RSC_FRAMEWORK_CHUNK_TEST, clientTreeshakeConfig, createClientAssetFileNames, createClientCodeSplittingConfig, createClientFileNameConfig, createClientManualChunks, createClientOutputConfig, createRscFrameworkChunkOutputConfig, getBuildBundlerOptions, getClientTreeshakeConfigForVite, isRscFrameworkModule, withBuildBundlerOptions };
194
+ export { RSC_FRAMEWORK_CHUNK_TEST, createClientAssetFileNames, createClientCodeSplittingConfig, createClientFileNameConfig, createClientManualChunks, createRscFrameworkChunkOutputConfig, getBuildBundlerOptions, getClientTreeshakeConfig, isRscFrameworkModule, withBuildBundlerOptions };
@@ -1,4 +1,4 @@
1
- import path from "node:path";
1
+ import path, { toSlash } from "../deps/.pnpm/pathslash@0.1.0/deps/pathslash/dist/index.js";
2
2
  //#region src/build/css-url-assets.ts
3
3
  /**
4
4
  * Next-parity for CSS `url()` asset dependencies.
@@ -35,7 +35,7 @@ const CSS_URL_RE = /url\(\s*(?:"([^"]*)"|'([^']*)'|([^'")]*?))\s*\)/g;
35
35
  const CSS_ASSET_EXT_RE = /\.(?:avif|bmp|gif|ico|jpe?g|png|svg|webp|woff2?|eot|ttf|otf|mp4|webm|ogg|mp3|wav|flac|aac|wasm)$/i;
36
36
  const CSS_REQUEST_RE = /\.(?:css|scss|sass|less|styl|stylus)(?:\?|$)/i;
37
37
  function basename(value) {
38
- const normalized = value.replaceAll("\\", "/");
38
+ const normalized = toSlash(value);
39
39
  const slash = normalized.lastIndexOf("/");
40
40
  return slash === -1 ? normalized : normalized.slice(slash + 1);
41
41
  }
@@ -137,7 +137,7 @@ function rebaseCssUrlAssetReferences(code, sourceDirectory, targetDirectory) {
137
137
  const lower = parts.path.toLowerCase();
138
138
  if (!CSS_ASSET_EXT_RE.test(lower) || lower.endsWith(".css")) return null;
139
139
  const absolutePath = path.resolve(sourceDirectory, parts.path);
140
- let rebasedPath = path.relative(targetDirectory, absolutePath).replaceAll("\\", "/");
140
+ let rebasedPath = path.relative(targetDirectory, absolutePath);
141
141
  if (!rebasedPath.startsWith(".")) rebasedPath = `./${rebasedPath}`;
142
142
  return joinUrl({
143
143
  ...parts,
@@ -1,5 +1,5 @@
1
1
  import { escapeCSSString } from "../../shims/font-utils.js";
2
- import fallback_metrics_data_default from "./fallback-metrics-data.js";
2
+ import fallback_metrics_data_default from "./fallback-metrics-data.json.js";
3
3
  //#region src/build/google-fonts/fallback-metrics.ts
4
4
  const EXPECTED_METRIC_LENGTH = 6;
5
5
  const fallbackMetrics = fallback_metrics_data_default;
@@ -1,4 +1,4 @@
1
- import font_data_default from "./font-data.js";
1
+ import font_data_default from "./font-data.json.js";
2
2
  //#region src/build/google-fonts/font-metadata.ts
3
3
  const googleFontsMetadata = font_data_default;
4
4
  //#endregion
@@ -1,7 +1,7 @@
1
+ import path from "../deps/.pnpm/pathslash@0.1.0/deps/pathslash/dist/index.js";
1
2
  import { escapeRegExp } from "../utils/regex.js";
2
3
  import { readPrerenderManifest } from "../server/prerender-manifest.js";
3
4
  import fs from "node:fs";
4
- import path from "node:path";
5
5
  //#region src/build/inject-pregenerated-paths.ts
6
6
  const VINEXT_PREGEN_START = "/* __VINEXT_PREGENERATED_CONCRETE_PATHS_START__ */";
7
7
  const VINEXT_PREGEN_END = "/* __VINEXT_PREGENERATED_CONCRETE_PATHS_END__ */";
@@ -1,6 +1,6 @@
1
+ import path from "../deps/.pnpm/pathslash@0.1.0/deps/pathslash/dist/index.js";
1
2
  import { resolveAssetUrlPrefix, resolveAssetsDir } from "../utils/asset-prefix.js";
2
3
  import fs from "node:fs";
3
- import path from "node:path";
4
4
  //#region src/build/inline-css.ts
5
5
  const INLINE_CSS_GLOBAL_MARKER = "globalThis.__VINEXT_INLINE_CSS__ = ";
6
6
  function collectCssFiles(directory) {
@@ -12,9 +12,6 @@ function collectCssFiles(directory) {
12
12
  }
13
13
  return files;
14
14
  }
15
- function toUrlPath(filePath) {
16
- return filePath.split(path.sep).join("/");
17
- }
18
15
  function addPathnameAlias(manifest, href, css) {
19
16
  try {
20
17
  const url = new URL(href);
@@ -27,7 +24,7 @@ function collectInlineCssManifest(clientDir, assetPrefix) {
27
24
  const urlPrefix = resolveAssetUrlPrefix(assetPrefix);
28
25
  const manifest = {};
29
26
  for (const filePath of collectCssFiles(assetsDir)) {
30
- const href = `${urlPrefix}${toUrlPath(path.relative(assetsDir, filePath))}`;
27
+ const href = `${urlPrefix}${path.relative(assetsDir, filePath)}`;
31
28
  const css = fs.readFileSync(filePath, "utf8");
32
29
  manifest[href] = css;
33
30
  addPathnameAlias(manifest, href, css);
@@ -0,0 +1,4 @@
1
+ //#region src/build/module-dependency-cache.d.ts
2
+ declare function createModuleDependencyCache<T>(collect: (moduleId: string) => Promise<T>): (moduleId: string) => Promise<T>;
3
+ //#endregion
4
+ export { createModuleDependencyCache };