vite-plugin-react-server 0.3.17 → 0.3.19
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.
- package/README.md +119 -118
- package/bin/patch.mjs +8 -2
- package/dist/package.json +3 -3
- package/dist/plugin/checkFilesExist.d.ts.map +1 -1
- package/dist/plugin/checkFilesExist.js +6 -2
- package/dist/plugin/checkFilesExist.js.map +1 -1
- package/dist/plugin/collect-manifest-client-files.d.ts +23 -0
- package/dist/plugin/collect-manifest-client-files.d.ts.map +1 -0
- package/dist/plugin/collect-manifest-client-files.js +117 -0
- package/dist/plugin/collect-manifest-client-files.js.map +1 -0
- package/dist/plugin/components.d.ts +9 -9
- package/dist/plugin/components.d.ts.map +1 -1
- package/dist/plugin/components.js +50 -9
- package/dist/plugin/components.js.map +1 -0
- package/dist/plugin/config/defaults.d.ts +7 -6
- package/dist/plugin/config/defaults.d.ts.map +1 -1
- package/dist/plugin/config/defaults.js +8 -5
- package/dist/plugin/config/defaults.js.map +1 -1
- package/dist/plugin/config/getPaths.d.ts +0 -1
- package/dist/plugin/config/getPaths.d.ts.map +1 -1
- package/dist/plugin/config/getPaths.js +2 -7
- package/dist/plugin/config/getPaths.js.map +1 -1
- package/dist/plugin/config/mimeTypes.d.ts +2 -0
- package/dist/plugin/config/mimeTypes.d.ts.map +1 -0
- package/dist/plugin/config/mimeTypes.js +24 -0
- package/dist/plugin/config/mimeTypes.js.map +1 -0
- package/dist/plugin/config/resolveOptions.d.ts +1 -1
- package/dist/plugin/config/resolveOptions.d.ts.map +1 -1
- package/dist/plugin/config/resolveOptions.js +41 -28
- package/dist/plugin/config/resolveOptions.js.map +1 -1
- package/dist/plugin/config/resolvePages.d.ts +1 -0
- package/dist/plugin/config/resolvePages.d.ts.map +1 -1
- package/dist/plugin/config/resolvePages.js +9 -5
- package/dist/plugin/config/resolvePages.js.map +1 -1
- package/dist/plugin/config/resolveUserConfig.d.ts +2 -1
- package/dist/plugin/config/resolveUserConfig.d.ts.map +1 -1
- package/dist/plugin/config/resolveUserConfig.js +12 -7
- package/dist/plugin/config/resolveUserConfig.js.map +1 -1
- package/dist/plugin/copy-dir.js +23 -18
- package/dist/plugin/copy-dir.js.map +1 -0
- package/dist/plugin/helpers/createHandler.d.ts +22 -0
- package/dist/plugin/helpers/createHandler.d.ts.map +1 -0
- package/dist/plugin/{react-server → helpers}/createHandler.js +36 -48
- package/dist/plugin/helpers/createHandler.js.map +1 -0
- package/dist/plugin/{react-server → helpers}/createRscStream.d.ts +2 -1
- package/dist/plugin/helpers/createRscStream.d.ts.map +1 -0
- package/dist/plugin/helpers/createRscStream.js +71 -0
- package/dist/plugin/helpers/createRscStream.js.map +1 -0
- package/dist/plugin/helpers/getBundleManifest.d.ts.map +1 -1
- package/dist/plugin/helpers/getBundleManifest.js +12 -4
- package/dist/plugin/helpers/getBundleManifest.js.map +1 -1
- package/dist/plugin/loader/createBuildLoader.d.ts +1 -1
- package/dist/plugin/loader/createBuildLoader.d.ts.map +1 -1
- package/dist/plugin/loader/createBuildLoader.js +8 -5
- package/dist/plugin/loader/createBuildLoader.js.map +1 -1
- package/dist/plugin/loader/css-loader.d.ts.map +1 -1
- package/dist/plugin/loader/css-loader.js.map +1 -1
- package/dist/plugin/loader/react-loader.js +2 -2
- package/dist/plugin/loader/react-loader.js.map +1 -1
- package/dist/plugin/preserver/plugin.d.ts.map +1 -1
- package/dist/plugin/preserver/plugin.js +49 -14
- package/dist/plugin/preserver/plugin.js.map +1 -1
- package/dist/plugin/react-client/plugin.d.ts.map +1 -1
- package/dist/plugin/react-client/plugin.js +18 -60
- package/dist/plugin/react-client/plugin.js.map +1 -1
- package/dist/plugin/react-server/index.d.ts.map +1 -1
- package/dist/plugin/react-server/index.js +2 -0
- package/dist/plugin/react-server/index.js.map +1 -1
- package/dist/plugin/react-server/plugin.d.ts +2 -1
- package/dist/plugin/react-server/plugin.d.ts.map +1 -1
- package/dist/plugin/react-server/plugin.js +53 -219
- package/dist/plugin/react-server/plugin.js.map +1 -1
- package/dist/plugin/react-static/index.d.ts +2 -0
- package/dist/plugin/react-static/index.d.ts.map +1 -0
- package/dist/plugin/react-static/index.js +1 -0
- package/dist/plugin/react-static/plugin.d.ts +7 -0
- package/dist/plugin/react-static/plugin.d.ts.map +1 -0
- package/dist/plugin/react-static/plugin.js +199 -0
- package/dist/plugin/react-static/plugin.js.map +1 -0
- package/dist/plugin/resolvePage.d.ts.map +1 -1
- package/dist/plugin/resolvePage.js +9 -0
- package/dist/plugin/resolvePage.js.map +1 -1
- package/dist/plugin/root.d.ts +2 -0
- package/dist/plugin/root.d.ts.map +1 -0
- package/dist/plugin/root.js +12 -0
- package/dist/plugin/root.js.map +1 -0
- package/dist/plugin/transformer/plugin.d.ts.map +1 -1
- package/dist/plugin/transformer/plugin.js +32 -23
- package/dist/plugin/transformer/plugin.js.map +1 -1
- package/dist/plugin/transformer/types.d.ts +1 -18
- package/dist/plugin/transformer/types.d.ts.map +1 -1
- package/dist/plugin/types.d.ts +24 -6
- package/dist/plugin/types.d.ts.map +1 -1
- package/dist/plugin/worker/createWorker.js +0 -1
- package/dist/plugin/worker/createWorker.js.map +1 -1
- package/dist/plugin/worker/html/html-worker.development.d.ts +30 -0
- package/dist/plugin/worker/html/html-worker.development.d.ts.map +1 -1
- package/dist/plugin/worker/html/html-worker.development.js +30 -2
- package/dist/plugin/worker/html/html-worker.development.js.map +1 -1
- package/dist/plugin/worker/html/html-worker.production.js +3 -5
- package/dist/plugin/worker/html/html-worker.production.js.map +1 -1
- package/dist/plugin/worker/html/messageHandler.d.ts.map +1 -1
- package/dist/plugin/worker/html/messageHandler.js +8 -2
- package/dist/plugin/worker/html/messageHandler.js.map +1 -1
- package/dist/plugin/worker/html/plugin.d.ts.map +1 -1
- package/dist/plugin/worker/html/plugin.js +2 -3
- package/dist/plugin/worker/html/renderPages.d.ts +8 -4
- package/dist/plugin/worker/html/renderPages.d.ts.map +1 -1
- package/dist/plugin/worker/html/renderPages.js +118 -83
- package/dist/plugin/worker/html/renderPages.js.map +1 -1
- package/dist/plugin/worker/rsc/messageHandler.d.ts.map +1 -1
- package/dist/plugin/worker/rsc/messageHandler.js +91 -87
- package/dist/plugin/worker/rsc/messageHandler.js.map +1 -1
- package/dist/plugin/worker/rsc/plugin.d.ts.map +1 -1
- package/dist/plugin/worker/rsc/plugin.js +1 -2
- package/dist/plugin/worker/rsc/rsc-worker.development.js +13 -18
- package/dist/plugin/worker/rsc/rsc-worker.development.js.map +1 -1
- package/dist/plugin/worker/rsc/rsc-worker.production.js +4 -1
- package/dist/plugin/worker/rsc/rsc-worker.production.js.map +1 -1
- package/dist/plugin/worker/rsc/state.d.ts.map +1 -1
- package/dist/plugin/worker/rsc/state.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +3 -3
- package/plugin/checkFilesExist.ts +7 -3
- package/plugin/collect-manifest-client-files.ts +152 -0
- package/plugin/components.tsx +55 -10
- package/plugin/config/defaults.tsx +69 -0
- package/plugin/config/getPaths.ts +1 -7
- package/plugin/config/mimeTypes.ts +17 -0
- package/plugin/config/resolveOptions.ts +48 -40
- package/plugin/config/resolvePages.ts +8 -4
- package/plugin/config/resolveUserConfig.ts +14 -11
- package/plugin/{react-server → helpers}/createHandler.ts +46 -63
- package/plugin/helpers/createRscStream.ts +81 -0
- package/plugin/helpers/getBundleManifest.ts +14 -5
- package/plugin/loader/createBuildLoader.ts +9 -6
- package/plugin/loader/css-loader.ts +0 -2
- package/plugin/loader/react-loader.ts +2 -2
- package/plugin/preserver/plugin.ts +64 -17
- package/plugin/react-client/plugin.ts +20 -74
- package/plugin/react-server/index.ts +2 -0
- package/plugin/react-server/plugin.ts +66 -298
- package/plugin/react-static/index.ts +1 -0
- package/plugin/react-static/plugin.ts +247 -0
- package/plugin/resolvePage.ts +9 -0
- package/plugin/root.ts +4 -0
- package/plugin/transformer/plugin.ts +40 -31
- package/plugin/transformer/types.ts +0 -19
- package/plugin/types.ts +25 -6
- package/plugin/worker/createWorker.ts +1 -1
- package/plugin/worker/html/README.md +63 -0
- package/plugin/worker/html/html-worker.development.tsx +89 -2
- package/plugin/worker/html/html-worker.production.tsx +8 -10
- package/plugin/worker/html/messageHandler.ts +8 -2
- package/plugin/worker/html/plugin.ts +2 -3
- package/plugin/worker/html/renderPages.ts +150 -114
- package/plugin/worker/rsc/README.md +58 -0
- package/plugin/worker/rsc/messageHandler.tsx +98 -119
- package/plugin/worker/rsc/plugin.ts +1 -2
- package/plugin/worker/rsc/rsc-worker.development.ts +12 -22
- package/plugin/worker/rsc/rsc-worker.production.ts +5 -1
- package/plugin/worker/rsc/state.ts +0 -3
- package/scripts/react+0.0.0-experimental-eda36a1c-20250228.patch +114 -12
- package/scripts/react-dom+0.0.0-experimental-eda36a1c-20250228.patch +10571 -121
- package/tsconfig.json +2 -2
- package/dist/plugin/collect-css-manifest.d.ts +0 -4
- package/dist/plugin/collect-css-manifest.d.ts.map +0 -1
- package/dist/plugin/collect-css-manifest.js +0 -66
- package/dist/plugin/collect-css-manifest.js.map +0 -1
- package/dist/plugin/config/createModuleIdGenerator.d.ts +0 -11
- package/dist/plugin/config/createModuleIdGenerator.d.ts.map +0 -1
- package/dist/plugin/config/createModuleIdGenerator.js +0 -44
- package/dist/plugin/config/createModuleIdGenerator.js.map +0 -1
- package/dist/plugin/loader/createCssLoader.d.ts +0 -30
- package/dist/plugin/loader/createCssLoader.d.ts.map +0 -1
- package/dist/plugin/loader/createCssLoader.js +0 -35
- package/dist/plugin/loader/createPageLoader.d.ts +0 -24
- package/dist/plugin/loader/createPageLoader.d.ts.map +0 -1
- package/dist/plugin/loader/createPageLoader.js +0 -50
- package/dist/plugin/loader/rsc/messageHandler.d.ts +0 -2
- package/dist/plugin/loader/rsc/messageHandler.d.ts.map +0 -1
- package/dist/plugin/loader/rsc/messageHandler.js +0 -1
- package/dist/plugin/loader/rsc/rsc-worker.development.d.ts +0 -2
- package/dist/plugin/loader/rsc/rsc-worker.development.d.ts.map +0 -1
- package/dist/plugin/loader/rsc/rsc-worker.development.js +0 -1
- package/dist/plugin/react-server/createHandler.d.ts +0 -17
- package/dist/plugin/react-server/createHandler.d.ts.map +0 -1
- package/dist/plugin/react-server/createHandler.js.map +0 -1
- package/dist/plugin/react-server/createRscStream.d.ts.map +0 -1
- package/dist/plugin/react-server/createRscStream.js +0 -66
- package/dist/plugin/react-server/createRscStream.js.map +0 -1
- package/dist/plugin/react-server/createSsrHandler.d.ts +0 -4
- package/dist/plugin/react-server/createSsrHandler.d.ts.map +0 -1
- package/dist/plugin/react-server/createSsrHandler.js +0 -95
- package/dist/plugin/utils/logger.d.ts +0 -9
- package/dist/plugin/utils/logger.d.ts.map +0 -1
- package/dist/plugin/utils/logger.js +0 -68
- package/dist/plugin/utils/logger.js.map +0 -1
- package/plugin/collect-css-manifest.ts +0 -83
- package/plugin/config/createModuleIdGenerator.ts +0 -52
- package/plugin/config/defaults.ts +0 -51
- package/plugin/loader/createCssLoader.ts +0 -73
- package/plugin/loader/createPageLoader.ts +0 -103
- package/plugin/loader/rsc/messageHandler.tsx +0 -1
- package/plugin/loader/rsc/rsc-worker.development.ts +0 -1
- package/plugin/react-server/createRscStream.ts +0 -82
- package/plugin/react-server/createSsrHandler.ts +0 -125
- package/plugin/utils/logger.ts +0 -52
package/README.md
CHANGED
|
@@ -1,107 +1,103 @@
|
|
|
1
|
-
# Vite React Server
|
|
1
|
+
# Vite React Server Plugin
|
|
2
2
|
|
|
3
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
4
|
|
|
5
|
-
## Features
|
|
6
5
|
|
|
7
|
-
|
|
8
|
-
- 🔄 Use vite to create your personal meta-framework
|
|
9
|
-
- ⚡ Full RSC streaming support
|
|
10
|
-
- 📦 Dual-worker architecture for optimal performance
|
|
11
|
-
- 🔧 Automatic client/server code splitting
|
|
12
|
-
- 🎯 Directive-based component targeting
|
|
6
|
+
## Example Projects
|
|
13
7
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
The [mmcelebration.com project](https://github.com/nicobrinkkemper/mmc) uses this plugin. Build time for ~200 html pages is just a few seconds.
|
|
8
|
+
- [The official demo](https://github.com/nicobrinkkemper/vite-plugin-react-server-demo-official)
|
|
9
|
+
- [The mmcelebration.com project](https://github.com/nicobrinkkemper/mmc)
|
|
17
10
|
|
|
18
11
|
## Installation
|
|
19
12
|
|
|
20
|
-
```
|
|
21
|
-
npm install vite-plugin-react-
|
|
13
|
+
```ts
|
|
14
|
+
npm install -D vite-plugin-react-stream
|
|
22
15
|
```
|
|
23
16
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
This plugin requires React's experimental features. You'll need to:
|
|
17
|
+
## Open source and work in progress
|
|
27
18
|
|
|
28
|
-
|
|
29
|
-
```
|
|
30
|
-
|
|
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
|
+
```json
|
|
21
|
+
"patch": "check-react-version && patch",
|
|
31
22
|
```
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
npx vite-plugin-react-server/patch
|
|
23
|
+
Now run `npm run patch` to create the patch. It will tell you to add this as well:
|
|
24
|
+
```json
|
|
25
|
+
"postinstall": "patch-package",
|
|
36
26
|
```
|
|
37
|
-
This will
|
|
38
|
-
|
|
39
|
-
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
27
|
+
This will apply the patch for us after running `npm install`
|
|
28
|
+
|
|
29
|
+
If errors start showing up related to the missing `react-server-dom-esm` package - it's likely the postinstall step didn't run.
|
|
30
|
+
|
|
31
|
+
## Included plugins
|
|
32
|
+
### vite-plugin-react-server/client
|
|
33
|
+
- Client build
|
|
34
|
+
- Server Worker thread (rsc-worker)
|
|
35
|
+
|
|
36
|
+
### vite-plugin-react-server
|
|
37
|
+
- Server build
|
|
38
|
+
- Client Worker thread (html-worker)
|
|
39
|
+
|
|
40
|
+
### vite-plugin-react-server/preserver
|
|
41
|
+
- Preserves "use client" and "use server" condition in source code
|
|
42
|
+
|
|
43
|
+
### vite-plugin-react-server/transformer
|
|
44
|
+
- Transforms client components for server environment or vice versa
|
|
45
|
+
|
|
46
|
+
### vite-plugin-react-server/worker/html
|
|
47
|
+
- Create your own html worker (client side worker)
|
|
48
|
+
- Make html worker part of the application
|
|
49
|
+
|
|
50
|
+
### vite-plugin-react-server/worker/rsc
|
|
51
|
+
- Create your own rsc worker (server side worker)
|
|
52
|
+
- Make rsc worker part of the application
|
|
53
|
+
|
|
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.
|
|
56
|
+
```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),
|
|
63
|
+
}
|
|
64
|
+
});
|
|
45
65
|
```
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
```
|
|
49
|
-
{
|
|
50
|
-
|
|
51
|
-
|
|
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)
|
|
67
|
+
|
|
68
|
+
```ts
|
|
69
|
+
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),
|
|
52
75
|
}
|
|
53
|
-
}
|
|
76
|
+
});
|
|
54
77
|
```
|
|
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.
|
|
55
79
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
## Basic Configuration
|
|
59
|
-
|
|
60
|
-
```typescript
|
|
61
|
-
// vite.react-server.config.ts
|
|
62
|
-
import { defineConfig } from 'vite'
|
|
63
|
-
import type { Options } from 'vite-plugin-react-server'
|
|
80
|
+
```ts
|
|
81
|
+
import React from "react"
|
|
64
82
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
if(url.includes('bidoof')) return `src/page/bidoof/${file}`
|
|
68
|
-
if(url === '/index.rsc') return `src/page/${file}`;
|
|
69
|
-
return `src/page/404/${file}`;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
export const streamPluginOptions: Options = {
|
|
83
|
+
export const config = {
|
|
84
|
+
// set the root dir
|
|
73
85
|
moduleBase: "src",
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
export default defineConfig({
|
|
90
|
-
plugins: [viteReactStreamPlugin(streamPluginOptions)]
|
|
91
|
-
})
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
### Server Build Config
|
|
95
|
-
|
|
96
|
-
```typescript
|
|
97
|
-
// vite.server.config.ts
|
|
98
|
-
import { defineConfig } from 'vite'
|
|
99
|
-
import { viteReactStreamPlugin } from 'vite-plugin-react-server/server'
|
|
100
|
-
import { streamPluginOptions } from './vite.react-server.config.js'
|
|
101
|
-
|
|
102
|
-
export default defineConfig({
|
|
103
|
-
plugins: [viteReactStreamPlugin(streamPluginOptions)]
|
|
104
|
-
})
|
|
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
|
+
};
|
|
105
101
|
```
|
|
106
102
|
|
|
107
103
|
### Scripts Setup
|
|
@@ -109,11 +105,13 @@ export default defineConfig({
|
|
|
109
105
|
```json
|
|
110
106
|
{
|
|
111
107
|
"scripts": {
|
|
112
|
-
"start": "
|
|
108
|
+
"start": "vite",
|
|
109
|
+
"dev": "NODE_OPTIONS=--conditions=react-server vite --config vite.server.config.ts",
|
|
113
110
|
"build": "npm run build:client && npm run build:server",
|
|
114
111
|
"build:client": "vite build",
|
|
115
112
|
"build:server": "NODE_OPTIONS=--conditions=react-server vite build --ssr --config vite.server.config.ts",
|
|
116
|
-
"test:server": "NODE_OPTIONS=--conditions=react-server vitest
|
|
113
|
+
"test:server": "NODE_OPTIONS=--conditions=react-server vitest",
|
|
114
|
+
"test:client": "vitest",
|
|
117
115
|
}
|
|
118
116
|
}
|
|
119
117
|
```
|
|
@@ -165,49 +163,52 @@ export async function submitForm(data: FormData) {
|
|
|
165
163
|
- Components are streamed only when visited
|
|
166
164
|
- Supports both sync and async props, and all kinds of combinations I haven't tried or tested yet!
|
|
167
165
|
|
|
168
|
-
##
|
|
166
|
+
## Architecture and Implementation Details
|
|
169
167
|
|
|
170
|
-
|
|
168
|
+
### Dual Implementation Strategy
|
|
171
169
|
|
|
172
|
-
|
|
170
|
+
The plugin provides two complete implementations of RSC handling:
|
|
173
171
|
|
|
174
|
-
|
|
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
|
|
175
177
|
|
|
176
|
-
|
|
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
|
|
177
183
|
|
|
178
|
-
|
|
179
|
-
2. **Pure Server** - Server-side RSC streaming
|
|
180
|
-
3. **Client-with-server-worker** - Thread WITHOUT React server conditions using dependencies that are ONLY available using the server condition
|
|
181
|
-
4. **Server-with-client-worker** - Thread WITH React server conditions using dependencies that are ONLY available WITHOUT the server condition
|
|
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.
|
|
182
185
|
|
|
183
|
-
|
|
186
|
+
### Node Conditions and Worker Threads
|
|
184
187
|
|
|
185
|
-
|
|
188
|
+
The use of worker threads isn't primarily about parallelization - it's about handling Node conditions:
|
|
186
189
|
|
|
187
|
-
The
|
|
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
|
|
188
194
|
|
|
195
|
+
### Future Possibilities: Application-Level Workers
|
|
189
196
|
|
|
190
|
-
|
|
191
|
-
this plugin will register it as a server action - which means you can intend the exported functions to be API endpoints.
|
|
197
|
+
While currently focused on build-time RSC handling, the worker pattern could be extended to the end application:
|
|
192
198
|
|
|
193
|
-
|
|
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
|
|
194
203
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
The React Server Components system requires specific Node conditions:
|
|
202
|
-
|
|
203
|
-
- `NODE_OPTIONS='--conditions=react-server'` is required for RSC functionality (generating RSC streams)
|
|
204
|
-
- This condition must NOT be present for client-side React operations (generating HTML from RSC streams)
|
|
205
|
-
|
|
206
|
-
The plugin recommends using the react-server condition in the main thread to enable React server features from the start. When different conditions are needed (e.g., generating static HTML), the plugin uses workers with appropriate conditions.
|
|
207
|
-
|
|
208
|
-
### Why start with "use client"?
|
|
209
|
-
|
|
210
|
-
With React 19's server-first approach, many existing ecosystem tools and patterns need the "use client" directive to work as they did before. It's becoming a common pattern to start with "use client" to maintain compatibility with existing code while gradually adopting the new server-first paradigm.
|
|
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
|
|
211
209
|
|
|
210
|
+
While this isn't currently implemented, the architecture is designed to potentially support this kind of extension in the future.
|
|
212
211
|
|
|
212
|
+
## License
|
|
213
213
|
|
|
214
|
+
MIT
|
package/bin/patch.mjs
CHANGED
|
@@ -13,8 +13,6 @@ async function patchReactExperimental() {
|
|
|
13
13
|
try {
|
|
14
14
|
// Read installed React version from user's project
|
|
15
15
|
|
|
16
|
-
const installedVersion = React.version
|
|
17
|
-
const PATCH_RECONCILER_VERSION = installedVersion.replace('19.1.0', '0.0.0')
|
|
18
16
|
if(TEMPLATE_VERSION === PATCH_RECONCILER_VERSION) {
|
|
19
17
|
console.log('React version is patched')
|
|
20
18
|
}
|
|
@@ -25,6 +23,14 @@ async function patchReactExperimental() {
|
|
|
25
23
|
template: `../scripts/react-server-dom-esm+${TEMPLATE_VERSION}.patch`,
|
|
26
24
|
output: `react-server-dom-esm+${STUB_VERSION}.patch`
|
|
27
25
|
},
|
|
26
|
+
{
|
|
27
|
+
template: `../scripts/react+${TEMPLATE_VERSION}.patch`,
|
|
28
|
+
output: `react+${PATCH_RECONCILER_VERSION}.patch`
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
template: `../scripts/react-dom+${TEMPLATE_VERSION}.patch`,
|
|
32
|
+
output: `react-dom+${PATCH_RECONCILER_VERSION}.patch`
|
|
33
|
+
},
|
|
28
34
|
]
|
|
29
35
|
|
|
30
36
|
// Create patches dir in user's project
|
package/dist/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vite-plugin-react-server",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.19",
|
|
4
4
|
"description": "Vite plugin for React Server Components (RSC)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/plugin/index.js",
|
|
@@ -91,8 +91,8 @@
|
|
|
91
91
|
},
|
|
92
92
|
"homepage": "https://github.com/nicobrinkkemper/vite-plugin-react-server#readme",
|
|
93
93
|
"peerDependencies": {
|
|
94
|
-
"react": "^0.0.0-experimental-
|
|
95
|
-
"react-dom": "^0.0.0-experimental-
|
|
94
|
+
"react": "^0.0.0-experimental-f9d78089-20250306",
|
|
95
|
+
"react-dom": "^0.0.0-experimental-f9d78089-20250306",
|
|
96
96
|
"vite": "*"
|
|
97
97
|
},
|
|
98
98
|
"peerDependenciesMeta": {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"checkFilesExist.d.ts","sourceRoot":"","sources":["../../plugin/checkFilesExist.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"checkFilesExist.d.ts","sourceRoot":"","sources":["../../plugin/checkFilesExist.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAY7E,wBAAsB,eAAe,CACnC,KAAK,EAAE,MAAM,EAAE,EACf,OAAO,EAAE,mBAAmB,EAC5B,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,qBAAqB,CAAC,CA+ChC"}
|
|
@@ -5,9 +5,9 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { existsSync } from 'node:fs';
|
|
7
7
|
import { join } from 'node:path';
|
|
8
|
-
import 'vite';
|
|
9
8
|
import { createInputNormalizer } from './helpers/inputNormalizer.js';
|
|
10
9
|
|
|
10
|
+
let stashedFiles = null;
|
|
11
11
|
const resolveFileOption = (pageOrProps) => {
|
|
12
12
|
if (typeof pageOrProps === "string") {
|
|
13
13
|
return () => pageOrProps;
|
|
@@ -15,6 +15,9 @@ const resolveFileOption = (pageOrProps) => {
|
|
|
15
15
|
return pageOrProps;
|
|
16
16
|
};
|
|
17
17
|
async function checkFilesExist(pages, options, root) {
|
|
18
|
+
if (stashedFiles) {
|
|
19
|
+
return stashedFiles;
|
|
20
|
+
}
|
|
18
21
|
if (!root || root === "") {
|
|
19
22
|
throw new Error("Root not found");
|
|
20
23
|
}
|
|
@@ -56,7 +59,8 @@ async function checkFilesExist(pages, options, root) {
|
|
|
56
59
|
pageMap.set(pageKey, pageValue);
|
|
57
60
|
propsMap.set(propsKey, propsValue);
|
|
58
61
|
}
|
|
59
|
-
|
|
62
|
+
stashedFiles = { pageMap, pageSet, propsMap, propsSet, urlMap, errors };
|
|
63
|
+
return stashedFiles;
|
|
60
64
|
}
|
|
61
65
|
|
|
62
66
|
export { checkFilesExist };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"checkFilesExist.js","sources":["../../plugin/checkFilesExist.ts"],"sourcesContent":["import { existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { CheckFilesExistReturn, ResolvedUserOptions } from \"./types.js\";\nimport {
|
|
1
|
+
{"version":3,"file":"checkFilesExist.js","sources":["../../plugin/checkFilesExist.ts"],"sourcesContent":["import { existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { CheckFilesExistReturn, ResolvedUserOptions } from \"./types.js\";\nimport { createInputNormalizer } from \"./helpers/inputNormalizer.js\";\n\nlet stashedFiles: CheckFilesExistReturn | null = null;\n\nconst resolveFileOption = (pageOrProps: string | ((url: string) => string)) => {\n if (typeof pageOrProps === \"string\") {\n return () => pageOrProps;\n }\n return pageOrProps;\n};\n\nexport async function checkFilesExist(\n pages: string[],\n options: ResolvedUserOptions,\n root: string\n): Promise<CheckFilesExistReturn> {\n if(stashedFiles){\n return stashedFiles;\n }\n if (!root || root === \"\") {\n throw new Error(\"Root not found\");\n }\n const errors: string[] = [];\n const pageSet = new Set<string>();\n const propsSet = new Set<string>();\n const pageMap = new Map<string, string>();\n const propsMap = new Map<string, string>();\n const urlMap = new Map<string, { props: string; page: string }>();\n const normalizer = createInputNormalizer({\n root,\n preserveModulesRoot: options.build.preserveModulesRoot === true ? options.moduleBase : undefined,\n removeExtension: true,\n });\n const pageFn = resolveFileOption(options.Page);\n const propsFn = resolveFileOption(options.props);\n for (const page of pages) {\n const pagePath = pageFn(page);\n const propsPath = propsFn(page);\n const [pageKey, pageValue] = normalizer(pagePath);\n const [propsKey, propsValue] = normalizer(propsPath);\n try {\n if (!existsSync(join(root, pageValue))) {\n errors.push(\n `Page file not found: ${pagePath}, ${join(root, pagePath)}`\n );\n }\n if (!existsSync(join(root, propsValue))) {\n errors.push(\n `Props file not found: ${propsPath}, ${join(root, propsPath)}`\n );\n }\n } catch (error) {\n errors.push(`Error checking files: ${error}`);\n }\n urlMap.set(page, { props: propsPath, page: pagePath });\n pageSet.add(pagePath);\n propsSet.add(propsPath);\n pageMap.set(pageKey, pageValue);\n propsMap.set(propsKey, propsValue);\n }\n stashedFiles = { pageMap, pageSet, propsMap, propsSet, urlMap, errors };\n return stashedFiles;\n}\n"],"names":[],"mappings":";;;;;;;;;AAKA,IAAI,YAA6C,GAAA,IAAA;AAEjD,MAAM,iBAAA,GAAoB,CAAC,WAAoD,KAAA;AAC7E,EAAI,IAAA,OAAO,gBAAgB,QAAU,EAAA;AACnC,IAAA,OAAO,MAAM,WAAA;AAAA;AAEf,EAAO,OAAA,WAAA;AACT,CAAA;AAEsB,eAAA,eAAA,CACpB,KACA,EAAA,OAAA,EACA,IACgC,EAAA;AAChC,EAAA,IAAG,YAAa,EAAA;AACd,IAAO,OAAA,YAAA;AAAA;AAET,EAAI,IAAA,CAAC,IAAQ,IAAA,IAAA,KAAS,EAAI,EAAA;AACxB,IAAM,MAAA,IAAI,MAAM,gBAAgB,CAAA;AAAA;AAElC,EAAA,MAAM,SAAmB,EAAC;AAC1B,EAAM,MAAA,OAAA,uBAAc,GAAY,EAAA;AAChC,EAAM,MAAA,QAAA,uBAAe,GAAY,EAAA;AACjC,EAAM,MAAA,OAAA,uBAAc,GAAoB,EAAA;AACxC,EAAM,MAAA,QAAA,uBAAe,GAAoB,EAAA;AACzC,EAAM,MAAA,MAAA,uBAAa,GAA6C,EAAA;AAChE,EAAA,MAAM,aAAa,qBAAsB,CAAA;AAAA,IACvC,IAAA;AAAA,IACA,qBAAqB,OAAQ,CAAA,KAAA,CAAM,mBAAwB,KAAA,IAAA,GAAO,QAAQ,UAAa,GAAA,SAAA;AAAA,IACvF,eAAiB,EAAA;AAAA,GAClB,CAAA;AACD,EAAM,MAAA,MAAA,GAAS,iBAAkB,CAAA,OAAA,CAAQ,IAAI,CAAA;AAC7C,EAAM,MAAA,OAAA,GAAU,iBAAkB,CAAA,OAAA,CAAQ,KAAK,CAAA;AAC/C,EAAA,KAAA,MAAW,QAAQ,KAAO,EAAA;AACxB,IAAM,MAAA,QAAA,GAAW,OAAO,IAAI,CAAA;AAC5B,IAAM,MAAA,SAAA,GAAY,QAAQ,IAAI,CAAA;AAC9B,IAAA,MAAM,CAAC,OAAA,EAAS,SAAS,CAAA,GAAI,WAAW,QAAQ,CAAA;AAChD,IAAA,MAAM,CAAC,QAAA,EAAU,UAAU,CAAA,GAAI,WAAW,SAAS,CAAA;AACnD,IAAI,IAAA;AACF,MAAA,IAAI,CAAC,UAAW,CAAA,IAAA,CAAK,IAAM,EAAA,SAAS,CAAC,CAAG,EAAA;AACtC,QAAO,MAAA,CAAA,IAAA;AAAA,UACL,wBAAwB,QAAQ,CAAA,EAAA,EAAK,IAAK,CAAA,IAAA,EAAM,QAAQ,CAAC,CAAA;AAAA,SAC3D;AAAA;AAEF,MAAA,IAAI,CAAC,UAAW,CAAA,IAAA,CAAK,IAAM,EAAA,UAAU,CAAC,CAAG,EAAA;AACvC,QAAO,MAAA,CAAA,IAAA;AAAA,UACL,yBAAyB,SAAS,CAAA,EAAA,EAAK,IAAK,CAAA,IAAA,EAAM,SAAS,CAAC,CAAA;AAAA,SAC9D;AAAA;AACF,aACO,KAAO,EAAA;AACd,MAAO,MAAA,CAAA,IAAA,CAAK,CAAyB,sBAAA,EAAA,KAAK,CAAE,CAAA,CAAA;AAAA;AAE9C,IAAA,MAAA,CAAO,IAAI,IAAM,EAAA,EAAE,OAAO,SAAW,EAAA,IAAA,EAAM,UAAU,CAAA;AACrD,IAAA,OAAA,CAAQ,IAAI,QAAQ,CAAA;AACpB,IAAA,QAAA,CAAS,IAAI,SAAS,CAAA;AACtB,IAAQ,OAAA,CAAA,GAAA,CAAI,SAAS,SAAS,CAAA;AAC9B,IAAS,QAAA,CAAA,GAAA,CAAI,UAAU,UAAU,CAAA;AAAA;AAEnC,EAAA,YAAA,GAAe,EAAE,OAAS,EAAA,OAAA,EAAS,QAAU,EAAA,QAAA,EAAU,QAAQ,MAAO,EAAA;AACtE,EAAO,OAAA,YAAA;AACT;;;;"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { Manifest, ModuleGraph } from "vite";
|
|
2
|
+
export declare function collectModuleGraphCss({ moduleGraph, pagePath, onCss, parentUrl, }: {
|
|
3
|
+
moduleGraph: ModuleGraph;
|
|
4
|
+
pagePath: string;
|
|
5
|
+
onCss?: (path: string, parentUrl: string) => void;
|
|
6
|
+
parentUrl?: string;
|
|
7
|
+
}): Promise<Map<string, string>>;
|
|
8
|
+
export declare function collectManifestClientFiles({ manifest, root, pagePath, preserveModulesRoot, moduleBase, onCss, onClientModule, testClient, testJson, }: {
|
|
9
|
+
manifest: Manifest;
|
|
10
|
+
root: string;
|
|
11
|
+
pagePath: string;
|
|
12
|
+
preserveModulesRoot?: boolean;
|
|
13
|
+
moduleBase?: string;
|
|
14
|
+
onCss?: (path: string, parentUrl: string) => void;
|
|
15
|
+
onClientModule?: (path: string, parentUrl: string) => void;
|
|
16
|
+
parentUrl?: string;
|
|
17
|
+
testClient?: (id: string) => boolean;
|
|
18
|
+
testJson?: (id: string) => boolean;
|
|
19
|
+
}): {
|
|
20
|
+
cssFiles: Map<string, string>;
|
|
21
|
+
clientFiles: Map<string, string>;
|
|
22
|
+
};
|
|
23
|
+
//# sourceMappingURL=collect-manifest-client-files.d.ts.map
|
|
@@ -0,0 +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"}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* vite-plugin-react-server
|
|
3
|
+
* Copyright (c) Nico Brinkkemper
|
|
4
|
+
* MIT License
|
|
5
|
+
*/
|
|
6
|
+
import { createInputNormalizer } from './helpers/inputNormalizer.js';
|
|
7
|
+
import { DEFAULT_CONFIG } from './config/defaults.js';
|
|
8
|
+
|
|
9
|
+
async function collectModuleGraphCss({
|
|
10
|
+
moduleGraph,
|
|
11
|
+
pagePath,
|
|
12
|
+
onCss,
|
|
13
|
+
parentUrl
|
|
14
|
+
}) {
|
|
15
|
+
if (!pagePath) return /* @__PURE__ */ new Map();
|
|
16
|
+
const cssFiles = /* @__PURE__ */ new Map();
|
|
17
|
+
const pageModule = await moduleGraph.getModuleByUrl(pagePath, true);
|
|
18
|
+
if (!pageModule) {
|
|
19
|
+
return /* @__PURE__ */ new Map();
|
|
20
|
+
}
|
|
21
|
+
const seen = /* @__PURE__ */ new Set();
|
|
22
|
+
const walkModule = (mod) => {
|
|
23
|
+
if (!mod?.id || seen.has(mod.id)) return;
|
|
24
|
+
seen.add(mod.id);
|
|
25
|
+
if (mod?.id?.endsWith(".css")) {
|
|
26
|
+
cssFiles.set(mod?.url, mod?.id);
|
|
27
|
+
onCss?.(mod?.url, parentUrl ?? pagePath);
|
|
28
|
+
}
|
|
29
|
+
mod?.importedModules?.forEach((imp) => walkModule(imp));
|
|
30
|
+
};
|
|
31
|
+
walkModule(pageModule);
|
|
32
|
+
return cssFiles;
|
|
33
|
+
}
|
|
34
|
+
function collectManifestClientFiles({
|
|
35
|
+
manifest,
|
|
36
|
+
root,
|
|
37
|
+
pagePath,
|
|
38
|
+
preserveModulesRoot,
|
|
39
|
+
moduleBase,
|
|
40
|
+
onCss,
|
|
41
|
+
onClientModule,
|
|
42
|
+
testClient = DEFAULT_CONFIG.AUTO_DISCOVER.clientComponents,
|
|
43
|
+
testJson = DEFAULT_CONFIG.AUTO_DISCOVER.jsonPattern
|
|
44
|
+
}) {
|
|
45
|
+
const normalizer = createInputNormalizer({
|
|
46
|
+
root,
|
|
47
|
+
removeExtension: true,
|
|
48
|
+
preserveModulesRoot: preserveModulesRoot ? moduleBase : undefined
|
|
49
|
+
});
|
|
50
|
+
const [_, value] = normalizer(pagePath);
|
|
51
|
+
const cssFiles = /* @__PURE__ */ new Map();
|
|
52
|
+
const clientFiles = /* @__PURE__ */ new Map();
|
|
53
|
+
const seen = /* @__PURE__ */ new Set();
|
|
54
|
+
const manifestValues = Object.values(manifest);
|
|
55
|
+
const possibleKeys = [
|
|
56
|
+
value
|
|
57
|
+
// Relative path
|
|
58
|
+
];
|
|
59
|
+
const walkManifestEntry = (id, parentUrl) => {
|
|
60
|
+
if (seen.has(id)) return;
|
|
61
|
+
seen.add(id);
|
|
62
|
+
const entry = manifest[id] ?? manifestValues.find((e) => id === e.file);
|
|
63
|
+
if (!entry) {
|
|
64
|
+
console.log(
|
|
65
|
+
`No manifest entry found for ${id}, possible keys: ${Object.keys(
|
|
66
|
+
manifest
|
|
67
|
+
).join(", ")}`
|
|
68
|
+
);
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
if (typeof testClient === "function" && typeof onClientModule === "function" && testClient(entry.file) || typeof testJson === "function" && testJson(entry.file)) {
|
|
72
|
+
onClientModule?.(entry.file ?? "", parentUrl);
|
|
73
|
+
clientFiles.set(id, entry.name ?? "");
|
|
74
|
+
}
|
|
75
|
+
if (entry.css) {
|
|
76
|
+
entry.css.forEach((css) => {
|
|
77
|
+
cssFiles.set(css, css);
|
|
78
|
+
onCss?.(css, id);
|
|
79
|
+
onClientModule?.(css, id);
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
if (entry.imports) {
|
|
83
|
+
entry.imports.forEach(
|
|
84
|
+
(imp) => walkManifestEntry(imp, entry.file)
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
if (entry.dynamicImports) {
|
|
88
|
+
entry.dynamicImports.forEach(
|
|
89
|
+
(imp) => walkManifestEntry(imp, entry.file)
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
for (const possibleKey of possibleKeys) {
|
|
94
|
+
if (manifest[possibleKey]) {
|
|
95
|
+
walkManifestEntry(possibleKey, pagePath);
|
|
96
|
+
break;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
if (cssFiles.size === 0) {
|
|
100
|
+
const entry = manifestValues.find(
|
|
101
|
+
(e) => possibleKeys.includes(e.file) || e.src && possibleKeys.includes(e.src) || e.name && possibleKeys.includes(e.name)
|
|
102
|
+
);
|
|
103
|
+
if (entry) {
|
|
104
|
+
walkManifestEntry(value, pagePath);
|
|
105
|
+
} else {
|
|
106
|
+
console.warn(
|
|
107
|
+
`No manifest entry found for ${value} (tried all possible keys: ${possibleKeys.join(
|
|
108
|
+
", "
|
|
109
|
+
)})`
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
return { cssFiles, clientFiles };
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export { collectManifestClientFiles, collectModuleGraphCss };
|
|
117
|
+
//# sourceMappingURL=collect-manifest-client-files.js.map
|
|
@@ -0,0 +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,14 +1,14 @@
|
|
|
1
|
+
import React from "react";
|
|
1
2
|
/**
|
|
2
3
|
* A component that emits <link> tags for CSS files during streaming.
|
|
3
4
|
* The high precedence ensures they bubble up to the document head.
|
|
4
5
|
*/
|
|
5
|
-
export declare function CssCollector({
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
}, HTMLElement>;
|
|
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
|
+
}>;
|
|
14
14
|
//# sourceMappingURL=components.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"components.d.ts","sourceRoot":"","sources":["../../plugin/components.tsx"],"names":[],"mappings":"
|
|
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,13 +1,54 @@
|
|
|
1
|
-
import { createElement } from 'react';
|
|
2
1
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
2
|
+
* vite-plugin-react-server
|
|
3
|
+
* Copyright (c) Nico Brinkkemper
|
|
4
|
+
* MIT License
|
|
5
5
|
*/
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
import React__default from 'react';
|
|
7
|
+
|
|
8
|
+
function CssCollector({
|
|
9
|
+
children,
|
|
10
|
+
cssFiles,
|
|
11
|
+
moduleBaseUrl,
|
|
12
|
+
route = "/"
|
|
13
|
+
}) {
|
|
14
|
+
const depth = route.split("/").filter(Boolean).length;
|
|
15
|
+
const prefix = depth > 0 ? "../".repeat(depth) : "./";
|
|
16
|
+
const base = typeof moduleBaseUrl === "string" && moduleBaseUrl !== "" ? moduleBaseUrl : prefix;
|
|
17
|
+
return React__default.createElement(
|
|
18
|
+
React__default.Fragment,
|
|
19
|
+
null,
|
|
20
|
+
...cssFiles.map((css) => {
|
|
21
|
+
try {
|
|
22
|
+
if (moduleBaseUrl) {
|
|
23
|
+
new URL(css, moduleBaseUrl);
|
|
24
|
+
} else {
|
|
25
|
+
new URL(`file://${base}${css}`);
|
|
26
|
+
}
|
|
27
|
+
} catch (error) {
|
|
28
|
+
return React__default.createElement(
|
|
29
|
+
"style",
|
|
30
|
+
{ type: "text/css" },
|
|
31
|
+
css
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
let url = css;
|
|
35
|
+
if (css.startsWith("http") || css.startsWith("data:")) {
|
|
36
|
+
url = css;
|
|
37
|
+
} else if (css.startsWith("/")) {
|
|
38
|
+
url = base + css.slice(1);
|
|
39
|
+
} else if (!css.startsWith("./") && !css.startsWith("../")) {
|
|
40
|
+
url = base + css;
|
|
41
|
+
}
|
|
42
|
+
return React__default.createElement("link", {
|
|
43
|
+
key: css,
|
|
44
|
+
rel: "stylesheet",
|
|
10
45
|
href: url,
|
|
11
|
-
precedence:
|
|
12
|
-
|
|
46
|
+
precedence: "high"
|
|
47
|
+
});
|
|
48
|
+
}),
|
|
49
|
+
children
|
|
50
|
+
);
|
|
13
51
|
}
|
|
52
|
+
|
|
53
|
+
export { CssCollector };
|
|
54
|
+
//# sourceMappingURL=components.js.map
|