waku 0.11.2 → 0.11.3
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 +1 -0
- package/dist/cjs/cli.js +66 -23
- package/dist/cjs/client.js +4 -0
- package/dist/cjs/lib/builder.js +234 -95
- package/dist/cjs/lib/middleware/devServer.js +65 -0
- package/dist/cjs/lib/{rsc-handler.js → middleware/rsc/worker-api.js} +11 -31
- package/dist/cjs/lib/middleware/rsc/worker-impl.js +221 -0
- package/dist/cjs/lib/{middleware.js → middleware/rsc.js} +13 -59
- package/dist/cjs/lib/vite-plugin/rsc-analyze-plugin.js +85 -0
- package/dist/cjs/lib/vite-plugin/rsc-index-plugin.js +25 -0
- package/dist/cjs/lib/vite-plugin/rsc-reload-plugin.js +97 -0
- package/dist/cjs/lib/{vite-plugin-rsc.js → vite-plugin/rsc-transform-plugin.js} +3 -103
- package/dist/cjs/main.js +4 -3
- package/dist/cjs/router/server.js +7 -5
- package/dist/cli.js +66 -23
- package/dist/client.d.ts +1 -1
- package/dist/client.js +4 -0
- package/dist/lib/builder.js +233 -94
- package/dist/lib/middleware/devServer.d.ts +5 -0
- package/dist/lib/middleware/devServer.js +50 -0
- package/dist/lib/{rsc-handler.d.ts → middleware/rsc/worker-api.d.ts} +11 -16
- package/dist/lib/{rsc-handler.js → middleware/rsc/worker-api.js} +9 -26
- package/dist/lib/middleware/rsc/worker-impl.js +212 -0
- package/dist/lib/{middleware.d.ts → middleware/rsc.d.ts} +0 -1
- package/dist/lib/{middleware.js → middleware/rsc.js} +10 -48
- package/dist/lib/vite-plugin/rsc-analyze-plugin.d.ts +2 -0
- package/dist/lib/vite-plugin/rsc-analyze-plugin.js +31 -0
- package/dist/lib/vite-plugin/rsc-index-plugin.d.ts +2 -0
- package/dist/lib/vite-plugin/rsc-index-plugin.js +16 -0
- package/dist/lib/vite-plugin/rsc-reload-plugin.d.ts +2 -0
- package/dist/lib/vite-plugin/rsc-reload-plugin.js +43 -0
- package/dist/lib/vite-plugin/rsc-transform-plugin.d.ts +2 -0
- package/dist/lib/vite-plugin/rsc-transform-plugin.js +61 -0
- package/dist/main.d.ts +2 -1
- package/dist/main.js +2 -1
- package/dist/router/server.js +7 -5
- package/dist/server.d.ts +13 -1
- package/package.json +27 -17
- package/src/cli.ts +70 -24
- package/src/client.ts +4 -0
- package/src/lib/builder.ts +300 -122
- package/src/lib/middleware/devServer.ts +51 -0
- package/src/lib/{rsc-handler.ts → middleware/rsc/worker-api.ts} +26 -39
- package/src/lib/middleware/rsc/worker-impl.ts +223 -0
- package/src/lib/{middleware.ts → middleware/rsc.ts} +9 -48
- package/src/lib/vite-plugin/rsc-analyze-plugin.ts +34 -0
- package/src/lib/vite-plugin/rsc-index-plugin.ts +19 -0
- package/src/lib/vite-plugin/rsc-reload-plugin.ts +44 -0
- package/src/lib/vite-plugin/rsc-transform-plugin.ts +55 -0
- package/src/main.ts +2 -1
- package/src/router/server.ts +5 -12
- package/src/server.ts +19 -3
- package/src/types.d.ts +2 -1
- package/dist/cjs/lib/rsc-handler-worker.js +0 -327
- package/dist/lib/rsc-handler-worker.js +0 -318
- package/dist/lib/vite-plugin-rsc.d.ts +0 -5
- package/dist/lib/vite-plugin-rsc.js +0 -147
- package/src/lib/rsc-handler-worker.ts +0 -358
- package/src/lib/vite-plugin-rsc.ts +0 -145
- /package/dist/cjs/lib/{rsc-utils.js → middleware/rsc/utils.js} +0 -0
- /package/dist/lib/{rsc-utils.d.ts → middleware/rsc/utils.d.ts} +0 -0
- /package/dist/lib/{rsc-utils.js → middleware/rsc/utils.js} +0 -0
- /package/dist/lib/{rsc-handler-worker.d.ts → middleware/rsc/worker-impl.d.ts} +0 -0
- /package/src/lib/{rsc-utils.ts → middleware/rsc/utils.ts} +0 -0
package/README.md
CHANGED
|
@@ -70,6 +70,7 @@ pnpm create waku # pnpm not working for now
|
|
|
70
70
|
- https://twitter.com/dai_shi/status/1660660331528728578
|
|
71
71
|
- https://twitter.com/dai_shi/status/1661727138746339328
|
|
72
72
|
- https://twitter.com/dai_shi/status/1664286329763684353
|
|
73
|
+
- https://twitter.com/dai_shi/status/1664989534889861123
|
|
73
74
|
|
|
74
75
|
</details>
|
|
75
76
|
|
package/dist/cjs/cli.js
CHANGED
|
@@ -5,6 +5,8 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
const _nodefs = /*#__PURE__*/ _interop_require_default(require("node:fs"));
|
|
7
7
|
const _nodepath = /*#__PURE__*/ _interop_require_default(require("node:path"));
|
|
8
|
+
const _nodeutil = require("node:util");
|
|
9
|
+
const _nodemodule = require("node:module");
|
|
8
10
|
function _interop_require_default(obj) {
|
|
9
11
|
return obj && obj.__esModule ? obj : {
|
|
10
12
|
default: obj
|
|
@@ -49,34 +51,60 @@ function _interop_require_wildcard(obj, nodeInterop) {
|
|
|
49
51
|
}
|
|
50
52
|
return newObj;
|
|
51
53
|
}
|
|
52
|
-
const
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
54
|
+
const require1 = (0, _nodemodule.createRequire)(new URL(".", require("url").pathToFileURL(__filename).toString()));
|
|
55
|
+
const { values , positionals } = (0, _nodeutil.parseArgs)({
|
|
56
|
+
args: process.argv.splice(2),
|
|
57
|
+
allowPositionals: true,
|
|
58
|
+
options: {
|
|
59
|
+
config: {
|
|
60
|
+
type: "string"
|
|
61
|
+
},
|
|
62
|
+
version: {
|
|
63
|
+
type: "boolean",
|
|
64
|
+
short: "v"
|
|
65
|
+
},
|
|
66
|
+
help: {
|
|
67
|
+
type: "boolean",
|
|
68
|
+
short: "h"
|
|
60
69
|
}
|
|
61
|
-
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
const cmd = positionals[0];
|
|
73
|
+
if (values.config) {
|
|
74
|
+
if (!_nodefs.default.existsSync(values.config)) {
|
|
75
|
+
throw new Error("config file does not exist");
|
|
76
|
+
} else {
|
|
77
|
+
process.env.CONFIG_FILE = values.config;
|
|
62
78
|
}
|
|
63
79
|
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
80
|
+
if (values.version) {
|
|
81
|
+
const { version } = require1("../package.json");
|
|
82
|
+
console.log(version);
|
|
83
|
+
} else if (values.help) {
|
|
84
|
+
displayUsage();
|
|
85
|
+
} else {
|
|
86
|
+
switch(cmd){
|
|
87
|
+
case "dev":
|
|
88
|
+
runDev();
|
|
89
|
+
break;
|
|
90
|
+
case "build":
|
|
91
|
+
runBuild();
|
|
92
|
+
break;
|
|
93
|
+
case "start":
|
|
94
|
+
runStart();
|
|
95
|
+
break;
|
|
96
|
+
default:
|
|
97
|
+
if (cmd) {
|
|
98
|
+
console.error("Unknown command:", cmd);
|
|
99
|
+
}
|
|
100
|
+
displayUsage();
|
|
101
|
+
break;
|
|
102
|
+
}
|
|
76
103
|
}
|
|
77
104
|
async function runDev() {
|
|
78
105
|
const { default: express } = await Promise.resolve().then(()=>/*#__PURE__*/ _interop_require_wildcard(require("express")));
|
|
79
|
-
const { rsc
|
|
106
|
+
const { rsc } = await Promise.resolve().then(()=>/*#__PURE__*/ _interop_require_wildcard(require("./lib/middleware/rsc.js")));
|
|
107
|
+
const { devServer } = await Promise.resolve().then(()=>/*#__PURE__*/ _interop_require_wildcard(require("./lib/middleware/devServer.js")));
|
|
80
108
|
const app = express();
|
|
81
109
|
app.use(rsc({
|
|
82
110
|
mode: "development"
|
|
@@ -95,7 +123,7 @@ async function runStart() {
|
|
|
95
123
|
const { default: express } = await Promise.resolve().then(()=>/*#__PURE__*/ _interop_require_wildcard(require("express")));
|
|
96
124
|
const { resolveConfig } = await Promise.resolve().then(()=>/*#__PURE__*/ _interop_require_wildcard(require("./lib/config.js")));
|
|
97
125
|
const config = await resolveConfig("serve");
|
|
98
|
-
const { rsc } = await Promise.resolve().then(()=>/*#__PURE__*/ _interop_require_wildcard(require("./lib/middleware.js")));
|
|
126
|
+
const { rsc } = await Promise.resolve().then(()=>/*#__PURE__*/ _interop_require_wildcard(require("./lib/middleware/rsc.js")));
|
|
99
127
|
const app = express();
|
|
100
128
|
app.use(rsc({
|
|
101
129
|
mode: "production"
|
|
@@ -107,3 +135,18 @@ async function runStart() {
|
|
|
107
135
|
console.info("Listening on", port);
|
|
108
136
|
});
|
|
109
137
|
}
|
|
138
|
+
function displayUsage() {
|
|
139
|
+
console.log(`
|
|
140
|
+
Usage: waku [options] <command>
|
|
141
|
+
|
|
142
|
+
Commands:
|
|
143
|
+
dev Start the development server
|
|
144
|
+
build Build the application for production
|
|
145
|
+
start Start the production server
|
|
146
|
+
|
|
147
|
+
Options:
|
|
148
|
+
-c, --config <path> Path to the configuration file
|
|
149
|
+
-v, --version Display the version number
|
|
150
|
+
-h, --help Display this help message
|
|
151
|
+
`);
|
|
152
|
+
}
|
package/dist/cjs/client.js
CHANGED
|
@@ -64,6 +64,10 @@ function serve(rscId, basePath = "/RSC/") {
|
|
|
64
64
|
];
|
|
65
65
|
});
|
|
66
66
|
const ServerComponent = (props)=>{
|
|
67
|
+
if (!props) {
|
|
68
|
+
console.warn("Something went wrong. Please refresh your browser.");
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
67
71
|
// FIXME we blindly expect JSON.stringify usage is deterministic
|
|
68
72
|
const serializedProps = JSON.stringify(props);
|
|
69
73
|
const [data, setRerender] = fetchRSC(serializedProps);
|
package/dist/cjs/lib/builder.js
CHANGED
|
@@ -11,121 +11,99 @@ Object.defineProperty(exports, "build", {
|
|
|
11
11
|
const _nodepath = /*#__PURE__*/ _interop_require_default(require("node:path"));
|
|
12
12
|
const _nodefs = /*#__PURE__*/ _interop_require_default(require("node:fs"));
|
|
13
13
|
const _nodemodule = require("node:module");
|
|
14
|
+
const _nodecrypto = require("node:crypto");
|
|
14
15
|
const _vite = require("vite");
|
|
15
16
|
const _pluginreact = /*#__PURE__*/ _interop_require_default(require("@vitejs/plugin-react"));
|
|
16
17
|
const _config = require("./config.js");
|
|
17
|
-
const
|
|
18
|
-
const
|
|
18
|
+
const _utils = require("./middleware/rsc/utils.js");
|
|
19
|
+
const _workerapi = require("./middleware/rsc/worker-api.js");
|
|
20
|
+
const _rscindexplugin = require("./vite-plugin/rsc-index-plugin.js");
|
|
21
|
+
const _rscanalyzeplugin = require("./vite-plugin/rsc-analyze-plugin.js");
|
|
19
22
|
function _interop_require_default(obj) {
|
|
20
23
|
return obj && obj.__esModule ? obj : {
|
|
21
24
|
default: obj
|
|
22
25
|
};
|
|
23
26
|
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
...htmlFiles
|
|
31
|
-
]){
|
|
32
|
-
const dstFile = _nodepath.default.join(dstDir, "static", _nodepath.default.relative(srcDir, file));
|
|
33
|
-
if (!_nodefs.default.existsSync(dstFile)) {
|
|
34
|
-
_nodefs.default.mkdirSync(_nodepath.default.dirname(dstFile), {
|
|
35
|
-
recursive: true
|
|
36
|
-
});
|
|
37
|
-
_nodefs.default.symlinkSync(_nodepath.default.relative(_nodepath.default.dirname(dstFile), file), dstFile);
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
const overrides = Object.fromEntries([
|
|
41
|
-
...rscFiles.filter((file)=>!_nodepath.default.extname(file)).map((file)=>[
|
|
42
|
-
_nodepath.default.relative(srcDir, file),
|
|
43
|
-
{
|
|
44
|
-
contentType: "text/plain"
|
|
45
|
-
}
|
|
46
|
-
]),
|
|
47
|
-
...htmlFiles.filter((file)=>!_nodepath.default.extname(file)).map((file)=>[
|
|
48
|
-
_nodepath.default.relative(srcDir, file),
|
|
49
|
-
{
|
|
50
|
-
contentType: "text/html"
|
|
51
|
-
}
|
|
52
|
-
])
|
|
53
|
-
]);
|
|
54
|
-
const configJson = {
|
|
55
|
-
version: 3,
|
|
56
|
-
overrides
|
|
57
|
-
};
|
|
58
|
-
_nodefs.default.mkdirSync(dstDir, {
|
|
59
|
-
recursive: true
|
|
60
|
-
});
|
|
61
|
-
_nodefs.default.writeFileSync(_nodepath.default.join(dstDir, "config.json"), JSON.stringify(configJson, null, 2));
|
|
62
|
-
};
|
|
63
|
-
const resolveFileName = (fname)=>{
|
|
64
|
-
for (const ext of [
|
|
65
|
-
".js",
|
|
66
|
-
".ts",
|
|
67
|
-
".tsx",
|
|
68
|
-
".jsx"
|
|
69
|
-
]){
|
|
70
|
-
const resolvedName = fname.slice(0, fname.length - _nodepath.default.extname(fname).length) + ext;
|
|
71
|
-
if (_nodefs.default.existsSync(resolvedName)) {
|
|
72
|
-
return resolvedName;
|
|
73
|
-
}
|
|
27
|
+
// Upstream issue: https://github.com/rollup/rollup/issues/4699
|
|
28
|
+
const onwarn = (warning, warn)=>{
|
|
29
|
+
if (warning.code === "MODULE_LEVEL_DIRECTIVE" && /"use (client|server)"/.test(warning.message)) {
|
|
30
|
+
return;
|
|
31
|
+
} else if (warning.code === "SOURCEMAP_ERROR" && warning.loc?.file?.endsWith(".tsx") && warning.loc?.column === 0 && warning.loc?.line === 1) {
|
|
32
|
+
return;
|
|
74
33
|
}
|
|
75
|
-
|
|
34
|
+
warn(warning);
|
|
76
35
|
};
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
36
|
+
const hash = (fname)=>new Promise((resolve)=>{
|
|
37
|
+
const sha256 = (0, _nodecrypto.createHash)("sha256");
|
|
38
|
+
sha256.on("readable", ()=>{
|
|
39
|
+
const data = sha256.read();
|
|
40
|
+
if (data) {
|
|
41
|
+
resolve(data.toString("hex").slice(0, 9));
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
_nodefs.default.createReadStream(fname).pipe(sha256);
|
|
45
|
+
});
|
|
46
|
+
const analyzeEntries = async (entriesFile)=>{
|
|
86
47
|
const clientEntryFileSet = new Set();
|
|
87
48
|
const serverEntryFileSet = new Set();
|
|
88
49
|
await (0, _vite.build)({
|
|
89
50
|
..._config.configFileConfig,
|
|
90
51
|
plugins: [
|
|
91
|
-
(0,
|
|
52
|
+
(0, _rscanalyzeplugin.rscAnalyzePlugin)((id)=>clientEntryFileSet.add(id), (id)=>serverEntryFileSet.add(id))
|
|
92
53
|
],
|
|
93
54
|
ssr: {
|
|
94
|
-
|
|
95
|
-
//
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
55
|
+
noExternal: /^(?!node:)/,
|
|
56
|
+
// FIXME this is very adhoc.
|
|
57
|
+
external: [
|
|
58
|
+
"react",
|
|
59
|
+
"minimatch"
|
|
60
|
+
]
|
|
61
|
+
},
|
|
62
|
+
resolve: {
|
|
63
|
+
conditions: [
|
|
64
|
+
"react-server"
|
|
100
65
|
]
|
|
101
66
|
},
|
|
102
67
|
build: {
|
|
103
68
|
write: false,
|
|
104
69
|
ssr: true,
|
|
105
70
|
rollupOptions: {
|
|
71
|
+
onwarn,
|
|
106
72
|
input: {
|
|
107
73
|
entries: entriesFile
|
|
108
74
|
}
|
|
109
75
|
}
|
|
110
76
|
}
|
|
111
77
|
});
|
|
112
|
-
const clientEntryFiles = Object.fromEntries(Array.from(clientEntryFileSet).map((fname, i)=>[
|
|
113
|
-
`rsc${i}`,
|
|
78
|
+
const clientEntryFiles = Object.fromEntries(await Promise.all(Array.from(clientEntryFileSet).map(async (fname, i)=>[
|
|
79
|
+
`rsc${i}-${await hash(fname)}`,
|
|
114
80
|
fname
|
|
115
|
-
]));
|
|
81
|
+
])));
|
|
116
82
|
const serverEntryFiles = Object.fromEntries(Array.from(serverEntryFileSet).map((fname, i)=>[
|
|
117
83
|
`rsf${i}`,
|
|
118
84
|
fname
|
|
119
85
|
]));
|
|
86
|
+
return {
|
|
87
|
+
clientEntryFiles,
|
|
88
|
+
serverEntryFiles
|
|
89
|
+
};
|
|
90
|
+
};
|
|
91
|
+
const buildServerBundle = async (config, entriesFile, clientEntryFiles, serverEntryFiles)=>{
|
|
120
92
|
const serverBuildOutput = await (0, _vite.build)({
|
|
121
93
|
..._config.configFileConfig,
|
|
122
94
|
ssr: {
|
|
123
|
-
noExternal:
|
|
95
|
+
noExternal: Object.values(clientEntryFiles).map(// FIXME this might not work with pnpm
|
|
124
96
|
(fname)=>_nodepath.default.relative(_nodepath.default.join(config.root, "node_modules"), fname).split("/")[0])
|
|
125
97
|
},
|
|
98
|
+
resolve: {
|
|
99
|
+
conditions: [
|
|
100
|
+
"react-server"
|
|
101
|
+
]
|
|
102
|
+
},
|
|
126
103
|
build: {
|
|
127
104
|
ssr: true,
|
|
128
105
|
rollupOptions: {
|
|
106
|
+
onwarn,
|
|
129
107
|
input: {
|
|
130
108
|
entries: entriesFile,
|
|
131
109
|
...clientEntryFiles,
|
|
@@ -135,10 +113,10 @@ async function build() {
|
|
|
135
113
|
banner: (chunk)=>{
|
|
136
114
|
// HACK to bring directives to the front
|
|
137
115
|
let code = "";
|
|
138
|
-
if (chunk.moduleIds.some((id)=>
|
|
116
|
+
if (chunk.moduleIds.some((id)=>Object.values(clientEntryFiles).includes(id))) {
|
|
139
117
|
code += '"use client";';
|
|
140
118
|
}
|
|
141
|
-
if (chunk.moduleIds.some((id)=>
|
|
119
|
+
if (chunk.moduleIds.some((id)=>Object.values(serverEntryFiles).includes(id))) {
|
|
142
120
|
code += '"use server";';
|
|
143
121
|
}
|
|
144
122
|
return code;
|
|
@@ -156,43 +134,140 @@ async function build() {
|
|
|
156
134
|
if (!("output" in serverBuildOutput)) {
|
|
157
135
|
throw new Error("Unexpected vite server build output");
|
|
158
136
|
}
|
|
137
|
+
return serverBuildOutput;
|
|
138
|
+
};
|
|
139
|
+
const buildClientBundle = async (config, clientEntryFiles)=>{
|
|
140
|
+
const indexHtmlFile = _nodepath.default.join(config.root, config.framework.indexHtml);
|
|
159
141
|
const clientBuildOutput = await (0, _vite.build)({
|
|
160
142
|
..._config.configFileConfig,
|
|
161
143
|
plugins: [
|
|
162
|
-
// @ts-
|
|
144
|
+
// @ts-expect-error This expression is not callable.
|
|
163
145
|
(0, _pluginreact.default)(),
|
|
164
|
-
(0,
|
|
146
|
+
(0, _rscindexplugin.rscIndexPlugin)()
|
|
165
147
|
],
|
|
166
148
|
build: {
|
|
167
149
|
outDir: _nodepath.default.join(config.build.outDir, config.framework.outPublic),
|
|
168
150
|
rollupOptions: {
|
|
151
|
+
onwarn,
|
|
169
152
|
input: {
|
|
170
153
|
main: indexHtmlFile,
|
|
171
154
|
...clientEntryFiles
|
|
172
155
|
},
|
|
173
|
-
preserveEntrySignatures: "exports-only"
|
|
156
|
+
preserveEntrySignatures: "exports-only",
|
|
157
|
+
output: {
|
|
158
|
+
entryFileNames: (chunkInfo)=>{
|
|
159
|
+
if (clientEntryFiles[chunkInfo.name]) {
|
|
160
|
+
return "assets/[name].js";
|
|
161
|
+
}
|
|
162
|
+
return "assets/[name]-[hash].js";
|
|
163
|
+
}
|
|
164
|
+
}
|
|
174
165
|
}
|
|
175
166
|
}
|
|
176
167
|
});
|
|
177
168
|
if (!("output" in clientBuildOutput)) {
|
|
178
169
|
throw new Error("Unexpected vite client build output");
|
|
179
170
|
}
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
171
|
+
return clientBuildOutput;
|
|
172
|
+
};
|
|
173
|
+
const emitRscFiles = async (config)=>{
|
|
174
|
+
const pathMap = await (0, _workerapi.getBuilderRSC)();
|
|
175
|
+
const clientModuleMap = new Map();
|
|
176
|
+
const addClientModule = (rscId, serializedProps, id)=>{
|
|
177
|
+
const key = rscId + "/" + serializedProps;
|
|
178
|
+
let idSet = clientModuleMap.get(key);
|
|
179
|
+
if (!idSet) {
|
|
180
|
+
idSet = new Set();
|
|
181
|
+
clientModuleMap.set(key, idSet);
|
|
186
182
|
}
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
183
|
+
idSet.add(id);
|
|
184
|
+
};
|
|
185
|
+
const getClientModules = (rscId, serializedProps)=>{
|
|
186
|
+
const key = rscId + "/" + serializedProps;
|
|
187
|
+
const idSet = clientModuleMap.get(key);
|
|
188
|
+
return Array.from(idSet || []);
|
|
189
|
+
};
|
|
190
|
+
const rscFileSet = new Set(); // XXX could be implemented better
|
|
191
|
+
await Promise.all(Object.entries(pathMap).map(async ([, { elements }])=>{
|
|
192
|
+
for (const [rscId, props] of elements || []){
|
|
193
|
+
// FIXME we blindly expect JSON.stringify usage is deterministic
|
|
194
|
+
const serializedProps = JSON.stringify(props);
|
|
195
|
+
const searchParams = new URLSearchParams();
|
|
196
|
+
searchParams.set("props", serializedProps);
|
|
197
|
+
const destFile = _nodepath.default.join(config.root, config.build.outDir, config.framework.outPublic, config.framework.rscPrefix + decodeURIComponent(rscId), decodeURIComponent(`${searchParams}`));
|
|
198
|
+
if (!rscFileSet.has(destFile)) {
|
|
199
|
+
rscFileSet.add(destFile);
|
|
200
|
+
_nodefs.default.mkdirSync(_nodepath.default.dirname(destFile), {
|
|
201
|
+
recursive: true
|
|
202
|
+
});
|
|
203
|
+
const pipeable = (0, _workerapi.renderRSC)({
|
|
204
|
+
rscId,
|
|
205
|
+
props
|
|
206
|
+
}, (id)=>addClientModule(rscId, serializedProps, id));
|
|
207
|
+
await new Promise((resolve, reject)=>{
|
|
208
|
+
const stream = _nodefs.default.createWriteStream(destFile);
|
|
209
|
+
stream.on("finish", resolve);
|
|
210
|
+
stream.on("error", reject);
|
|
211
|
+
pipeable.pipe(stream);
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}));
|
|
216
|
+
return {
|
|
217
|
+
pathMap,
|
|
218
|
+
getClientModules,
|
|
219
|
+
rscFiles: Array.from(rscFileSet)
|
|
220
|
+
};
|
|
221
|
+
};
|
|
222
|
+
const emitHtmlFiles = async (config, pathMap, getClientModules)=>{
|
|
223
|
+
const basePrefix = config.base + config.framework.rscPrefix;
|
|
224
|
+
const publicIndexHtmlFile = _nodepath.default.join(config.root, config.build.outDir, config.framework.outPublic, config.framework.indexHtml);
|
|
225
|
+
const publicIndexHtml = _nodefs.default.readFileSync(publicIndexHtmlFile, {
|
|
226
|
+
encoding: "utf8"
|
|
227
|
+
});
|
|
228
|
+
const htmlFiles = await Promise.all(Object.entries(pathMap).map(async ([pathStr, { elements , customCode }])=>{
|
|
229
|
+
const destFile = _nodepath.default.join(config.root, config.build.outDir, config.framework.outPublic, pathStr, pathStr.endsWith("/") ? "index.html" : "");
|
|
230
|
+
let data = "";
|
|
231
|
+
if (_nodefs.default.existsSync(destFile)) {
|
|
232
|
+
data = _nodefs.default.readFileSync(destFile, {
|
|
233
|
+
encoding: "utf8"
|
|
234
|
+
});
|
|
235
|
+
} else {
|
|
236
|
+
_nodefs.default.mkdirSync(_nodepath.default.dirname(destFile), {
|
|
237
|
+
recursive: true
|
|
238
|
+
});
|
|
239
|
+
data = publicIndexHtml;
|
|
240
|
+
}
|
|
241
|
+
const code = (0, _utils.generatePrefetchCode)(basePrefix, Array.from(elements || []).flatMap(([rscId, props, skipPrefetch])=>{
|
|
242
|
+
if (skipPrefetch) {
|
|
243
|
+
return [];
|
|
244
|
+
}
|
|
245
|
+
return [
|
|
246
|
+
[
|
|
247
|
+
rscId,
|
|
248
|
+
props
|
|
249
|
+
]
|
|
250
|
+
];
|
|
251
|
+
}), Array.from(elements || []).flatMap(([rscId, props])=>{
|
|
252
|
+
// FIXME we blindly expect JSON.stringify usage is deterministic
|
|
253
|
+
const serializedProps = JSON.stringify(props);
|
|
254
|
+
return getClientModules(rscId, serializedProps);
|
|
255
|
+
})) + (customCode || "");
|
|
256
|
+
if (code) {
|
|
257
|
+
// HACK is this too naive to inject script code?
|
|
258
|
+
data = data.replace(/<\/body>/, `<script>${code}</script></body>`);
|
|
259
|
+
}
|
|
260
|
+
_nodefs.default.writeFileSync(destFile, data, {
|
|
261
|
+
encoding: "utf8"
|
|
262
|
+
});
|
|
263
|
+
return destFile;
|
|
264
|
+
}));
|
|
265
|
+
return {
|
|
266
|
+
htmlFiles
|
|
267
|
+
};
|
|
268
|
+
};
|
|
269
|
+
const emitPackageJson = (config)=>{
|
|
270
|
+
const require1 = (0, _nodemodule.createRequire)(require("url").pathToFileURL(__filename).toString());
|
|
196
271
|
const origPackageJson = require1(_nodepath.default.join(config.root, "package.json"));
|
|
197
272
|
const packageJson = {
|
|
198
273
|
name: origPackageJson.name,
|
|
@@ -205,8 +280,72 @@ async function build() {
|
|
|
205
280
|
dependencies: origPackageJson.dependencies
|
|
206
281
|
};
|
|
207
282
|
_nodefs.default.writeFileSync(_nodepath.default.join(config.root, config.build.outDir, "package.json"), JSON.stringify(packageJson, null, 2));
|
|
283
|
+
};
|
|
284
|
+
const emitVercelOutput = (config, clientBuildOutput, rscFiles, htmlFiles)=>{
|
|
285
|
+
const clientFiles = clientBuildOutput.output.map(({ fileName })=>_nodepath.default.join(config.root, config.build.outDir, config.framework.outPublic, fileName));
|
|
286
|
+
const srcDir = _nodepath.default.join(config.root, config.build.outDir, config.framework.outPublic);
|
|
287
|
+
const dstDir = _nodepath.default.join(config.root, config.build.outDir, ".vercel", "output");
|
|
288
|
+
for (const file of [
|
|
289
|
+
...clientFiles,
|
|
290
|
+
...rscFiles,
|
|
291
|
+
...htmlFiles
|
|
292
|
+
]){
|
|
293
|
+
const dstFile = _nodepath.default.join(dstDir, "static", _nodepath.default.relative(srcDir, file));
|
|
294
|
+
if (!_nodefs.default.existsSync(dstFile)) {
|
|
295
|
+
_nodefs.default.mkdirSync(_nodepath.default.dirname(dstFile), {
|
|
296
|
+
recursive: true
|
|
297
|
+
});
|
|
298
|
+
_nodefs.default.symlinkSync(_nodepath.default.relative(_nodepath.default.dirname(dstFile), file), dstFile);
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
const overrides = Object.fromEntries([
|
|
302
|
+
...rscFiles.filter((file)=>!_nodepath.default.extname(file)).map((file)=>[
|
|
303
|
+
_nodepath.default.relative(srcDir, file),
|
|
304
|
+
{
|
|
305
|
+
contentType: "text/plain"
|
|
306
|
+
}
|
|
307
|
+
]),
|
|
308
|
+
...htmlFiles.filter((file)=>!_nodepath.default.extname(file)).map((file)=>[
|
|
309
|
+
_nodepath.default.relative(srcDir, file),
|
|
310
|
+
{
|
|
311
|
+
contentType: "text/html"
|
|
312
|
+
}
|
|
313
|
+
])
|
|
314
|
+
]);
|
|
315
|
+
const configJson = {
|
|
316
|
+
version: 3,
|
|
317
|
+
overrides
|
|
318
|
+
};
|
|
319
|
+
_nodefs.default.mkdirSync(dstDir, {
|
|
320
|
+
recursive: true
|
|
321
|
+
});
|
|
322
|
+
_nodefs.default.writeFileSync(_nodepath.default.join(dstDir, "config.json"), JSON.stringify(configJson, null, 2));
|
|
323
|
+
};
|
|
324
|
+
const resolveFileName = (fname)=>{
|
|
325
|
+
for (const ext of [
|
|
326
|
+
".js",
|
|
327
|
+
".ts",
|
|
328
|
+
".tsx",
|
|
329
|
+
".jsx"
|
|
330
|
+
]){
|
|
331
|
+
const resolvedName = fname.slice(0, fname.length - _nodepath.default.extname(fname).length) + ext;
|
|
332
|
+
if (_nodefs.default.existsSync(resolvedName)) {
|
|
333
|
+
return resolvedName;
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
return fname; // returning the default one
|
|
337
|
+
};
|
|
338
|
+
async function build() {
|
|
339
|
+
const config = await (0, _config.resolveConfig)("build");
|
|
340
|
+
const entriesFile = resolveFileName(_nodepath.default.join(config.root, config.framework.entriesJs));
|
|
341
|
+
const { clientEntryFiles , serverEntryFiles } = await analyzeEntries(entriesFile);
|
|
342
|
+
await buildServerBundle(config, entriesFile, clientEntryFiles, serverEntryFiles);
|
|
343
|
+
const clientBuildOutput = await buildClientBundle(config, clientEntryFiles);
|
|
344
|
+
const { pathMap , getClientModules , rscFiles } = await emitRscFiles(config);
|
|
345
|
+
const { htmlFiles } = await emitHtmlFiles(config, pathMap, getClientModules);
|
|
346
|
+
emitPackageJson(config);
|
|
208
347
|
// https://vercel.com/docs/build-output-api/v3
|
|
209
348
|
// So far, only static sites are supported.
|
|
210
|
-
|
|
211
|
-
await (0,
|
|
349
|
+
emitVercelOutput(config, clientBuildOutput, rscFiles, htmlFiles);
|
|
350
|
+
await (0, _workerapi.shutdown)();
|
|
212
351
|
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
Object.defineProperty(exports, "devServer", {
|
|
6
|
+
enumerable: true,
|
|
7
|
+
get: function() {
|
|
8
|
+
return devServer;
|
|
9
|
+
}
|
|
10
|
+
});
|
|
11
|
+
const _nodepath = /*#__PURE__*/ _interop_require_default(require("node:path"));
|
|
12
|
+
const _vite = require("vite");
|
|
13
|
+
const _pluginreact = /*#__PURE__*/ _interop_require_default(require("@vitejs/plugin-react"));
|
|
14
|
+
const _config = require("../config.js");
|
|
15
|
+
const _workerapi = require("./rsc/worker-api.js");
|
|
16
|
+
const _rscindexplugin = require("../vite-plugin/rsc-index-plugin.js");
|
|
17
|
+
function _interop_require_default(obj) {
|
|
18
|
+
return obj && obj.__esModule ? obj : {
|
|
19
|
+
default: obj
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
function devServer() {
|
|
23
|
+
const vitePromise = (0, _vite.createServer)({
|
|
24
|
+
..._config.configFileConfig,
|
|
25
|
+
optimizeDeps: {
|
|
26
|
+
include: [
|
|
27
|
+
"react-server-dom-webpack/client"
|
|
28
|
+
],
|
|
29
|
+
// FIXME without this, waku router has dual module hazard,
|
|
30
|
+
// and "Uncaught Error: Missing Router" happens.
|
|
31
|
+
exclude: [
|
|
32
|
+
"waku"
|
|
33
|
+
]
|
|
34
|
+
},
|
|
35
|
+
plugins: [
|
|
36
|
+
// @ts-expect-error This expression is not callable.
|
|
37
|
+
(0, _pluginreact.default)(),
|
|
38
|
+
(0, _rscindexplugin.rscIndexPlugin)()
|
|
39
|
+
],
|
|
40
|
+
server: {
|
|
41
|
+
middlewareMode: true
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
vitePromise.then((vite)=>{
|
|
45
|
+
(0, _workerapi.registerReloadCallback)((type)=>vite.ws.send({
|
|
46
|
+
type
|
|
47
|
+
}));
|
|
48
|
+
});
|
|
49
|
+
return async (req, res, next)=>{
|
|
50
|
+
const vite = await vitePromise;
|
|
51
|
+
if (req.url?.startsWith("/node_modules/")) {
|
|
52
|
+
// HACK re-export "?v=..." URL to avoid dual module hazard.
|
|
53
|
+
const fname = _nodepath.default.join(vite.config.root, req.url);
|
|
54
|
+
for (const item of vite.moduleGraph.idToModuleMap.values()){
|
|
55
|
+
if (item.file === fname && item.url !== req.url) {
|
|
56
|
+
res.setHeader("Content-Type", "application/javascript");
|
|
57
|
+
res.statusCode = 200;
|
|
58
|
+
res.end(`export * from "${item.url}";`, "utf8");
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
vite.middlewares(req, res, next);
|
|
64
|
+
};
|
|
65
|
+
}
|