vite-plugin-react-server 0.3.19 → 1.0.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 (109) hide show
  1. package/README.md +245 -144
  2. package/dist/package.json +13 -6
  3. package/dist/plugin/collect-manifest-client-files.d.ts.map +1 -1
  4. package/dist/plugin/collect-manifest-client-files.js +25 -11
  5. package/dist/plugin/collect-manifest-client-files.js.map +1 -1
  6. package/dist/plugin/components.d.ts +3 -13
  7. package/dist/plugin/components.d.ts.map +1 -1
  8. package/dist/plugin/components.js +3 -54
  9. package/dist/plugin/config/defaults.d.ts +9 -2
  10. package/dist/plugin/config/defaults.d.ts.map +1 -1
  11. package/dist/plugin/config/defaults.js +3 -2
  12. package/dist/plugin/config/defaults.js.map +1 -1
  13. package/dist/plugin/config/resolveOptions.d.ts +2 -2
  14. package/dist/plugin/config/resolveOptions.d.ts.map +1 -1
  15. package/dist/plugin/config/resolveOptions.js +6 -0
  16. package/dist/plugin/config/resolveOptions.js.map +1 -1
  17. package/dist/plugin/config/resolveUserConfig.d.ts.map +1 -1
  18. package/dist/plugin/config/resolveUserConfig.js +178 -149
  19. package/dist/plugin/config/resolveUserConfig.js.map +1 -1
  20. package/dist/plugin/css-collector-inline.d.ts +10 -0
  21. package/dist/plugin/css-collector-inline.d.ts.map +1 -0
  22. package/dist/plugin/css-collector-inline.js +55 -0
  23. package/dist/plugin/css-collector-inline.js.map +1 -0
  24. package/dist/plugin/css-collector.d.ts +14 -0
  25. package/dist/plugin/css-collector.d.ts.map +1 -0
  26. package/dist/plugin/css-collector.js +49 -0
  27. package/dist/plugin/css-collector.js.map +1 -0
  28. package/dist/plugin/helpers/createHandler.d.ts +3 -8
  29. package/dist/plugin/helpers/createHandler.d.ts.map +1 -1
  30. package/dist/plugin/helpers/createHandler.js +52 -55
  31. package/dist/plugin/helpers/createHandler.js.map +1 -1
  32. package/dist/plugin/helpers/createRscStream.d.ts +14 -4
  33. package/dist/plugin/helpers/createRscStream.d.ts.map +1 -1
  34. package/dist/plugin/helpers/createRscStream.js +25 -16
  35. package/dist/plugin/helpers/createRscStream.js.map +1 -1
  36. package/dist/plugin/html.d.ts +5 -0
  37. package/dist/plugin/html.d.ts.map +1 -0
  38. package/dist/plugin/html.js +11 -0
  39. package/dist/plugin/html.js.map +1 -0
  40. package/dist/plugin/react-client/plugin.d.ts.map +1 -1
  41. package/dist/plugin/react-client/plugin.js +3 -2
  42. package/dist/plugin/react-client/plugin.js.map +1 -1
  43. package/dist/plugin/react-server/plugin.d.ts.map +1 -1
  44. package/dist/plugin/react-server/plugin.js +47 -16
  45. package/dist/plugin/react-server/plugin.js.map +1 -1
  46. package/dist/plugin/react-static/plugin.d.ts.map +1 -1
  47. package/dist/plugin/react-static/plugin.js +20 -12
  48. package/dist/plugin/react-static/plugin.js.map +1 -1
  49. package/dist/plugin/react-static/types.d.ts +2 -0
  50. package/dist/plugin/react-static/types.d.ts.map +1 -0
  51. package/dist/plugin/react-static/types.js +1 -0
  52. package/dist/plugin/types.d.ts +48 -11
  53. package/dist/plugin/types.d.ts.map +1 -1
  54. package/dist/plugin/worker/html/messageHandler.d.ts.map +1 -1
  55. package/dist/plugin/worker/html/messageHandler.js +4 -1
  56. package/dist/plugin/worker/html/messageHandler.js.map +1 -1
  57. package/dist/plugin/worker/html/renderPages.d.ts +8 -25
  58. package/dist/plugin/worker/html/renderPages.d.ts.map +1 -1
  59. package/dist/plugin/worker/html/renderPages.js +61 -44
  60. package/dist/plugin/worker/html/renderPages.js.map +1 -1
  61. package/dist/plugin/worker/rsc/messageHandler.d.ts.map +1 -1
  62. package/dist/plugin/worker/rsc/messageHandler.js +37 -22
  63. package/dist/plugin/worker/rsc/messageHandler.js.map +1 -1
  64. package/dist/plugin/worker/types.d.ts +3 -0
  65. package/dist/plugin/worker/types.d.ts.map +1 -1
  66. package/dist/tsconfig.tsbuildinfo +1 -1
  67. package/package.json +12 -4
  68. package/plugin/collect-manifest-client-files.ts +25 -10
  69. package/plugin/components.ts +3 -0
  70. package/plugin/config/defaults.tsx +10 -9
  71. package/plugin/config/resolveOptions.ts +10 -5
  72. package/plugin/config/resolveUserConfig.ts +218 -177
  73. package/plugin/css-collector-inline.tsx +60 -0
  74. package/plugin/css-collector.tsx +62 -0
  75. package/plugin/helpers/createHandler.ts +73 -83
  76. package/plugin/helpers/createRscStream.ts +49 -21
  77. package/plugin/html.tsx +9 -0
  78. package/plugin/react-client/plugin.ts +3 -2
  79. package/plugin/react-server/plugin.ts +58 -22
  80. package/plugin/react-static/plugin.ts +20 -11
  81. package/plugin/react-static/types.ts +3 -0
  82. package/plugin/types.ts +53 -11
  83. package/plugin/worker/html/README.md +1 -6
  84. package/plugin/worker/html/messageHandler.ts +5 -2
  85. package/plugin/worker/html/renderPages.ts +82 -78
  86. package/plugin/worker/rsc/messageHandler.tsx +41 -26
  87. package/plugin/worker/types.ts +3 -0
  88. package/dist/plugin/components.js.map +0 -1
  89. package/dist/plugin/getEnv.d.ts +0 -19
  90. package/dist/plugin/getEnv.d.ts.map +0 -1
  91. package/dist/plugin/getEnv.js +0 -107
  92. package/dist/plugin/module-graph.d.ts +0 -10
  93. package/dist/plugin/module-graph.d.ts.map +0 -1
  94. package/dist/plugin/module-graph.js +0 -35
  95. package/dist/plugin/worker/html/plugin.d.ts +0 -4
  96. package/dist/plugin/worker/html/plugin.d.ts.map +0 -1
  97. package/dist/plugin/worker/html/plugin.js +0 -93
  98. package/dist/plugin/worker/plugin.d.ts +0 -19
  99. package/dist/plugin/worker/plugin.d.ts.map +0 -1
  100. package/dist/plugin/worker/plugin.js +0 -23
  101. package/dist/plugin/worker/rsc/plugin.d.ts +0 -4
  102. package/dist/plugin/worker/rsc/plugin.d.ts.map +0 -1
  103. package/dist/plugin/worker/rsc/plugin.js +0 -75
  104. package/plugin/components.tsx +0 -59
  105. package/plugin/getEnv.ts +0 -135
  106. package/plugin/module-graph.ts +0 -48
  107. package/plugin/worker/html/plugin.ts +0 -100
  108. package/plugin/worker/plugin.ts +0 -26
  109. package/plugin/worker/rsc/plugin.ts +0 -83
package/README.md CHANGED
@@ -1,7 +1,6 @@
1
1
  # Vite React Server Plugin
2
2
 
3
- A Vite plugin that enables React Server Components (RSC) streaming and static building of html pages. Uses experimental dependencies from React, specifically `react-server-dom-esm`.
4
-
3
+ A Vite plugin that enables React Server Components (RSC) streaming and static HTML page generation. It leverages experimental dependencies from React, specifically `react-server-dom-esm`.
5
4
 
6
5
  ## Example Projects
7
6
 
@@ -10,205 +9,307 @@ A Vite plugin that enables React Server Components (RSC) streaming and static bu
10
9
 
11
10
  ## Installation
12
11
 
13
- ```ts
14
- npm install -D vite-plugin-react-stream
12
+ ```sh
13
+ npm install -D vite-plugin-react-server
14
+ ```
15
+
16
+ ## Open Source and Work in Progress
17
+
18
+ This project uses the latest *OSS-experimental* React version from [the official React GitHub repository](https://github.com/facebook/react). The plugin includes a patch system to facilitate setup. First, install dependencies and patches:
19
+
20
+ ```sh
21
+ npm install -D patch-package react@experimental react-dom@experimental react-server-dom-esm
15
22
  ```
16
23
 
17
- ## Open source and work in progress
24
+ Add the following command to your `package.json` scripts:
18
25
 
19
- This project uses the latest* oss-experimental React version taken from [the offical React github repository](https://github.com/facebook/react). This plugin offers a patch system that can get you up and running quickly. First run `npm install -D patch-package react@experimental react-dom@experimental react-server-dom-esm` and add the follow command to the scripts
20
26
  ```json
21
- "patch": "check-react-version && patch",
27
+ "patch": "check-react-version && patch"
22
28
  ```
23
- Now run `npm run patch` to create the patch. It will tell you to add this as well:
29
+
30
+ Run the patch command:
31
+
32
+ ```sh
33
+ npm run patch
34
+ ```
35
+
36
+ It will instruct you to add:
37
+
24
38
  ```json
25
- "postinstall": "patch-package",
39
+ "postinstall": "patch-package"
26
40
  ```
27
- This will apply the patch for us after running `npm install`
28
41
 
29
- If errors start showing up related to the missing `react-server-dom-esm` package - it's likely the postinstall step didn't run.
42
+ This ensures the patch is applied after every `npm install`. If errors arise related to `react-server-dom-esm`, verify that the postinstall step ran.
30
43
 
31
- ## Included plugins
32
- ### vite-plugin-react-server/client
33
- - Client build
34
- - Server Worker thread (rsc-worker)
44
+ ---
35
45
 
36
- ### vite-plugin-react-server
37
- - Server build
38
- - Client Worker thread (html-worker)
46
+ ## Plugin Structure and Purpose
39
47
 
40
- ### vite-plugin-react-server/preserver
41
- - Preserves "use client" and "use server" condition in source code
48
+ ### Strict Client-Server Separation
42
49
 
43
- ### vite-plugin-react-server/transformer
44
- - Transforms client components for server environment or vice versa
50
+ This plugin enforces a **strict architectural separation** between client and server execution. It achieves this by requiring **distinct entry files** for both environments, preventing unintended dependencies or cross-thread interactions. While this approach improves maintainability and clarity, it requires additional boilerplate.
45
51
 
46
- ### vite-plugin-react-server/worker/html
47
- - Create your own html worker (client side worker)
48
- - Make html worker part of the application
52
+ The separation is accomplished through two complementary plugins:
49
53
 
50
- ### vite-plugin-react-server/worker/rsc
51
- - Create your own rsc worker (server side worker)
52
- - Make rsc worker part of the application
54
+ - **vite-plugin-react-server/client** → Handles client-side rendering and ESM bundling
55
+ - **vite-plugin-react-server** Manages server-side streaming and RSC processing
53
56
 
54
- ## Configuration
55
- For client and server boundaries to work, it's very important to know which environment (or thread) the system is in. Let's setup the client first.
57
+ This ensures that client-side and server-side concerns remain isolated from the beginning, reducing potential inconsistencies.
58
+
59
+ ### Custom composition
60
+
61
+ You can pick and choose only the plugins you like to get the desired behavior as well. For example, we can choose only to use the preserver, the transformer, static plugin, etc.
62
+
63
+ ### Worker support
64
+
65
+ The client plugin uses the `rsc-worker` to create server side streams. The server plugin uses the `html-worker` to create client side html. If you don't want to use the rsc-worker, simply don't serve the client plugin. If you don't want to use the `html-worker` simply don't configure the `build.pages` option.
66
+
67
+ ### Custom Worker
68
+
69
+ Both workers can be customized using the `htmlWorkerPath` and `rscWorkerPath` respectively. The paths will be used to create the workers instead of the prebuilt worker included with this plugin. If these paths are defined, they will be made part of your application build as well.
70
+
71
+ Keep in mind that, using your custom worker means interacting with the message system of this plugin during development/static generation process.
72
+
73
+
74
+ ## Plugin Usage
75
+
76
+ ### Configuration
56
77
  ```ts
57
- import { vitePluginReactClient } from "vite-plugin-react-server/client";
58
- import { config } from "./config.js";
59
- import { defineConfig } from "vite";
60
- export default defineConfig(()=> {
61
- return {
62
- plugins: vitePluginReactClient(config),
78
+ import type { StreamPluginOptions } from "vite-plugin-react-server/server";
79
+
80
+ const createRouter = (file: "props.ts" | "page.tsx") => (url: string) => {
81
+ switch (url) {
82
+ case "/bidoof":
83
+ case "/bidoof/index.rsc":
84
+ return `src/page/bidoof/${file}`;
85
+ case "/404":
86
+ case "/404/index.rsc":
87
+ return `src/page/404/${file}`;
88
+ case "/":
89
+ case "/index.rsc":
90
+ return `src/page/${file}`;
91
+ default:
92
+ throw new Error(`Unknown route: ${url}`);
63
93
  }
94
+ };
95
+
96
+ export const config = {
97
+ moduleBase: "src",
98
+ Page: createRouter("page.tsx"),
99
+ props: createRouter("props.ts"),
100
+ Html: Html,
101
+ build: {
102
+ pages: ["/", "/bidoof", "/404" ],
103
+ },
104
+ } satisfies StreamPluginOptions;
105
+ ```
106
+
107
+ ### vite-plugin-react-server/client
108
+
109
+ Used in `vite.config.ts` for standard Vite client-side behavior
110
+
111
+ ```ts
112
+ import { defineConfig, type Plugin } from "vite";
113
+ import { vitePluginReactClient } from "vite-plugin-react-server/client";
114
+ import { config } from "./vite.react.config";
115
+
116
+ export default defineConfig({
117
+ plugins: vitePluginReactClient(config),
64
118
  });
65
119
  ```
66
- The client plugin can help to quickly setup a client side build that'll work with the server build. It also allows you to serve the application. To handle the rsc streams, it uses the rsc-worker. You can read more about the rsc-worker [here](/docs)
120
+
121
+ #### Build Steps
122
+
123
+ ```sh
124
+ vite build
125
+ ```
126
+ Outputs React client-side ESM files to `dist/client`.
127
+
128
+ ```sh
129
+ vite build --ssr
130
+ ```
131
+ Outputs files for server-side execution to `dist/server`.
132
+
133
+ ```sh
134
+ vite preview
135
+ ```
136
+ Serves the static directory.
137
+
138
+ ---
139
+
140
+ ### vite-plugin-react-server
141
+
142
+ Used in `vite.server.config.ts`, this plugin strictly separates client and server execution. The client components will be emitted as references.
67
143
 
68
144
  ```ts
145
+ import { defineConfig, Plugin } from "vite";
69
146
  import { vitePluginReactServer } from "vite-plugin-react-server";
70
- import { config } from "./config.js";
71
- import { defineConfig } from "vite";
72
- export default defineConfig(()=> {
73
- return {
74
- plugins: vitePluginReactServer(config),
75
- }
147
+ import { config } from "./vite.react.config";
148
+
149
+ export default defineConfig({
150
+ plugins: vitePluginReactServer(config) as Plugin[],
76
151
  });
77
152
  ```
78
- The server plugin will look the same when you serve it, but under the hood works quite differently. This plugin requires you to write `NODE_OPTIONS="--conditions=react-server" vite --ssr --config vite.server.config.ts`. Aside from building the server dist files, it will populate the client's folder with index files for all your routes.
79
153
 
154
+ #### Running in Development
155
+
156
+ ```sh
157
+ NODE_OPTIONS="--conditions=react-server" vite --config vite.server.config.ts
158
+ ```
159
+
160
+ #### Build Steps
161
+
162
+ ```sh
163
+ NODE_OPTIONS="--conditions=react-server" vite build --config vite.server.config.ts
164
+ ```
165
+ Generates server and static folder. The plugin ensures proper SSR handling without requiring `--ssr` manually.
166
+ Note: ssr can still be disabled via config `{ssr:false}`, which will enable vite's browser virtualization
167
+
168
+ ---
169
+
170
+ ## Static Site Generation
171
+
172
+ Single-out the static generation step by only inluding the static plugin. Expects client and server folders to be there.
80
173
  ```ts
81
- import React from "react"
174
+ import { defineConfig, Plugin } from "vite";
175
+ import { reactStaticPlugin } from "vite-plugin-react-server/static";
176
+ import { config } from "./vite.react.config";
82
177
 
83
- export const config = {
84
- // set the root dir
85
- moduleBase: "src",
86
- // map the id to any page/prop file
87
- Page: (id)=>'page.tsx'),
88
- props: (id)=>'props.ts',
89
- // production html (not used during development)
90
- Html: ({ children, url }) => (
91
- <html>
92
- <title>{url}</title>
93
- <body>{children}</body>
94
- </html>
95
- ),
96
- build: {
97
- // routes to build index.html and index.rsc files for
98
- pages: ["/", "/about"],
99
- },
100
- };
178
+ export default defineConfig({
179
+ plugins: [reactStaticPlugin(config)],
180
+ });
101
181
  ```
102
182
 
103
- ### Scripts Setup
183
+ Example output structure:
104
184
 
105
- ```json
106
- {
107
- "scripts": {
108
- "start": "vite",
109
- "dev": "NODE_OPTIONS=--conditions=react-server vite --config vite.server.config.ts",
110
- "build": "npm run build:client && npm run build:server",
111
- "build:client": "vite build",
112
- "build:server": "NODE_OPTIONS=--conditions=react-server vite build --ssr --config vite.server.config.ts",
113
- "test:server": "NODE_OPTIONS=--conditions=react-server vitest",
114
- "test:client": "vitest",
115
- }
116
- }
185
+ ```sh
186
+ dist/static/index.html
187
+ dist/static/index.rsc
188
+ dist/static/about/index.html
189
+ dist/static/about/index.rsc
117
190
  ```
118
191
 
119
- ## Component Types
192
+ The entire `dist/client` directory is copied into `dist/static`, as well as any assets used server-side. Allowing easy deployment by moving the static folder to a hosting service.
120
193
 
121
- ### Server Components (Default)
122
- ```tsx
123
- // src/page/pokemon/page.tsx
124
- export function Page({ pokemon }) {
125
- return <div>Its a {pokemon.name}!</div>
194
+ ---
195
+
196
+ ## Configuration
197
+
198
+ ### moduleBase
199
+
200
+ ```ts
201
+ const config = {
202
+ moduleBase: "src",
126
203
  }
127
204
  ```
205
+ Defines the root directory for project modules. This can be customized.
128
206
 
129
- ### Page Props
130
- ```tsx
131
- // src/page/pokemon/props.ts
132
- export const props = async () => {
133
- const res = await fetch("https://pokeapi.co/api/v2/pokemon-form/399/")
134
- return res.json()
135
- }
207
+ ### moduleBasePath
208
+
209
+ ```ts
210
+ moduleBasePath: "",
136
211
  ```
212
+ Passed as the second argument to `renderToPipeableStream` for server-side rendering.
137
213
 
138
- ### Client Components
139
- Use the "use client" directive for client-side features:
140
- ```tsx
141
- "use client"
142
- import { useState } from 'react'
214
+ ### moduleBaseURL
143
215
 
144
- export function Counter() {
145
- const [count, setCount] = useState(0)
146
- return <button onClick={() => setCount(c => c + 1)}>{count}</button>
147
- }
216
+ ```ts
217
+ moduleBaseURL: "https://github.com/my-gh-pages",
148
218
  ```
219
+ Defines asset URL resolution for CSS collectors and bootstrapModule.
149
220
 
150
- ### Server Actions
151
- Use the "use server" directive for server-side API endpoints:
152
- ```tsx
153
- "use server"
154
- export async function submitForm(data: FormData) {
155
- // Server-side logic
156
- }
221
+ ### Page and props Mapping
222
+
223
+ ```ts
224
+ Page: (id) => join(id.replace('index.rsc',''), 'page.tsx')
225
+ ```
226
+ Defines how pages are mapped to file paths.
227
+ ```ts
228
+ props: (id) => join(id.replace('index.rsc',''), 'props.ts')
229
+ ```
230
+ Defines how to load the initial props of the page file.
231
+
232
+ If you do not want prop files, just don't define it.
233
+ ```ts
234
+ pageExportName: 'Page',
157
235
  ```
236
+ Changes the default name "Page"
237
+ ```ts
238
+ propsExportName: 'props',
239
+ ```
240
+ Changes the default name "props"
158
241
 
159
- ## Notes
242
+ ---
160
243
 
161
- - Requires `NODE_OPTIONS="--conditions=react-server"` for the Vite process
162
- - CSS files are automatically collected and link tags emitted
163
- - Components are streamed only when visited
164
- - Supports both sync and async props, and all kinds of combinations I haven't tried or tested yet!
244
+ ## Example Setup
165
245
 
166
- ## Architecture and Implementation Details
246
+ ### package.json Scripts
247
+
248
+ ```json
249
+ "scripts": {
250
+ "build": "build:client && build:server",
251
+ "dev": "NODE_OPTIONS='--conditions react-server' vite --config vite.server.config.ts",
252
+ "dev:client": "vite",
253
+ "build:server": "NODE_OPTIONS='--conditions react-server' vite build --config vite.server.config.ts",
254
+ "build:client": "vite build"
255
+ }
256
+ ```
257
+
258
+ ### Sample Page Component
259
+
260
+ ```tsx
261
+ // src/my-page.tsx
262
+ export const Page = ({ name }) => {
263
+ return <div>Hello {name}</div>;
264
+ };
265
+ ```
167
266
 
168
- ### Dual Implementation Strategy
267
+ ### Sample Props File
169
268
 
170
- The plugin provides two complete implementations of RSC handling:
269
+ ```ts
270
+ // src/my-props.ts
271
+ export const props = {
272
+ name: "John Doe",
273
+ };
274
+ ```
171
275
 
172
- 1. **Direct In-Thread Implementation** (when running under react-server condition)
173
- - Simpler architecture
174
- - Better error reporting (same errors in console and browser)
175
- - Easier to debug
176
- - More direct stream handling
276
+ ### Vite Configuration Files
177
277
 
178
- 2. **Worker-Based Implementation** (when not under react-server condition)
179
- - Allows running without react-server condition
180
- - Uses message passing for communication
181
- - Requires explicit support for features over message channels
182
- - More complex but more flexible
278
+ #### Client Configuration (`vite.config.ts`)
183
279
 
184
- This dual implementation approach gives users choice in how they want to structure their build process, recognizing that different projects may have different needs or constraints.
280
+ ```ts
281
+ import { vitePluginReactClient } from "vite-plugin-react-server/client";
282
+ import { defineConfig } from "vite";
185
283
 
186
- ### Node Conditions and Worker Threads
284
+ export default defineConfig({
285
+ plugins: vitePluginReactClient(),
286
+ });
287
+ ```
187
288
 
188
- The use of worker threads isn't primarily about parallelization - it's about handling Node conditions:
289
+ #### Server Configuration (`vite.server.config.ts`)
189
290
 
190
- - The main Node process conditions (`NODE_OPTIONS`) are set at startup and can't be changed
191
- - When running under `--conditions=react-server`, we need a way to handle client-side bundling
192
- - Worker threads allow us to run code under different conditions than the main thread
193
- - This makes worker threads essential for supporting both server and client code in the same build process
291
+ ```ts
292
+ import { vitePluginReactServer } from "vite-plugin-react-server";
293
+ import { defineConfig } from "vite";
194
294
 
195
- ### Future Possibilities: Application-Level Workers
295
+ export default defineConfig({
296
+ plugins: vitePluginReactServer(),
297
+ });
298
+ ```
196
299
 
197
- While currently focused on build-time RSC handling, the worker pattern could be extended to the end application:
300
+ ---
198
301
 
199
- - Users could create their own RSC workers
200
- - Run in client dev mode to naturally support their worker setup
201
- - Get worker isolation benefits in their application
202
- - Have more control over RSC boundaries
302
+ ```sh
303
+ NODE_OPTIONS='--conditions react-server' npx vite --config vite.server.config.ts
304
+ ```
203
305
 
204
- This would require:
205
- - APIs for user-defined workers
206
- - Documentation for worker patterns
207
- - Examples of worker-based architectures
208
- - Support for different worker strategies
306
+ In development mode, the server plugin pipes the React stream directly to the response.
209
307
 
210
- While this isn't currently implemented, the architecture is designed to potentially support this kind of extension in the future.
308
+ ```sh
309
+ NODE_OPTIONS='--conditions react-server' npx vite build --config vite.server.config.ts
310
+ ```
311
+ This builds the `dist/server` directory. It sets ssr to true by default, so you can't forget to. Additionally, when the build is done it generates the `dist/static` directory using the /static plugin.
211
312
 
212
- ## License
313
+ ## Contributions
213
314
 
214
- MIT
315
+ If you want to help develop or maintain the plugin feel free to open a PR or issue on GitHub.
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vite-plugin-react-server",
3
- "version": "0.3.19",
3
+ "version": "1.0.1",
4
4
  "description": "Vite plugin for React Server Components (RSC)",
5
5
  "type": "module",
6
6
  "main": "./dist/plugin/index.js",
@@ -19,13 +19,15 @@
19
19
  ".": "./dist/plugin/index.js",
20
20
  "./client": "./dist/client.js",
21
21
  "./server": "./dist/server.js",
22
+ "./static": "./dist/static.js",
22
23
  "./html-worker": "./dist/plugin/worker/html-worker.js",
23
24
  "./rsc-worker": "./dist/plugin/worker/rsc-worker.js",
24
25
  "./loader": "./dist/plugin/worker/loader.js",
25
26
  "./package.json": "./package.json",
26
27
  "./patch": "./scripts/patch.mjs",
27
28
  "./check-react-version": "./scripts/check-react-version.mjs",
28
- "./css-loader": "./dist/plugin/loader/css-loader.js"
29
+ "./css-loader": "./dist/plugin/loader/css-loader.js",
30
+ "./components": "./dist/plugin/components.js"
29
31
  },
30
32
  "typesVersions": {
31
33
  "*": {
@@ -38,11 +40,17 @@
38
40
  "server": [
39
41
  "./dist/plugin/react-server/plugin.d.ts"
40
42
  ],
43
+ "static": [
44
+ "./dist/plugin/static/plugin.d.ts"
45
+ ],
41
46
  "worker": [
42
47
  "./dist/plugin/worker/worker.d.ts"
43
48
  ],
44
49
  "loader": [
45
50
  "./dist/plugin/worker/loader.d.ts"
51
+ ],
52
+ "components": [
53
+ "./dist/plugin/components.d.ts"
46
54
  ]
47
55
  }
48
56
  },
@@ -120,13 +128,12 @@
120
128
  "typescript": "^5.7.3",
121
129
  "vite": "^6.0.11",
122
130
  "vitest": "^3.0.4",
123
- "webpack-sources": "^3.2.3"
131
+ "webpack-sources": "^3.2.3",
132
+ "tsx": "^4.19.2"
124
133
  },
125
134
  "bin": {
126
135
  "check-react-version": "./scripts/check-react-version.mjs",
127
136
  "patch": "./bin/patch.mjs"
128
137
  },
129
- "dependencies": {
130
- "tsx": "^4.19.2"
131
- }
138
+ "dependencies": {}
132
139
  }
@@ -1 +1 @@
1
- {"version":3,"file":"collect-manifest-client-files.d.ts","sourceRoot":"","sources":["../../plugin/collect-manifest-client-files.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,MAAM,CAAC;AAIlD,wBAAsB,qBAAqB,CAAC,EAC1C,WAAW,EACX,QAAQ,EACR,KAAK,EACL,SAAS,GACV,EAAE;IACD,WAAW,EAAE,WAAW,CAAC;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAClD,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,gCAoBA;AAED,wBAAgB,0BAA0B,CAAC,EACzC,QAAQ,EACR,IAAI,EACJ,QAAQ,EACR,mBAAmB,EACnB,UAAU,EACV,KAAK,EACL,cAAc,EACd,UAA0D,EAC1D,QAAmD,GACpD,EAAE;IACD,QAAQ,EAAE,QAAQ,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAClD,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC;IACrC,QAAQ,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC;CACpC;;;EA8FA"}
1
+ {"version":3,"file":"collect-manifest-client-files.d.ts","sourceRoot":"","sources":["../../plugin/collect-manifest-client-files.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,MAAM,CAAC;AAIlD,wBAAsB,qBAAqB,CAAC,EAC1C,WAAW,EACX,QAAQ,EACR,KAAK,EACL,SAAS,GACV,EAAE;IACD,WAAW,EAAE,WAAW,CAAC;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAClD,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,gCAoBA;AAED,wBAAgB,0BAA0B,CAAC,EACzC,QAAQ,EACR,IAAI,EACJ,QAAQ,EACR,mBAAmB,EACnB,UAAU,EACV,KAAK,EACL,cAAc,EACd,UAA0D,EAC1D,QAAmD,GACpD,EAAE;IACD,QAAQ,EAAE,QAAQ,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAClD,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC;IACrC,QAAQ,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC;CACpC;;;EA6GA"}
@@ -24,7 +24,6 @@ async function collectModuleGraphCss({
24
24
  seen.add(mod.id);
25
25
  if (mod?.id?.endsWith(".css")) {
26
26
  cssFiles.set(mod?.url, mod?.id);
27
- onCss?.(mod?.url, parentUrl ?? pagePath);
28
27
  }
29
28
  mod?.importedModules?.forEach((imp) => walkModule(imp));
30
29
  };
@@ -61,11 +60,19 @@ function collectManifestClientFiles({
61
60
  seen.add(id);
62
61
  const entry = manifest[id] ?? manifestValues.find((e) => id === e.file);
63
62
  if (!entry) {
64
- console.log(
65
- `No manifest entry found for ${id}, possible keys: ${Object.keys(
66
- manifest
67
- ).join(", ")}`
68
- );
63
+ const hasKey = Object.keys(manifest).find((key) => id === key);
64
+ if (hasKey) {
65
+ console.log(
66
+ `Manifest entry found for ${id}, but it is ${typeof entry}`
67
+ );
68
+ return;
69
+ } else {
70
+ console.log(
71
+ `No manifest entry found for ${id}, possible keys: ${Object.keys(
72
+ manifest
73
+ ).join(", ")}`
74
+ );
75
+ }
69
76
  return;
70
77
  }
71
78
  if (typeof testClient === "function" && typeof onClientModule === "function" && testClient(entry.file) || typeof testJson === "function" && testJson(entry.file)) {
@@ -103,11 +110,18 @@ function collectManifestClientFiles({
103
110
  if (entry) {
104
111
  walkManifestEntry(value, pagePath);
105
112
  } else {
106
- console.warn(
107
- `No manifest entry found for ${value} (tried all possible keys: ${possibleKeys.join(
108
- ", "
109
- )})`
110
- );
113
+ const hasKey = Object.keys(manifest).find((key) => value === key);
114
+ if (hasKey) {
115
+ console.warn(
116
+ `Manifest entry found for ${value}, but it is ${typeof manifest[hasKey]}`
117
+ );
118
+ } else {
119
+ console.warn(
120
+ `No manifest entry found for ${value} (tried all possible keys: ${possibleKeys.join(
121
+ ", "
122
+ )} for manifest keys: ${Object.keys(manifest).join(", ")})`
123
+ );
124
+ }
111
125
  }
112
126
  }
113
127
  return { cssFiles, clientFiles };
@@ -1 +1 @@
1
- {"version":3,"file":"collect-manifest-client-files.js","sources":["../../plugin/collect-manifest-client-files.ts"],"sourcesContent":["import type { Manifest, ModuleGraph } from \"vite\";\nimport { createInputNormalizer } from \"./helpers/inputNormalizer.js\";\nimport { DEFAULT_CONFIG } from \"./config/defaults.js\";\n\nexport async function collectModuleGraphCss({\n moduleGraph,\n pagePath,\n onCss,\n parentUrl,\n}: {\n moduleGraph: ModuleGraph;\n pagePath: string;\n onCss?: (path: string, parentUrl: string) => void;\n parentUrl?: string;\n}) {\n if (!pagePath) return new Map<string, string>();\n\n const cssFiles = new Map<string, string>();\n const pageModule = await moduleGraph.getModuleByUrl(pagePath, true);\n if (!pageModule) {\n return new Map<string, string>();\n }\n const seen = new Set<string>();\n const walkModule = (mod: any) => {\n if (!mod?.id || seen.has(mod.id)) return;\n seen.add(mod.id);\n if (mod?.id?.endsWith(\".css\")) {\n cssFiles.set(mod?.url, mod?.id);\n onCss?.(mod?.url, parentUrl ?? pagePath);\n }\n mod?.importedModules?.forEach((imp: any) => walkModule(imp));\n };\n walkModule(pageModule);\n return cssFiles;\n}\n\nexport function collectManifestClientFiles({\n manifest,\n root,\n pagePath,\n preserveModulesRoot,\n moduleBase,\n onCss,\n onClientModule,\n testClient = DEFAULT_CONFIG.AUTO_DISCOVER.clientComponents,\n testJson = DEFAULT_CONFIG.AUTO_DISCOVER.jsonPattern,\n}: {\n manifest: Manifest;\n root: string;\n pagePath: string;\n preserveModulesRoot?: boolean;\n moduleBase?: string;\n onCss?: (path: string, parentUrl: string) => void;\n onClientModule?: (path: string, parentUrl: string) => void;\n parentUrl?: string;\n testClient?: (id: string) => boolean;\n testJson?: (id: string) => boolean;\n}) {\n const normalizer = createInputNormalizer({\n root,\n removeExtension: true,\n preserveModulesRoot: preserveModulesRoot ? moduleBase : undefined,\n });\n const [_, value] = normalizer(pagePath);\n\n const cssFiles = new Map<string, string>();\n const clientFiles = new Map<string, string>();\n const seen = new Set<string>();\n const manifestValues = Object.values(manifest);\n\n // Try different variations of the path\n const possibleKeys = [\n value, // Relative path\n ];\n\n const walkManifestEntry = (id: string, parentUrl: string) => {\n if (seen.has(id)) return;\n seen.add(id);\n\n // Get the manifest entry\n const entry = manifest[id] ?? manifestValues.find((e) => id === e.file);\n if (!entry) {\n console.log(\n `No manifest entry found for ${id}, possible keys: ${Object.keys(\n manifest\n ).join(\", \")}`\n );\n return;\n }\n if (\n (typeof testClient === \"function\" &&\n typeof onClientModule === \"function\" &&\n testClient(entry.file)) ||\n (typeof testJson === \"function\" && testJson(entry.file))\n ) {\n onClientModule?.(entry.file ?? \"\", parentUrl);\n clientFiles.set(id, entry.name ?? \"\");\n }\n\n // Add direct CSS from the css array\n if (entry.css) {\n entry.css.forEach((css: string) => {\n cssFiles.set(css, css);\n onCss?.(css, id);\n onClientModule?.(css, id);\n });\n }\n\n // Walk imports recursively\n if (entry.imports) {\n entry.imports.forEach((imp: string) =>\n walkManifestEntry(imp, entry.file)\n );\n }\n\n // Also check dynamicImports\n if (entry.dynamicImports) {\n entry.dynamicImports.forEach((imp: string) =>\n walkManifestEntry(imp, entry.file)\n );\n }\n };\n\n // Try all possible keys\n for (const possibleKey of possibleKeys) {\n if (manifest[possibleKey]) {\n walkManifestEntry(possibleKey, pagePath);\n break;\n }\n }\n\n // If no entry found by key, try matching by file\n if (cssFiles.size === 0) {\n const entry = manifestValues.find(\n (e) =>\n possibleKeys.includes(e.file) ||\n (e.src && possibleKeys.includes(e.src)) ||\n (e.name && possibleKeys.includes(e.name))\n );\n if (entry) {\n walkManifestEntry(value, pagePath);\n } else {\n console.warn(\n `No manifest entry found for ${value} (tried all possible keys: ${possibleKeys.join(\n \", \"\n )})`\n );\n }\n }\n\n return { cssFiles, clientFiles };\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"collect-manifest-client-files.js","sources":["../../plugin/collect-manifest-client-files.ts"],"sourcesContent":["import type { Manifest, ModuleGraph } from \"vite\";\nimport { createInputNormalizer } from \"./helpers/inputNormalizer.js\";\nimport { DEFAULT_CONFIG } from \"./config/defaults.js\";\n\nexport async function collectModuleGraphCss({\n moduleGraph,\n pagePath,\n onCss,\n parentUrl,\n}: {\n moduleGraph: ModuleGraph;\n pagePath: string;\n onCss?: (path: string, parentUrl: string) => void;\n parentUrl?: string;\n}) {\n if (!pagePath) return new Map<string, string>();\n\n const cssFiles = new Map<string, string>();\n const pageModule = await moduleGraph.getModuleByUrl(pagePath, true);\n if (!pageModule) {\n return new Map<string, string>();\n }\n const seen = new Set<string>();\n const walkModule = (mod: any) => {\n if (!mod?.id || seen.has(mod.id)) return;\n seen.add(mod.id);\n if (mod?.id?.endsWith(\".css\")) {\n cssFiles.set(mod?.url, mod?.id);\n onCss?.(mod?.url, parentUrl ?? pagePath);\n }\n mod?.importedModules?.forEach((imp: any) => walkModule(imp));\n };\n walkModule(pageModule);\n return cssFiles;\n}\n\nexport function collectManifestClientFiles({\n manifest,\n root,\n pagePath,\n preserveModulesRoot,\n moduleBase,\n onCss,\n onClientModule,\n testClient = DEFAULT_CONFIG.AUTO_DISCOVER.clientComponents,\n testJson = DEFAULT_CONFIG.AUTO_DISCOVER.jsonPattern,\n}: {\n manifest: Manifest;\n root: string;\n pagePath: string;\n preserveModulesRoot?: boolean;\n moduleBase?: string;\n onCss?: (path: string, parentUrl: string) => void;\n onClientModule?: (path: string, parentUrl: string) => void;\n parentUrl?: string;\n testClient?: (id: string) => boolean;\n testJson?: (id: string) => boolean;\n}) {\n const normalizer = createInputNormalizer({\n root,\n removeExtension: true,\n preserveModulesRoot: preserveModulesRoot ? moduleBase : undefined,\n });\n const [_, value] = normalizer(pagePath);\n\n const cssFiles = new Map<string, string>();\n const clientFiles = new Map<string, string>();\n const seen = new Set<string>();\n const manifestValues = Object.values(manifest);\n\n // Try different variations of the path\n const possibleKeys = [\n value, // Relative path\n ];\n\n const walkManifestEntry = (id: string, parentUrl: string) => {\n if (seen.has(id)) return;\n seen.add(id);\n\n // Get the manifest entry\n const entry = manifest[id] ?? manifestValues.find((e) => id === e.file);\n if (!entry) {\n const hasKey = Object.keys(manifest).find((key) => id === key);\n if (hasKey) {\n console.log(\n `Manifest entry found for ${id}, but it is ${typeof entry}`\n );\n return;\n } else {\n console.log(\n `No manifest entry found for ${id}, possible keys: ${Object.keys(\n manifest\n ).join(\", \")}`\n );\n }\n return;\n }\n if (\n (typeof testClient === \"function\" &&\n typeof onClientModule === \"function\" &&\n testClient(entry.file)) ||\n (typeof testJson === \"function\" && testJson(entry.file))\n ) {\n onClientModule?.(entry.file ?? \"\", parentUrl);\n clientFiles.set(id, entry.name ?? \"\");\n }\n\n // Add direct CSS from the css array\n if (entry.css) {\n entry.css.forEach((css: string) => {\n cssFiles.set(css, css);\n onCss?.(css, id);\n onClientModule?.(css, id);\n });\n }\n\n // Walk imports recursively\n if (entry.imports) {\n entry.imports.forEach((imp: string) =>\n walkManifestEntry(imp, entry.file)\n );\n }\n\n // Also check dynamicImports\n if (entry.dynamicImports) {\n entry.dynamicImports.forEach((imp: string) =>\n walkManifestEntry(imp, entry.file)\n );\n }\n };\n\n // Try all possible keys\n for (const possibleKey of possibleKeys) {\n if (manifest[possibleKey]) {\n walkManifestEntry(possibleKey, pagePath);\n break;\n }\n }\n\n // If no entry found by key, try matching by file\n if (cssFiles.size === 0) {\n const entry = manifestValues.find(\n (e) =>\n possibleKeys.includes(e.file) ||\n (e.src && possibleKeys.includes(e.src)) ||\n (e.name && possibleKeys.includes(e.name))\n );\n if (entry) {\n walkManifestEntry(value, pagePath);\n } else {\n const hasKey = Object.keys(manifest).find((key) => value === key);\n if (hasKey) {\n console.warn(\n `Manifest entry found for ${value}, but it is ${typeof manifest[hasKey]}`\n );\n } else {\n console.warn(\n `No manifest entry found for ${value} (tried all possible keys: ${possibleKeys.join(\n \", \"\n )} for manifest keys: ${Object.keys(manifest).join(\", \")})`\n );\n }\n }\n }\n\n return { cssFiles, clientFiles };\n}\n"],"names":[],"mappings":"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"}
@@ -1,14 +1,4 @@
1
- import React from "react";
2
- /**
3
- * A component that emits <link> tags for CSS files during streaming.
4
- * The high precedence ensures they bubble up to the document head.
5
- */
6
- export declare function CssCollector({ children, cssFiles, moduleBaseUrl, route }: {
7
- children?: React.ReactNode;
8
- cssFiles: string[];
9
- moduleBaseUrl?: string;
10
- route?: string;
11
- }): React.FunctionComponentElement<{
12
- children?: React.ReactNode | undefined;
13
- }>;
1
+ export { Html } from "./html.js";
2
+ export { CssCollector } from "./css-collector.js";
3
+ export { InlineCssCollector } from "./css-collector-inline.js";
14
4
  //# sourceMappingURL=components.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"components.d.ts","sourceRoot":"","sources":["../../plugin/components.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B;;;GAGG;AACH,wBAAgB,YAAY,CAAC,EAC3B,QAAQ,EACR,QAAQ,EACR,aAAa,EACb,KAAW,EACZ,EAAE;IACD,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;;GA2CA"}
1
+ {"version":3,"file":"components.d.ts","sourceRoot":"","sources":["../../plugin/components.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC"}