vinext 0.2.0 → 1.0.0-beta.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 (168) hide show
  1. package/README.md +50 -29
  2. package/dist/build/client-build-config.d.ts +13 -92
  3. package/dist/build/client-build-config.js +17 -95
  4. package/dist/build/css-url-assets.d.ts +3 -1
  5. package/dist/build/css-url-assets.js +18 -1
  6. package/dist/build/inject-pregenerated-paths.d.ts +3 -0
  7. package/dist/build/inject-pregenerated-paths.js +4 -1
  8. package/dist/build/prerender-paths.d.ts +23 -0
  9. package/dist/build/prerender-paths.js +296 -0
  10. package/dist/build/prerender-server-entry.d.ts +1 -0
  11. package/dist/build/prerender-server-entry.js +49 -0
  12. package/dist/build/prerender-server-pool.d.ts +44 -0
  13. package/dist/build/prerender-server-pool.js +194 -0
  14. package/dist/build/prerender.d.ts +12 -1
  15. package/dist/build/prerender.js +87 -23
  16. package/dist/build/run-prerender.js +2 -1
  17. package/dist/cache/cache-adapters-virtual.d.ts +7 -1
  18. package/dist/cache/cache-adapters-virtual.js +26 -2
  19. package/dist/check.d.ts +4 -6
  20. package/dist/check.js +13 -9
  21. package/dist/cli.js +34 -54
  22. package/dist/client/vinext-next-data.d.ts +4 -1
  23. package/dist/config/config-matchers.js +33 -11
  24. package/dist/config/next-config.d.ts +36 -6
  25. package/dist/config/next-config.js +17 -4
  26. package/dist/config/prerender.d.ts +11 -1
  27. package/dist/config/prerender.js +19 -1
  28. package/dist/config/tsconfig-paths.js +5 -1
  29. package/dist/entries/app-browser-entry.js +5 -1
  30. package/dist/entries/app-rsc-entry.d.ts +3 -2
  31. package/dist/entries/app-rsc-entry.js +4 -0
  32. package/dist/entries/pages-client-entry.js +14 -3
  33. package/dist/entries/pages-server-entry.js +18 -4
  34. package/dist/image/image-adapters-virtual.js +1 -0
  35. package/dist/index.d.ts +1 -1
  36. package/dist/index.js +549 -152
  37. package/dist/init-cloudflare.js +12 -3
  38. package/dist/init-platform.d.ts +10 -1
  39. package/dist/init-platform.js +78 -12
  40. package/dist/init.d.ts +11 -3
  41. package/dist/init.js +129 -31
  42. package/dist/plugins/fonts.js +1 -1
  43. package/dist/plugins/ignore-dynamic-requests.js +1 -1
  44. package/dist/plugins/og-assets.js +2 -1
  45. package/dist/plugins/optimize-imports.js +1 -1
  46. package/dist/plugins/rsc-reference-validation-normalizer.d.ts +12 -0
  47. package/dist/plugins/rsc-reference-validation-normalizer.js +48 -0
  48. package/dist/plugins/sass.d.ts +17 -1
  49. package/dist/plugins/sass.js +74 -1
  50. package/dist/plugins/styled-jsx.d.ts +16 -0
  51. package/dist/plugins/styled-jsx.js +149 -0
  52. package/dist/routing/app-route-graph.js +22 -16
  53. package/dist/routing/file-matcher.d.ts +8 -1
  54. package/dist/routing/file-matcher.js +15 -3
  55. package/dist/server/app-browser-entry.js +44 -14
  56. package/dist/server/app-browser-navigation-controller.js +5 -2
  57. package/dist/server/app-browser-server-action-client.js +5 -3
  58. package/dist/server/app-browser-state.d.ts +1 -0
  59. package/dist/server/app-browser-state.js +1 -1
  60. package/dist/server/app-layout-param-observation.d.ts +1 -1
  61. package/dist/server/app-page-boundary.js +2 -1
  62. package/dist/server/app-page-cache-finalizer.d.ts +1 -0
  63. package/dist/server/app-page-cache-finalizer.js +3 -3
  64. package/dist/server/app-page-cache-render.d.ts +1 -1
  65. package/dist/server/app-page-cache.js +23 -6
  66. package/dist/server/app-page-dispatch.d.ts +2 -1
  67. package/dist/server/app-page-dispatch.js +27 -10
  68. package/dist/server/app-page-element-builder.js +1 -0
  69. package/dist/server/app-page-execution.js +2 -1
  70. package/dist/server/app-page-render-identity.d.ts +1 -0
  71. package/dist/server/app-page-render-identity.js +2 -1
  72. package/dist/server/app-page-render.d.ts +3 -1
  73. package/dist/server/app-page-render.js +67 -16
  74. package/dist/server/app-page-response.d.ts +7 -0
  75. package/dist/server/app-page-response.js +16 -4
  76. package/dist/server/app-page-route-wiring.js +3 -3
  77. package/dist/server/app-page-stream.d.ts +2 -1
  78. package/dist/server/app-page-stream.js +1 -1
  79. package/dist/server/app-route-handler-execution.d.ts +1 -1
  80. package/dist/server/app-route-tree-prefetch.d.ts +43 -0
  81. package/dist/server/app-route-tree-prefetch.js +187 -0
  82. package/dist/server/app-router-entry.js +1 -1
  83. package/dist/server/app-rsc-cache-busting.d.ts +2 -1
  84. package/dist/server/app-rsc-cache-busting.js +9 -5
  85. package/dist/server/app-rsc-handler.d.ts +6 -0
  86. package/dist/server/app-rsc-handler.js +88 -10
  87. package/dist/server/app-rsc-render-mode.d.ts +3 -5
  88. package/dist/server/app-rsc-render-mode.js +5 -12
  89. package/dist/server/app-rsc-request-normalization.d.ts +3 -4
  90. package/dist/server/app-rsc-request-normalization.js +4 -5
  91. package/dist/server/app-server-action-execution.js +6 -5
  92. package/dist/server/app-ssr-entry.js +1 -1
  93. package/dist/server/cache-control.d.ts +3 -1
  94. package/dist/server/cache-control.js +13 -1
  95. package/dist/server/dev-module-runner.js +1 -1
  96. package/dist/server/dev-origin-check.d.ts +2 -2
  97. package/dist/server/dev-origin-check.js +2 -2
  98. package/dist/server/dev-server.d.ts +11 -1
  99. package/dist/server/dev-server.js +82 -24
  100. package/dist/server/headers.d.ts +6 -2
  101. package/dist/server/headers.js +11 -5
  102. package/dist/server/image-optimization.d.ts +12 -1
  103. package/dist/server/image-optimization.js +13 -1
  104. package/dist/server/isr-cache.d.ts +13 -4
  105. package/dist/server/isr-cache.js +8 -4
  106. package/dist/server/pages-data-route.d.ts +4 -2
  107. package/dist/server/pages-data-route.js +18 -4
  108. package/dist/server/pages-dev-module-url.d.ts +2 -1
  109. package/dist/server/pages-dev-module-url.js +6 -3
  110. package/dist/server/pages-node-compat.d.ts +12 -1
  111. package/dist/server/pages-node-compat.js +50 -1
  112. package/dist/server/pages-page-data.d.ts +9 -0
  113. package/dist/server/pages-page-data.js +18 -10
  114. package/dist/server/pages-page-handler.js +19 -7
  115. package/dist/server/pages-page-response.d.ts +1 -0
  116. package/dist/server/pages-page-response.js +5 -4
  117. package/dist/server/pages-request-pipeline.d.ts +8 -6
  118. package/dist/server/pages-request-pipeline.js +31 -7
  119. package/dist/server/pages-router-entry.js +1 -1
  120. package/dist/server/prerender-manifest.d.ts +15 -1
  121. package/dist/server/prerender-manifest.js +29 -1
  122. package/dist/server/prod-server.d.ts +10 -7
  123. package/dist/server/prod-server.js +43 -28
  124. package/dist/server/request-pipeline.js +1 -1
  125. package/dist/server/static-file-cache.js +1 -1
  126. package/dist/shims/cache-handler.js +8 -1
  127. package/dist/shims/cache.d.ts +1 -1
  128. package/dist/shims/cache.js +3 -0
  129. package/dist/shims/cdn-cache.d.ts +2 -7
  130. package/dist/shims/cdn-cache.js +2 -14
  131. package/dist/shims/fetch-cache.d.ts +3 -1
  132. package/dist/shims/fetch-cache.js +77 -52
  133. package/dist/shims/internal/app-prefetch-fetch-queue.d.ts +10 -0
  134. package/dist/shims/internal/app-prefetch-fetch-queue.js +61 -0
  135. package/dist/shims/internal/hybrid-client-route-owner.d.ts +2 -1
  136. package/dist/shims/internal/hybrid-client-route-owner.js +34 -1
  137. package/dist/shims/internal/pages-data-fetch-dedup.d.ts +2 -1
  138. package/dist/shims/internal/pages-data-fetch-dedup.js +13 -2
  139. package/dist/shims/internal/pages-data-target.d.ts +8 -3
  140. package/dist/shims/internal/pages-data-target.js +9 -4
  141. package/dist/shims/link.d.ts +1 -1
  142. package/dist/shims/link.js +179 -42
  143. package/dist/shims/navigation.d.ts +15 -3
  144. package/dist/shims/navigation.js +202 -39
  145. package/dist/shims/request-context.js +18 -0
  146. package/dist/shims/request-state-types.d.ts +2 -2
  147. package/dist/shims/router.js +31 -15
  148. package/dist/shims/unified-request-context.d.ts +1 -1
  149. package/dist/shims/unified-request-context.js +1 -0
  150. package/dist/typegen.js +1 -1
  151. package/dist/utils/middleware-request-headers.js +1 -1
  152. package/dist/utils/project.d.ts +1 -1
  153. package/dist/utils/protocol-headers.d.ts +7 -1
  154. package/dist/utils/protocol-headers.js +7 -1
  155. package/dist/utils/vite-version.d.ts +4 -12
  156. package/dist/utils/vite-version.js +39 -21
  157. package/package.json +31 -13
  158. package/dist/cloudflare/index.d.ts +0 -3
  159. package/dist/cloudflare/index.js +0 -3
  160. package/dist/packages/cloudflare/src/cache/cdn-adapter.runtime.js +0 -102
  161. package/dist/packages/cloudflare/src/cache/kv-data-adapter.runtime.d.ts +0 -126
  162. package/dist/packages/cloudflare/src/cache/kv-data-adapter.runtime.js +0 -435
  163. package/dist/packages/cloudflare/src/deploy-config.js +0 -150
  164. package/dist/packages/cloudflare/src/deploy-help.js +0 -55
  165. package/dist/packages/cloudflare/src/deploy.js +0 -276
  166. package/dist/packages/cloudflare/src/tpr.d.ts +0 -45
  167. package/dist/packages/cloudflare/src/tpr.js +0 -561
  168. package/dist/packages/cloudflare/src/utils/cache-control-metadata.js +0 -20
package/README.md CHANGED
@@ -1,10 +1,34 @@
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
 
@@ -25,13 +49,15 @@ The skill handles compatibility checking, dependency installation, config genera
25
49
  ### Or do it manually
26
50
 
27
51
  ```bash
28
- npm install -D vinext vite @vitejs/plugin-react
52
+ npm install vinext
53
+ npm install -D vite @vitejs/plugin-react
29
54
  ```
30
55
 
31
56
  If you're using the App Router, also install:
32
57
 
33
58
  ```bash
34
- npm install -D @vitejs/plugin-rsc react-server-dom-webpack
59
+ npm install react-server-dom-webpack
60
+ npm install -D @vitejs/plugin-rsc
35
61
  ```
36
62
 
37
63
  Replace `next` with `vinext` in your scripts:
@@ -93,9 +119,15 @@ Environment variables: `PORT` (default `3000`), `HOST` (default `0.0.0.0`).
93
119
 
94
120
  ### Starting a new vinext project
95
121
 
96
- Run `npm create next-app@latest` to create a new Next.js project, and then follow these instructions to migrate it to vinext.
122
+ Use `create-vinext-app` for new projects. It creates a TypeScript App Router project
123
+ with Tailwind CSS and then runs the same vinext init setup used for existing apps:
124
+
125
+ ```bash
126
+ pnpm create vinext-app@latest my-app
127
+ ```
97
128
 
98
- In the future, we will have a proper `npm create vinext` new project workflow.
129
+ The generated project is Cloudflare Workers-ready by default. Pass
130
+ `--platform=node` if you want the Node target instead.
99
131
 
100
132
  ### Migrating an existing Next.js project
101
133
 
@@ -108,7 +140,7 @@ npx vinext init
108
140
  This will:
109
141
 
110
142
  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
143
+ 2. Install vinext runtime packages as dependencies and Vite/plugin tooling as devDependencies
112
144
  3. Rename CJS config files (e.g. `postcss.config.js` -> `.cjs`) to avoid ESM conflicts
113
145
  4. Add `"type": "module"` to `package.json`
114
146
  5. Add `dev:vinext`, `build:vinext`, and `start:vinext` scripts to `package.json`
@@ -136,7 +168,7 @@ the compatibility report.
136
168
 
137
169
  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
170
 
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.
171
+ 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
172
 
141
173
  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
174
 
@@ -158,13 +190,13 @@ vinext works everywhere. It natively supports Cloudflare Workers (with `npx @vin
158
190
  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
191
 
160
192
  **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.
193
+ 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
194
 
163
195
  **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.
196
+ [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
197
 
166
198
  **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.
199
+ 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
200
 
169
201
  **Can I just self-host Next.js?**
170
202
  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 +208,7 @@ The test suite has over 1,700 Vitest tests and 380 Playwright E2E tests. This in
176
208
  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
209
 
178
210
  **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.
211
+ 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
212
 
181
213
  **Does this support the Pages Router, App Router, or both?**
182
214
  Both. File-system routing, SSR, client hydration, and deployment to Cloudflare Workers work for both routers.
@@ -240,7 +272,7 @@ Use `--env <name>` to target `wrangler.jsonc` `env.<name>`. `--preview` is short
240
272
  The init command also auto-detects and fixes common migration issues:
241
273
 
242
274
  - Adds `"type": "module"` to package.json if missing
243
- - Resolves tsconfig.json path aliases automatically (via `vite-tsconfig-paths`)
275
+ - Resolves tsconfig.json path aliases automatically with Vite's native resolver
244
276
  - Detects MDX usage and configures `@mdx-js/rollup`
245
277
  - Renames CJS config files (postcss.config.js, etc.) to `.cjs` when needed
246
278
  - 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 +632,16 @@ vinext({
600
632
 
601
633
  ## What's NOT supported (and won't be)
602
634
 
603
- These are intentional exclusions. For things that are missing today but on the roadmap, see [Known limitations](#known-limitations) below.
635
+ 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
636
 
605
637
  - **Vercel-specific features** — `@vercel/og` edge runtime, Vercel Analytics integration, Vercel KV/Blob/Postgres bindings. Use platform equivalents.
606
638
  - **AMP** — Deprecated since Next.js 13. `useAmp()` returns `false`.
607
639
  - **`next export` (legacy)** — Use `output: 'export'` in config instead.
608
640
  - **Turbopack/webpack configuration** — This runs on Vite. Use Vite plugins instead of webpack loaders/plugins.
609
641
  - **`next/jest`** — Use Vitest.
610
- - **`create-next-app` scaffolding** — Not a goal.
642
+ - **`create-next-app` scaffolding** — Use `create-vinext-app` for new vinext projects.
611
643
  - **Bug-for-bug parity with undocumented behavior** — If it's not in the Next.js docs, we probably don't replicate it.
612
644
 
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
645
  ## Benchmarks
625
646
 
626
647
  > **Caveat:** Benchmarks are hard to get right and these are early results. Take them as directional, not definitive.
@@ -642,7 +663,7 @@ Benchmarks run on GitHub CI runners (2-core Ubuntu) on every merge to `main`. Se
642
663
 
643
664
  Analysis of the build output shows two main factors:
644
665
 
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.
666
+ 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
667
  2. **Framework overhead**: Next.js ships more client-side infrastructure (router, Turbopack runtime loader, prefetching, error handling) than vinext's lighter client runtime.
647
668
 
648
669
  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 +790,11 @@ Or add it to your `package.json` as a file dependency:
769
790
  }
770
791
  ```
771
792
 
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.
793
+ 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
794
 
774
795
  ## Contributing
775
796
 
776
- This project is experimental and under active development. Issues and PRs are welcome.
797
+ This project is under active development. Issues and PRs are welcome.
777
798
 
778
799
  ### CI
779
800
 
@@ -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 };
@@ -78,7 +78,7 @@ function getPackageName(id) {
78
78
  * mobile devices.
79
79
  * - No major Vite-based framework (Remix, SvelteKit, Astro, TanStack)
80
80
  * uses per-package splitting. Next.js only isolates packages >160KB.
81
- * - Rollup's graph-based splitting already handles the common case
81
+ * - The bundler's graph-based splitting already handles the common case
82
82
  * well: shared dependencies between routes get their own chunks,
83
83
  * and route-specific code stays in route chunks.
84
84
  */
@@ -101,15 +101,6 @@ function createClientManualChunks(shimsDir, preserveRouteBoundaries = false) {
101
101
  }
102
102
  };
103
103
  }
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
104
  function createClientFileNameConfig(assetsDir) {
114
105
  const chunksDir = `${assetsDir}/chunks`;
115
106
  return {
@@ -117,14 +108,6 @@ function createClientFileNameConfig(assetsDir) {
117
108
  chunkFileNames: `${chunksDir}/[name]-[hash].js`
118
109
  };
119
110
  }
120
- function createClientOutputConfig(clientManualChunks, assetsDir) {
121
- return {
122
- ...createClientFileNameConfig(assetsDir),
123
- assetFileNames: createClientAssetFileNames(assetsDir),
124
- manualChunks: clientManualChunks,
125
- experimentalMinChunkSize: 1e4
126
- };
127
- }
128
111
  function createClientCodeSplittingConfig(clientManualChunks) {
129
112
  return {
130
113
  minSize: 1e4,
@@ -174,97 +157,36 @@ function isRscFrameworkModule(id) {
174
157
  const pkg = getPackageName(id);
175
158
  return pkg !== null && FRAMEWORK_PACKAGES.includes(pkg);
176
159
  }
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
160
  /**
186
161
  * 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).
162
+ * dedicated "framework" chunk in the RSC server build. See
163
+ * {@link RSC_FRAMEWORK_CHUNK_TEST} for the motivation (issue #1549). Framework
164
+ * modules that are only reachable through dynamic imports must stay out of the
165
+ * eager framework chunk (issue #2073).
192
166
  */
193
- function createRscFrameworkChunkOutputConfig(viteMajorVersion) {
194
- if (viteMajorVersion >= 8) return { codeSplitting: { groups: [{
167
+ function createRscFrameworkChunkOutputConfig() {
168
+ return { codeSplitting: { groups: [{
195
169
  name: "framework",
196
170
  test: RSC_FRAMEWORK_CHUNK_TEST,
197
171
  entriesAware: true
198
172
  }] } };
199
- return { manualChunks(id, meta) {
200
- return isRscFrameworkModule(id) && isStaticallyReachableFromEntry(id, meta) ? "framework" : void 0;
201
- } };
202
173
  }
203
174
  /**
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)
175
+ * Returns Rolldown treeshake configuration for production client builds.
249
176
  *
250
177
  * 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.
178
+ * by Rolldown and provides the DCE benefits for barrel-exporting libraries. It
179
+ * treats node_modules as side-effect-free while preserving side effects in
180
+ * local code.
254
181
  */
255
- function getClientTreeshakeConfigForVite(viteMajorVersion) {
256
- if (viteMajorVersion >= 8) return { moduleSideEffects: "no-external" };
257
- return {
258
- preset: "recommended",
259
- moduleSideEffects: "no-external"
260
- };
182
+ function getClientTreeshakeConfig() {
183
+ return { moduleSideEffects: "no-external" };
261
184
  }
262
185
  function getBuildBundlerOptions(build) {
263
- const buildConfig = build;
264
- return buildConfig?.rolldownOptions ?? buildConfig?.rollupOptions;
186
+ return build?.rolldownOptions;
265
187
  }
266
- function withBuildBundlerOptions(viteMajorVersion, bundlerOptions) {
267
- return viteMajorVersion >= 8 ? { rolldownOptions: bundlerOptions } : { rollupOptions: bundlerOptions };
188
+ function withBuildBundlerOptions(bundlerOptions) {
189
+ return { rolldownOptions: bundlerOptions };
268
190
  }
269
191
  //#endregion
270
- export { RSC_FRAMEWORK_CHUNK_TEST, clientTreeshakeConfig, createClientAssetFileNames, createClientCodeSplittingConfig, createClientFileNameConfig, createClientManualChunks, createClientOutputConfig, createRscFrameworkChunkOutputConfig, getBuildBundlerOptions, getClientTreeshakeConfigForVite, isRscFrameworkModule, withBuildBundlerOptions };
192
+ export { RSC_FRAMEWORK_CHUNK_TEST, createClientAssetFileNames, createClientCodeSplittingConfig, createClientFileNameConfig, createClientManualChunks, createRscFrameworkChunkOutputConfig, getBuildBundlerOptions, getClientTreeshakeConfig, isRscFrameworkModule, withBuildBundlerOptions };
@@ -13,6 +13,8 @@ type EmitRestoredCssUrlAsset = (asset: {
13
13
  * safe to run on every build-environment stylesheet, vendored CSS included.
14
14
  */
15
15
  declare function markCssUrlAssetReferences(code: string, id: string): string | null;
16
+ /** Rebase relative asset URLs when Sass inlines a partial into an entry file. */
17
+ declare function rebaseCssUrlAssetReferences(code: string, sourceDirectory: string, targetDirectory: string): string | null;
16
18
  /**
17
19
  * Mutates emitted CSS assets in place so byte-identical `url()` dependencies
18
20
  * keep their distinct Next-compatible filenames. Sibling files are produced via
@@ -26,4 +28,4 @@ declare function markCssUrlAssetReferences(code: string, id: string): string | n
26
28
  */
27
29
  declare function restoreDedupedCssAssetReferences(bundle: CssUrlAssetBundle, emitRestoredAsset: EmitRestoredCssUrlAsset): void;
28
30
  //#endregion
29
- export { markCssUrlAssetReferences, restoreDedupedCssAssetReferences };
31
+ export { markCssUrlAssetReferences, rebaseCssUrlAssetReferences, restoreDedupedCssAssetReferences };
@@ -1,3 +1,4 @@
1
+ import path from "node:path";
1
2
  //#region src/build/css-url-assets.ts
2
3
  /**
3
4
  * Next-parity for CSS `url()` asset dependencies.
@@ -128,6 +129,22 @@ function markCssUrlAssetReferences(code, id) {
128
129
  });
129
130
  });
130
131
  }
132
+ /** Rebase relative asset URLs when Sass inlines a partial into an entry file. */
133
+ function rebaseCssUrlAssetReferences(code, sourceDirectory, targetDirectory) {
134
+ return rewriteCssUrls(code, (rawUrl) => {
135
+ const parts = splitUrl(rawUrl.trim());
136
+ if (!isRelativeAssetUrl(parts.path)) return null;
137
+ const lower = parts.path.toLowerCase();
138
+ if (!CSS_ASSET_EXT_RE.test(lower) || lower.endsWith(".css")) return null;
139
+ const absolutePath = path.resolve(sourceDirectory, parts.path);
140
+ let rebasedPath = path.relative(targetDirectory, absolutePath).replaceAll("\\", "/");
141
+ if (!rebasedPath.startsWith(".")) rebasedPath = `./${rebasedPath}`;
142
+ return joinUrl({
143
+ ...parts,
144
+ path: rebasedPath
145
+ });
146
+ });
147
+ }
131
148
  function isCssFileName(fileName) {
132
149
  return fileName.toLowerCase().endsWith(".css");
133
150
  }
@@ -210,4 +227,4 @@ function stripChunkMarkers(code) {
210
227
  return code.replace(CSS_URL_MARKER_PARAM_RE, (_m, leadingQuestion) => leadingQuestion ? leadingQuestion : "");
211
228
  }
212
229
  //#endregion
213
- export { markCssUrlAssetReferences, restoreDedupedCssAssetReferences };
230
+ export { markCssUrlAssetReferences, rebaseCssUrlAssetReferences, restoreDedupedCssAssetReferences };
@@ -1,4 +1,7 @@
1
1
  //#region src/build/inject-pregenerated-paths.d.ts
2
+ declare global {
3
+ var __VINEXT_PREGENERATED_CONCRETE_PATHS: unknown;
4
+ }
2
5
  declare function injectPregeneratedConcretePaths(root: string): void;
3
6
  //#endregion
4
7
  export { injectPregeneratedConcretePaths };
@@ -11,7 +11,10 @@ function injectPregeneratedConcretePaths(root) {
11
11
  if (!fs.existsSync(workerEntry)) return;
12
12
  let code = fs.readFileSync(workerEntry, "utf-8").replace(VINEXT_PREGEN_RE, "");
13
13
  const table = readPrerenderManifest(path.join(root, "dist", "server", "vinext-prerender.json"))?.pregeneratedConcretePaths ?? [];
14
- if (table.length > 0) code = `${VINEXT_PREGEN_START}\nglobalThis.__VINEXT_PREGENERATED_CONCRETE_PATHS = ${JSON.stringify(table)};\n${VINEXT_PREGEN_END}\n` + code;
14
+ if (table.length > 0) {
15
+ globalThis.__VINEXT_PREGENERATED_CONCRETE_PATHS = table;
16
+ code = `${VINEXT_PREGEN_START}\nglobalThis.__VINEXT_PREGENERATED_CONCRETE_PATHS = ${JSON.stringify(table)};\n${VINEXT_PREGEN_END}\n` + code;
17
+ } else delete globalThis.__VINEXT_PREGENERATED_CONCRETE_PATHS;
15
18
  fs.writeFileSync(workerEntry, code);
16
19
  }
17
20
  //#endregion
@@ -0,0 +1,23 @@
1
+ import { ResolvedNextConfig } from "../config/next-config.js";
2
+ import { VinextRouteRootConfig } from "../config/prerender.js";
3
+
4
+ //#region src/build/prerender-paths.d.ts
5
+ type PrerenderPathManifest = {
6
+ buildId?: string;
7
+ trailingSlash?: boolean;
8
+ paths: string[];
9
+ };
10
+ declare const PRERENDER_PATH_DISCOVERY_ENV = "__VINEXT_PRERENDER_PATH_DISCOVERY";
11
+ declare const PRERENDER_PATHS_MANIFEST = "vinext-prerender-paths.json";
12
+ type EmitPrerenderPathManifestOptions = {
13
+ root: string;
14
+ nextConfigOverride?: Partial<ResolvedNextConfig>;
15
+ appDir?: string | null;
16
+ pagesDir?: string | null;
17
+ routeRootConfig?: VinextRouteRootConfig | null;
18
+ pagesBundlePath?: string;
19
+ rscBundlePath?: string;
20
+ };
21
+ declare function emitPrerenderPathManifest(options: EmitPrerenderPathManifestOptions): Promise<PrerenderPathManifest | null>;
22
+ //#endregion
23
+ export { PRERENDER_PATHS_MANIFEST, PRERENDER_PATH_DISCOVERY_ENV, PrerenderPathManifest, emitPrerenderPathManifest };