@blinkk/root 1.0.0-beta.2 → 1.0.0-beta.20
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/bin/root.js +3 -0
- package/dist/{chunk-LTSJAEBG.js → chunk-73FJH4HP.js} +5 -4
- package/dist/chunk-73FJH4HP.js.map +1 -0
- package/dist/{chunk-GGQGZ7ZE.js → chunk-DXD5LKU3.js} +1 -1
- package/dist/chunk-DXD5LKU3.js.map +1 -0
- package/dist/{chunk-DTEQ2AIW.js → chunk-QKBMWK5B.js} +1 -1
- package/dist/chunk-QKBMWK5B.js.map +1 -0
- package/dist/{chunk-WTSNW7BB.js → chunk-WX2GLKRC.js} +1 -1
- package/dist/chunk-WX2GLKRC.js.map +1 -0
- package/dist/cli.d.ts +30 -4
- package/dist/cli.js +494 -443
- package/dist/cli.js.map +1 -1
- package/dist/core.d.ts +4 -6
- package/dist/core.js +2 -6
- package/dist/core.js.map +1 -1
- package/dist/node.d.ts +1 -1
- package/dist/node.js +2 -2
- package/dist/render.d.ts +1 -1
- package/dist/render.js +227 -196
- package/dist/render.js.map +1 -1
- package/dist/{config-872b068d.d.ts → types-d73469ff.d.ts} +154 -144
- package/package.json +1 -1
- package/dist/chunk-DTEQ2AIW.js.map +0 -1
- package/dist/chunk-GGQGZ7ZE.js.map +0 -1
- package/dist/chunk-LTSJAEBG.js.map +0 -1
- package/dist/chunk-WTSNW7BB.js.map +0 -1
package/dist/cli.js
CHANGED
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
htmlPretty,
|
|
4
4
|
isValidTagName,
|
|
5
5
|
parseTagNames
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-DXD5LKU3.js";
|
|
7
7
|
import {
|
|
8
8
|
copyGlob,
|
|
9
9
|
createViteServer,
|
|
@@ -16,199 +16,45 @@ import {
|
|
|
16
16
|
makeDir,
|
|
17
17
|
rmDir,
|
|
18
18
|
writeFile
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-73FJH4HP.js";
|
|
20
20
|
import {
|
|
21
21
|
configureServerPlugins,
|
|
22
22
|
getVitePlugins
|
|
23
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-QKBMWK5B.js";
|
|
24
24
|
|
|
25
|
-
// src/cli/commands/
|
|
25
|
+
// src/cli/commands/build.ts
|
|
26
26
|
import path3 from "node:path";
|
|
27
27
|
import { fileURLToPath } from "node:url";
|
|
28
|
-
import
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
import
|
|
32
|
-
import { searchForWorkspaceRoot } from "vite";
|
|
33
|
-
var DevServerAssetMap = class {
|
|
34
|
-
constructor(rootConfig, moduleGraph) {
|
|
35
|
-
this.rootConfig = rootConfig;
|
|
36
|
-
this.moduleGraph = moduleGraph;
|
|
37
|
-
}
|
|
38
|
-
async get(src) {
|
|
39
|
-
const file = path.resolve(this.rootConfig.rootDir, src);
|
|
40
|
-
const viteModules = this.moduleGraph.getModulesByFile(file);
|
|
41
|
-
if (viteModules && viteModules.size > 0) {
|
|
42
|
-
const [viteModule] = viteModules;
|
|
43
|
-
return new DevServerAsset(src, {
|
|
44
|
-
assetMap: this,
|
|
45
|
-
viteModule
|
|
46
|
-
});
|
|
47
|
-
}
|
|
48
|
-
if (file.startsWith(this.rootConfig.rootDir)) {
|
|
49
|
-
const assetUrl = file.slice(this.rootConfig.rootDir.length);
|
|
50
|
-
return {
|
|
51
|
-
src,
|
|
52
|
-
assetUrl,
|
|
53
|
-
getCssDeps: async () => [],
|
|
54
|
-
getJsDeps: async () => [assetUrl]
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
|
-
const workspaceRoot = searchForWorkspaceRoot(this.rootConfig.rootDir);
|
|
58
|
-
if (await directoryContains(workspaceRoot, file)) {
|
|
59
|
-
const assetUrl = `/@fs/${file}`;
|
|
60
|
-
return {
|
|
61
|
-
src,
|
|
62
|
-
assetUrl,
|
|
63
|
-
getCssDeps: async () => [],
|
|
64
|
-
getJsDeps: async () => [assetUrl]
|
|
65
|
-
};
|
|
66
|
-
}
|
|
67
|
-
console.log(`could not find asset in asset map: ${src}`);
|
|
68
|
-
return null;
|
|
69
|
-
}
|
|
70
|
-
filePathToSrc(file) {
|
|
71
|
-
return path.relative(this.rootConfig.rootDir, file);
|
|
72
|
-
}
|
|
73
|
-
};
|
|
74
|
-
var DevServerAsset = class {
|
|
75
|
-
constructor(src, options) {
|
|
76
|
-
this.src = src;
|
|
77
|
-
this.assetMap = options.assetMap;
|
|
78
|
-
this.viteModule = options.viteModule;
|
|
79
|
-
this.moduleId = this.viteModule.id;
|
|
80
|
-
this.assetUrl = this.viteModule.url;
|
|
81
|
-
}
|
|
82
|
-
async getCssDeps() {
|
|
83
|
-
const visited = /* @__PURE__ */ new Set();
|
|
84
|
-
const deps = /* @__PURE__ */ new Set();
|
|
85
|
-
this.collectCss(this, deps, visited);
|
|
86
|
-
return Array.from(deps);
|
|
87
|
-
}
|
|
88
|
-
async getJsDeps() {
|
|
89
|
-
const visited = /* @__PURE__ */ new Set();
|
|
90
|
-
const deps = /* @__PURE__ */ new Set();
|
|
91
|
-
this.collectJs(this, deps, visited);
|
|
92
|
-
return Array.from(deps);
|
|
93
|
-
}
|
|
94
|
-
getImportedModules() {
|
|
95
|
-
return this.viteModule.importedModules;
|
|
96
|
-
}
|
|
97
|
-
collectJs(asset, urls, visited) {
|
|
98
|
-
if (!asset) {
|
|
99
|
-
return;
|
|
100
|
-
}
|
|
101
|
-
if (!asset.moduleId) {
|
|
102
|
-
return;
|
|
103
|
-
}
|
|
104
|
-
if (visited.has(asset.moduleId)) {
|
|
105
|
-
return;
|
|
106
|
-
}
|
|
107
|
-
visited.add(asset.moduleId);
|
|
108
|
-
const parts = path.parse(asset.assetUrl);
|
|
109
|
-
if ([".js", ".jsx", ".ts", ".tsx"].includes(parts.ext) && asset.moduleId.includes("/elements/")) {
|
|
110
|
-
urls.add(asset.assetUrl);
|
|
111
|
-
}
|
|
112
|
-
asset.getImportedModules().forEach((viteModule) => {
|
|
113
|
-
if (viteModule.file) {
|
|
114
|
-
const src = this.assetMap.filePathToSrc(viteModule.file);
|
|
115
|
-
const importedAsset = new DevServerAsset(src, {
|
|
116
|
-
assetMap: this.assetMap,
|
|
117
|
-
viteModule
|
|
118
|
-
});
|
|
119
|
-
this.collectJs(importedAsset, urls, visited);
|
|
120
|
-
}
|
|
121
|
-
});
|
|
122
|
-
}
|
|
123
|
-
collectCss(asset, urls, visited) {
|
|
124
|
-
if (!asset) {
|
|
125
|
-
return;
|
|
126
|
-
}
|
|
127
|
-
if (!asset.assetUrl) {
|
|
128
|
-
return;
|
|
129
|
-
}
|
|
130
|
-
if (visited.has(asset.assetUrl)) {
|
|
131
|
-
return;
|
|
132
|
-
}
|
|
133
|
-
visited.add(asset.assetUrl);
|
|
134
|
-
if (asset.src.endsWith(".scss")) {
|
|
135
|
-
const parts = path.parse(asset.src);
|
|
136
|
-
if (!parts.name.startsWith("_")) {
|
|
137
|
-
urls.add(asset.assetUrl);
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
asset.getImportedModules().forEach((viteModule) => {
|
|
141
|
-
if (viteModule.file) {
|
|
142
|
-
const src = this.assetMap.filePathToSrc(viteModule.file);
|
|
143
|
-
const importedAsset = new DevServerAsset(src, {
|
|
144
|
-
assetMap: this.assetMap,
|
|
145
|
-
viteModule
|
|
146
|
-
});
|
|
147
|
-
this.collectCss(importedAsset, urls, visited);
|
|
148
|
-
}
|
|
149
|
-
});
|
|
150
|
-
}
|
|
151
|
-
};
|
|
152
|
-
|
|
153
|
-
// src/cli/commands/dev.ts
|
|
154
|
-
import { dim } from "kleur/colors";
|
|
155
|
-
|
|
156
|
-
// src/core/middleware.ts
|
|
157
|
-
function rootProjectMiddleware(options) {
|
|
158
|
-
return (req, _, next) => {
|
|
159
|
-
req.rootConfig = options.rootConfig;
|
|
160
|
-
next();
|
|
161
|
-
};
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
// src/utils/ports.ts
|
|
165
|
-
import { createServer } from "node:net";
|
|
166
|
-
function isPortOpen(port) {
|
|
167
|
-
return new Promise((resolve, reject) => {
|
|
168
|
-
const server = createServer();
|
|
169
|
-
server.on("error", (err) => {
|
|
170
|
-
if (err.code === "EADDRINUSE") {
|
|
171
|
-
resolve(false);
|
|
172
|
-
return;
|
|
173
|
-
}
|
|
174
|
-
reject(err);
|
|
175
|
-
});
|
|
176
|
-
server.on("close", () => {
|
|
177
|
-
resolve(true);
|
|
178
|
-
});
|
|
179
|
-
server.listen(port, () => {
|
|
180
|
-
server.close((err) => {
|
|
181
|
-
if (err) {
|
|
182
|
-
console.log(`error closing server: ${err}`);
|
|
183
|
-
reject(err);
|
|
184
|
-
}
|
|
185
|
-
});
|
|
186
|
-
});
|
|
187
|
-
});
|
|
188
|
-
}
|
|
189
|
-
async function findOpenPort(min, max) {
|
|
190
|
-
let port = min;
|
|
191
|
-
while (port <= max) {
|
|
192
|
-
const isOpen = await isPortOpen(port);
|
|
193
|
-
if (isOpen) {
|
|
194
|
-
return port;
|
|
195
|
-
}
|
|
196
|
-
port += 1;
|
|
197
|
-
}
|
|
198
|
-
throw new Error(`no ports open between ${min} and ${max}`);
|
|
199
|
-
}
|
|
28
|
+
import fsExtra from "fs-extra";
|
|
29
|
+
import { dim, cyan } from "kleur/colors";
|
|
30
|
+
import glob2 from "tiny-glob";
|
|
31
|
+
import { build as viteBuild } from "vite";
|
|
200
32
|
|
|
201
33
|
// src/node/element-graph.ts
|
|
202
34
|
import fs from "node:fs";
|
|
203
|
-
import
|
|
204
|
-
import { searchForWorkspaceRoot as searchForWorkspaceRoot2 } from "vite";
|
|
35
|
+
import path from "node:path";
|
|
205
36
|
import glob from "tiny-glob";
|
|
37
|
+
import { searchForWorkspaceRoot } from "vite";
|
|
206
38
|
var ElementGraph = class {
|
|
207
39
|
constructor(sourceFiles) {
|
|
208
40
|
this.sourceFiles = {};
|
|
209
41
|
this.deps = {};
|
|
210
42
|
this.sourceFiles = sourceFiles;
|
|
211
43
|
}
|
|
44
|
+
toJson() {
|
|
45
|
+
for (const tagName in this.sourceFiles) {
|
|
46
|
+
this.deps[tagName] ??= this.parseDepsFromSource(tagName);
|
|
47
|
+
}
|
|
48
|
+
return {
|
|
49
|
+
sourceFiles: this.sourceFiles,
|
|
50
|
+
deps: this.deps
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
static fromJson(data) {
|
|
54
|
+
const graph = new ElementGraph(data.sourceFiles);
|
|
55
|
+
graph.deps = data.deps;
|
|
56
|
+
return graph;
|
|
57
|
+
}
|
|
212
58
|
getDeps(tagName, visited) {
|
|
213
59
|
visited ??= /* @__PURE__ */ new Set();
|
|
214
60
|
if (visited.has(tagName)) {
|
|
@@ -243,15 +89,15 @@ var ElementGraph = class {
|
|
|
243
89
|
async function getElements(rootConfig) {
|
|
244
90
|
var _a, _b;
|
|
245
91
|
const rootDir = rootConfig.rootDir;
|
|
246
|
-
const workspaceRoot =
|
|
247
|
-
const elementsDirs = [
|
|
92
|
+
const workspaceRoot = searchForWorkspaceRoot(rootDir);
|
|
93
|
+
const elementsDirs = [path.join(rootDir, "elements")];
|
|
248
94
|
const elementsInclude = ((_a = rootConfig.elements) == null ? void 0 : _a.include) || [];
|
|
249
95
|
const excludePatterns = ((_b = rootConfig.elements) == null ? void 0 : _b.exclude) || [];
|
|
250
96
|
const excludeElement = (moduleId) => {
|
|
251
97
|
return excludePatterns.some((pattern) => Boolean(moduleId.match(pattern)));
|
|
252
98
|
};
|
|
253
99
|
for (const dirPath of elementsInclude) {
|
|
254
|
-
const elementsDir =
|
|
100
|
+
const elementsDir = path.resolve(rootDir, dirPath);
|
|
255
101
|
if (!directoryContains(rootDir, elementsDir)) {
|
|
256
102
|
throw new Error(
|
|
257
103
|
`the elements dir (${dirPath}) should be within the project's workspace (${workspaceRoot})`
|
|
@@ -264,11 +110,11 @@ async function getElements(rootConfig) {
|
|
|
264
110
|
if (await isDirectory(dirPath)) {
|
|
265
111
|
const files = await glob("**/*", { cwd: dirPath });
|
|
266
112
|
files.forEach((file) => {
|
|
267
|
-
const parts =
|
|
113
|
+
const parts = path.parse(file);
|
|
268
114
|
if (isJsFile(parts.base) && isValidTagName(parts.name)) {
|
|
269
115
|
const tagName = parts.name;
|
|
270
|
-
const filePath =
|
|
271
|
-
const relPath =
|
|
116
|
+
const filePath = path.join(dirPath, file);
|
|
117
|
+
const relPath = path.relative(rootDir, filePath);
|
|
272
118
|
if (!excludeElement(relPath)) {
|
|
273
119
|
elementFilePaths[tagName] = { filePath, relPath };
|
|
274
120
|
}
|
|
@@ -280,146 +126,9 @@ async function getElements(rootConfig) {
|
|
|
280
126
|
return graph;
|
|
281
127
|
}
|
|
282
128
|
|
|
283
|
-
// src/cli/commands/dev.ts
|
|
284
|
-
import glob2 from "tiny-glob";
|
|
285
|
-
var __dirname = path3.dirname(fileURLToPath(import.meta.url));
|
|
286
|
-
async function dev(rootProjectDir) {
|
|
287
|
-
process.env.NODE_ENV = "development";
|
|
288
|
-
const rootDir = path3.resolve(rootProjectDir || process.cwd());
|
|
289
|
-
const defaultPort = parseInt(process.env.PORT || "4007");
|
|
290
|
-
const port = await findOpenPort(defaultPort, defaultPort + 10);
|
|
291
|
-
console.log();
|
|
292
|
-
console.log(`${dim("\u2503")} project: ${rootDir}`);
|
|
293
|
-
console.log(`${dim("\u2503")} server: http://localhost:${port}`);
|
|
294
|
-
console.log(`${dim("\u2503")} mode: development`);
|
|
295
|
-
console.log();
|
|
296
|
-
const server = await createServer2({ rootDir, port });
|
|
297
|
-
server.listen(port);
|
|
298
|
-
}
|
|
299
|
-
async function createServer2(options) {
|
|
300
|
-
const rootDir = path3.resolve((options == null ? void 0 : options.rootDir) || process.cwd());
|
|
301
|
-
const rootConfig = await loadRootConfig(rootDir, { command: "dev" });
|
|
302
|
-
const port = options == null ? void 0 : options.port;
|
|
303
|
-
const server = express();
|
|
304
|
-
server.disable("x-powered-by");
|
|
305
|
-
server.use(rootProjectMiddleware({ rootConfig }));
|
|
306
|
-
server.use(await viteServerMiddleware({ rootConfig, port }));
|
|
307
|
-
const plugins = rootConfig.plugins || [];
|
|
308
|
-
await configureServerPlugins(
|
|
309
|
-
server,
|
|
310
|
-
async () => {
|
|
311
|
-
var _a;
|
|
312
|
-
const userMiddlewares = ((_a = rootConfig.server) == null ? void 0 : _a.middlewares) || [];
|
|
313
|
-
for (const middleware of userMiddlewares) {
|
|
314
|
-
server.use(middleware);
|
|
315
|
-
}
|
|
316
|
-
server.use(rootDevServerMiddleware());
|
|
317
|
-
server.use(rootDevServer404Middleware());
|
|
318
|
-
server.use(rootDevServer500Middleware());
|
|
319
|
-
},
|
|
320
|
-
plugins,
|
|
321
|
-
{ type: "dev", rootConfig }
|
|
322
|
-
);
|
|
323
|
-
return server;
|
|
324
|
-
}
|
|
325
|
-
async function viteServerMiddleware(options) {
|
|
326
|
-
const rootConfig = options.rootConfig;
|
|
327
|
-
const rootDir = rootConfig.rootDir;
|
|
328
|
-
const elementGraph = await getElements(rootConfig);
|
|
329
|
-
const elements = Object.values(elementGraph.sourceFiles).map((sourceFile) => {
|
|
330
|
-
return sourceFile.relPath;
|
|
331
|
-
});
|
|
332
|
-
const bundleScripts = [];
|
|
333
|
-
if (await isDirectory(path3.join(rootDir, "bundles"))) {
|
|
334
|
-
const bundleFiles = await glob2("bundles/*", { cwd: rootDir });
|
|
335
|
-
bundleFiles.forEach((file) => {
|
|
336
|
-
const parts = path3.parse(file);
|
|
337
|
-
if (isJsFile(parts.base)) {
|
|
338
|
-
bundleScripts.push(file);
|
|
339
|
-
}
|
|
340
|
-
});
|
|
341
|
-
}
|
|
342
|
-
const optimizeDeps = [...elements, ...bundleScripts];
|
|
343
|
-
const viteServer = await createViteServer(rootConfig, {
|
|
344
|
-
port: options.port,
|
|
345
|
-
optimizeDeps
|
|
346
|
-
});
|
|
347
|
-
return async (req, res, next) => {
|
|
348
|
-
try {
|
|
349
|
-
req.viteServer = viteServer;
|
|
350
|
-
const renderModulePath = path3.resolve(__dirname, "./render.js");
|
|
351
|
-
const render = await viteServer.ssrLoadModule(
|
|
352
|
-
renderModulePath
|
|
353
|
-
);
|
|
354
|
-
const assetMap = new DevServerAssetMap(
|
|
355
|
-
rootConfig,
|
|
356
|
-
viteServer.moduleGraph
|
|
357
|
-
);
|
|
358
|
-
req.renderer = new render.Renderer(rootConfig, { assetMap, elementGraph });
|
|
359
|
-
viteServer.middlewares(req, res, next);
|
|
360
|
-
} catch (e) {
|
|
361
|
-
next(e);
|
|
362
|
-
}
|
|
363
|
-
};
|
|
364
|
-
}
|
|
365
|
-
function rootDevServerMiddleware() {
|
|
366
|
-
return async (req, res, next) => {
|
|
367
|
-
const renderer = req.renderer;
|
|
368
|
-
const viteServer = req.viteServer;
|
|
369
|
-
try {
|
|
370
|
-
await renderer.handle(req, res, next);
|
|
371
|
-
} catch (err) {
|
|
372
|
-
viteServer.ssrFixStacktrace(err);
|
|
373
|
-
next(err);
|
|
374
|
-
}
|
|
375
|
-
};
|
|
376
|
-
}
|
|
377
|
-
function rootDevServer404Middleware() {
|
|
378
|
-
return async (req, res) => {
|
|
379
|
-
console.error(`\u2753 404 ${req.originalUrl}`);
|
|
380
|
-
if (req.renderer) {
|
|
381
|
-
const url = req.path;
|
|
382
|
-
const ext = path3.extname(url);
|
|
383
|
-
if (!ext) {
|
|
384
|
-
const renderer = req.renderer;
|
|
385
|
-
const data = await renderer.renderDevServer404(req);
|
|
386
|
-
const html = data.html || "";
|
|
387
|
-
res.status(404).set({ "Content-Type": "text/html" }).end(html);
|
|
388
|
-
return;
|
|
389
|
-
}
|
|
390
|
-
}
|
|
391
|
-
res.status(404).set({ "Content-Type": "text/plain" }).end("404");
|
|
392
|
-
};
|
|
393
|
-
}
|
|
394
|
-
function rootDevServer500Middleware() {
|
|
395
|
-
return async (err, req, res, next) => {
|
|
396
|
-
console.error(`\u2757 500 ${req.originalUrl}`);
|
|
397
|
-
console.error(String(err.stack || err));
|
|
398
|
-
if (req.renderer) {
|
|
399
|
-
const url = req.path;
|
|
400
|
-
const ext = path3.extname(url);
|
|
401
|
-
if (!ext) {
|
|
402
|
-
const renderer = req.renderer;
|
|
403
|
-
const data = await renderer.renderDevServer500(req, err);
|
|
404
|
-
const html = data.html || "";
|
|
405
|
-
res.status(500).set({ "Content-Type": "text/html" }).end(html);
|
|
406
|
-
return;
|
|
407
|
-
}
|
|
408
|
-
}
|
|
409
|
-
next(err);
|
|
410
|
-
};
|
|
411
|
-
}
|
|
412
|
-
|
|
413
|
-
// src/cli/commands/build.ts
|
|
414
|
-
import path5 from "node:path";
|
|
415
|
-
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
416
|
-
import fsExtra from "fs-extra";
|
|
417
|
-
import glob3 from "tiny-glob";
|
|
418
|
-
import { build as viteBuild } from "vite";
|
|
419
|
-
|
|
420
129
|
// src/render/asset-map/build-asset-map.ts
|
|
421
130
|
import fs2 from "node:fs";
|
|
422
|
-
import
|
|
131
|
+
import path2 from "node:path";
|
|
423
132
|
var BuildAssetMap = class {
|
|
424
133
|
constructor(rootConfig) {
|
|
425
134
|
this.rootConfig = rootConfig;
|
|
@@ -489,12 +198,12 @@ var BuildAssetMap = class {
|
|
|
489
198
|
}
|
|
490
199
|
};
|
|
491
200
|
function realPathRelativeTo(rootDir, src) {
|
|
492
|
-
const fullPath =
|
|
201
|
+
const fullPath = path2.resolve(rootDir, src);
|
|
493
202
|
if (!fs2.existsSync(fullPath)) {
|
|
494
203
|
return src;
|
|
495
204
|
}
|
|
496
|
-
const realpath = fs2.realpathSync(
|
|
497
|
-
return
|
|
205
|
+
const realpath = fs2.realpathSync(path2.resolve(rootDir, src));
|
|
206
|
+
return path2.relative(rootDir, realpath);
|
|
498
207
|
}
|
|
499
208
|
var BuildAsset = class {
|
|
500
209
|
constructor(assetMap, assetData) {
|
|
@@ -571,30 +280,29 @@ var BuildAsset = class {
|
|
|
571
280
|
};
|
|
572
281
|
|
|
573
282
|
// src/cli/commands/build.ts
|
|
574
|
-
|
|
575
|
-
var __dirname2 = path5.dirname(fileURLToPath2(import.meta.url));
|
|
283
|
+
var __dirname = path3.dirname(fileURLToPath(import.meta.url));
|
|
576
284
|
async function build(rootProjectDir, options) {
|
|
577
285
|
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
578
286
|
const mode = (options == null ? void 0 : options.mode) || "production";
|
|
579
287
|
process.env.NODE_ENV = mode;
|
|
580
|
-
const rootDir =
|
|
288
|
+
const rootDir = path3.resolve(rootProjectDir || process.cwd());
|
|
581
289
|
const rootConfig = await loadRootConfig(rootDir, { command: "build" });
|
|
582
|
-
const distDir =
|
|
290
|
+
const distDir = path3.join(rootDir, "dist");
|
|
583
291
|
const ssrOnly = (options == null ? void 0 : options.ssrOnly) || false;
|
|
584
292
|
console.log();
|
|
585
|
-
console.log(`${
|
|
586
|
-
console.log(`${
|
|
587
|
-
console.log(`${
|
|
293
|
+
console.log(`${dim("\u2503")} project: ${rootDir}`);
|
|
294
|
+
console.log(`${dim("\u2503")} output: ${distDir}/html`);
|
|
295
|
+
console.log(`${dim("\u2503")} mode: ${mode}`);
|
|
588
296
|
console.log();
|
|
589
297
|
await rmDir(distDir);
|
|
590
298
|
await makeDir(distDir);
|
|
591
299
|
const routeFiles = [];
|
|
592
|
-
if (await isDirectory(
|
|
593
|
-
const pageFiles = await
|
|
300
|
+
if (await isDirectory(path3.join(rootDir, "routes"))) {
|
|
301
|
+
const pageFiles = await glob2("routes/**/*", { cwd: rootDir });
|
|
594
302
|
pageFiles.forEach((file) => {
|
|
595
|
-
const parts =
|
|
303
|
+
const parts = path3.parse(file);
|
|
596
304
|
if (!parts.name.startsWith("_") && isJsFile(parts.base)) {
|
|
597
|
-
routeFiles.push(
|
|
305
|
+
routeFiles.push(path3.resolve(rootDir, file));
|
|
598
306
|
}
|
|
599
307
|
});
|
|
600
308
|
}
|
|
@@ -603,12 +311,12 @@ async function build(rootProjectDir, options) {
|
|
|
603
311
|
return sourceFile.filePath;
|
|
604
312
|
});
|
|
605
313
|
const bundleScripts = [];
|
|
606
|
-
if (await isDirectory(
|
|
607
|
-
const bundleFiles = await
|
|
314
|
+
if (await isDirectory(path3.join(rootDir, "bundles"))) {
|
|
315
|
+
const bundleFiles = await glob2("bundles/*", { cwd: rootDir });
|
|
608
316
|
bundleFiles.forEach((file) => {
|
|
609
|
-
const parts =
|
|
317
|
+
const parts = path3.parse(file);
|
|
610
318
|
if (isJsFile(parts.base)) {
|
|
611
|
-
bundleScripts.push(
|
|
319
|
+
bundleScripts.push(path3.resolve(rootDir, file));
|
|
612
320
|
}
|
|
613
321
|
});
|
|
614
322
|
}
|
|
@@ -631,7 +339,7 @@ async function build(rootProjectDir, options) {
|
|
|
631
339
|
plugins: vitePlugins
|
|
632
340
|
};
|
|
633
341
|
const ssrInput = {
|
|
634
|
-
render:
|
|
342
|
+
render: path3.resolve(__dirname, "./render.js")
|
|
635
343
|
};
|
|
636
344
|
rootPlugins.forEach((plugin) => {
|
|
637
345
|
if (plugin.ssrInput) {
|
|
@@ -661,7 +369,7 @@ async function build(rootProjectDir, options) {
|
|
|
661
369
|
assetFileNames: "assets/[name].[hash][extname]"
|
|
662
370
|
}
|
|
663
371
|
},
|
|
664
|
-
outDir:
|
|
372
|
+
outDir: path3.join(distDir, "server"),
|
|
665
373
|
ssr: true,
|
|
666
374
|
ssrManifest: false,
|
|
667
375
|
cssCodeSplit: true,
|
|
@@ -692,7 +400,7 @@ async function build(rootProjectDir, options) {
|
|
|
692
400
|
...(_e = (_d = viteConfig == null ? void 0 : viteConfig.build) == null ? void 0 : _d.rollupOptions) == null ? void 0 : _e.output
|
|
693
401
|
}
|
|
694
402
|
},
|
|
695
|
-
outDir:
|
|
403
|
+
outDir: path3.join(distDir, "routes"),
|
|
696
404
|
ssr: false,
|
|
697
405
|
ssrManifest: false,
|
|
698
406
|
manifest: true,
|
|
@@ -721,7 +429,7 @@ async function build(rootProjectDir, options) {
|
|
|
721
429
|
...(_h = (_g = viteConfig == null ? void 0 : viteConfig.build) == null ? void 0 : _g.rollupOptions) == null ? void 0 : _h.output
|
|
722
430
|
}
|
|
723
431
|
},
|
|
724
|
-
outDir:
|
|
432
|
+
outDir: path3.join(distDir, "client"),
|
|
725
433
|
ssr: false,
|
|
726
434
|
ssrManifest: false,
|
|
727
435
|
manifest: true,
|
|
@@ -733,18 +441,18 @@ async function build(rootProjectDir, options) {
|
|
|
733
441
|
}
|
|
734
442
|
});
|
|
735
443
|
} else {
|
|
736
|
-
await writeFile(
|
|
444
|
+
await writeFile(path3.join(distDir, "client/manifest.json"), "{}");
|
|
737
445
|
}
|
|
738
446
|
await copyGlob(
|
|
739
447
|
"*.css",
|
|
740
|
-
|
|
741
|
-
|
|
448
|
+
path3.join(distDir, "routes/assets"),
|
|
449
|
+
path3.join(distDir, "client/assets")
|
|
742
450
|
);
|
|
743
451
|
const routesManifest = await loadJson(
|
|
744
|
-
|
|
452
|
+
path3.join(distDir, "routes/manifest.json")
|
|
745
453
|
);
|
|
746
454
|
const clientManifest = await loadJson(
|
|
747
|
-
|
|
455
|
+
path3.join(distDir, "client/manifest.json")
|
|
748
456
|
);
|
|
749
457
|
function collectRouteCss(asset, cssDeps, visited) {
|
|
750
458
|
if (!asset || !asset.file || visited.has(asset.file)) {
|
|
@@ -780,112 +488,423 @@ async function build(rootProjectDir, options) {
|
|
|
780
488
|
);
|
|
781
489
|
const rootManifest = assetMap.toJson();
|
|
782
490
|
await writeFile(
|
|
783
|
-
|
|
491
|
+
path3.join(distDir, "client/root-manifest.json"),
|
|
784
492
|
JSON.stringify(rootManifest, null, 2)
|
|
785
493
|
);
|
|
786
|
-
const
|
|
787
|
-
|
|
788
|
-
|
|
494
|
+
const elementGraphJson = elementGraph.toJson();
|
|
495
|
+
await writeFile(
|
|
496
|
+
path3.join(distDir, "client/root-element-graph.json"),
|
|
497
|
+
JSON.stringify(elementGraphJson, null, 2)
|
|
498
|
+
);
|
|
499
|
+
const buildDir = path3.join(distDir, "html");
|
|
500
|
+
const publicDir = path3.join(rootDir, "public");
|
|
501
|
+
if (fsExtra.existsSync(path3.join(rootDir, "public"))) {
|
|
789
502
|
fsExtra.copySync(publicDir, buildDir, { dereference: true });
|
|
790
503
|
} else {
|
|
791
504
|
await makeDir(buildDir);
|
|
792
505
|
}
|
|
793
|
-
await makeDir(
|
|
794
|
-
await makeDir(
|
|
506
|
+
await makeDir(path3.join(buildDir, "assets"));
|
|
507
|
+
await makeDir(path3.join(buildDir, "chunks"));
|
|
795
508
|
console.log("\njs/css output:");
|
|
796
509
|
await Promise.all(
|
|
797
510
|
Object.keys(rootManifest).map(async (src) => {
|
|
798
511
|
if (isRouteFile(src)) {
|
|
799
512
|
return;
|
|
800
513
|
}
|
|
801
|
-
const assetData = rootManifest[src];
|
|
802
|
-
if (!assetData.assetUrl) {
|
|
803
|
-
return;
|
|
514
|
+
const assetData = rootManifest[src];
|
|
515
|
+
if (!assetData.assetUrl) {
|
|
516
|
+
return;
|
|
517
|
+
}
|
|
518
|
+
const assetRelPath = assetData.assetUrl.slice(1);
|
|
519
|
+
const assetFrom = path3.join(distDir, "client", assetRelPath);
|
|
520
|
+
const assetTo = path3.join(buildDir, assetRelPath);
|
|
521
|
+
if (!await fileExists(assetFrom)) {
|
|
522
|
+
console.log(`${assetFrom} does not exist`);
|
|
523
|
+
return;
|
|
524
|
+
}
|
|
525
|
+
await fsExtra.copy(assetFrom, assetTo);
|
|
526
|
+
printFileOutput(fileSize(assetTo), "dist/html/", assetRelPath);
|
|
527
|
+
})
|
|
528
|
+
);
|
|
529
|
+
if (!ssrOnly) {
|
|
530
|
+
const render = await import(path3.join(distDir, "server/render.js"));
|
|
531
|
+
const renderer = new render.Renderer(rootConfig, { assetMap, elementGraph });
|
|
532
|
+
const sitemap = await renderer.getSitemap();
|
|
533
|
+
console.log("\nhtml output:");
|
|
534
|
+
await Promise.all(
|
|
535
|
+
Object.keys(sitemap).map(async (urlPath) => {
|
|
536
|
+
const { route, params } = sitemap[urlPath];
|
|
537
|
+
const data = await renderer.renderRoute(route, {
|
|
538
|
+
routeParams: params
|
|
539
|
+
});
|
|
540
|
+
if (data.notFound) {
|
|
541
|
+
return;
|
|
542
|
+
}
|
|
543
|
+
let outFilePath = path3.join(urlPath.slice(1), "index.html");
|
|
544
|
+
if (outFilePath.endsWith("404/index.html")) {
|
|
545
|
+
outFilePath = outFilePath.replace("404/index.html", "404.html");
|
|
546
|
+
}
|
|
547
|
+
const outPath = path3.join(buildDir, outFilePath);
|
|
548
|
+
let html = data.html || "";
|
|
549
|
+
if (rootConfig.prettyHtml !== false) {
|
|
550
|
+
html = await htmlPretty(html, rootConfig.prettyHtmlOptions);
|
|
551
|
+
}
|
|
552
|
+
if (rootConfig.minifyHtml !== false) {
|
|
553
|
+
html = await htmlMinify(html, rootConfig.minifyHtmlOptions);
|
|
554
|
+
}
|
|
555
|
+
await writeFile(outPath, html);
|
|
556
|
+
printFileOutput(fileSize(outPath), "dist/html/", outFilePath);
|
|
557
|
+
})
|
|
558
|
+
);
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
function isRouteFile(filepath) {
|
|
562
|
+
return filepath.startsWith("routes") && isJsFile(filepath);
|
|
563
|
+
}
|
|
564
|
+
function fileSize(filepath) {
|
|
565
|
+
const stats = fsExtra.statSync(filepath);
|
|
566
|
+
const bytes = stats.size;
|
|
567
|
+
const k = 1024;
|
|
568
|
+
if (bytes < k) {
|
|
569
|
+
return (bytes / k).toFixed(2) + " kB";
|
|
570
|
+
}
|
|
571
|
+
const units = ["B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
|
|
572
|
+
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
573
|
+
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + " " + units[i];
|
|
574
|
+
}
|
|
575
|
+
function printFileOutput(fileSize2, outputDir, outputFile) {
|
|
576
|
+
const indent = " ".repeat(2);
|
|
577
|
+
const paddedSize = fileSize2.padStart(9, " ");
|
|
578
|
+
console.log(
|
|
579
|
+
`${indent}${dim(paddedSize)} ${dim(outputDir)}${cyan(outputFile)}`
|
|
580
|
+
);
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
// src/cli/commands/dev.ts
|
|
584
|
+
import path5 from "node:path";
|
|
585
|
+
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
586
|
+
import { default as express } from "express";
|
|
587
|
+
import { dim as dim2 } from "kleur/colors";
|
|
588
|
+
import glob3 from "tiny-glob";
|
|
589
|
+
|
|
590
|
+
// src/core/middleware.ts
|
|
591
|
+
function rootProjectMiddleware(options) {
|
|
592
|
+
return (req, _, next) => {
|
|
593
|
+
req.rootConfig = options.rootConfig;
|
|
594
|
+
next();
|
|
595
|
+
};
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
// src/render/asset-map/dev-asset-map.ts
|
|
599
|
+
import path4 from "node:path";
|
|
600
|
+
import { searchForWorkspaceRoot as searchForWorkspaceRoot2 } from "vite";
|
|
601
|
+
var DevServerAssetMap = class {
|
|
602
|
+
constructor(rootConfig, moduleGraph) {
|
|
603
|
+
this.rootConfig = rootConfig;
|
|
604
|
+
this.moduleGraph = moduleGraph;
|
|
605
|
+
}
|
|
606
|
+
async get(src) {
|
|
607
|
+
const file = path4.resolve(this.rootConfig.rootDir, src);
|
|
608
|
+
const viteModules = this.moduleGraph.getModulesByFile(file);
|
|
609
|
+
if (viteModules && viteModules.size > 0) {
|
|
610
|
+
const [viteModule] = viteModules;
|
|
611
|
+
return new DevServerAsset(src, {
|
|
612
|
+
assetMap: this,
|
|
613
|
+
viteModule
|
|
614
|
+
});
|
|
615
|
+
}
|
|
616
|
+
if (file.startsWith(this.rootConfig.rootDir)) {
|
|
617
|
+
const assetUrl = file.slice(this.rootConfig.rootDir.length);
|
|
618
|
+
return {
|
|
619
|
+
src,
|
|
620
|
+
assetUrl,
|
|
621
|
+
getCssDeps: async () => [],
|
|
622
|
+
getJsDeps: async () => [assetUrl]
|
|
623
|
+
};
|
|
624
|
+
}
|
|
625
|
+
const workspaceRoot = searchForWorkspaceRoot2(this.rootConfig.rootDir);
|
|
626
|
+
if (await directoryContains(workspaceRoot, file)) {
|
|
627
|
+
const assetUrl = `/@fs/${file}`;
|
|
628
|
+
return {
|
|
629
|
+
src,
|
|
630
|
+
assetUrl,
|
|
631
|
+
getCssDeps: async () => [],
|
|
632
|
+
getJsDeps: async () => [assetUrl]
|
|
633
|
+
};
|
|
634
|
+
}
|
|
635
|
+
console.log(`could not find asset in asset map: ${src}`);
|
|
636
|
+
return null;
|
|
637
|
+
}
|
|
638
|
+
filePathToSrc(file) {
|
|
639
|
+
return path4.relative(this.rootConfig.rootDir, file);
|
|
640
|
+
}
|
|
641
|
+
};
|
|
642
|
+
var DevServerAsset = class {
|
|
643
|
+
constructor(src, options) {
|
|
644
|
+
this.src = src;
|
|
645
|
+
this.assetMap = options.assetMap;
|
|
646
|
+
this.viteModule = options.viteModule;
|
|
647
|
+
this.moduleId = this.viteModule.id;
|
|
648
|
+
this.assetUrl = this.viteModule.url;
|
|
649
|
+
}
|
|
650
|
+
async getCssDeps() {
|
|
651
|
+
const visited = /* @__PURE__ */ new Set();
|
|
652
|
+
const deps = /* @__PURE__ */ new Set();
|
|
653
|
+
this.collectCss(this, deps, visited);
|
|
654
|
+
return Array.from(deps);
|
|
655
|
+
}
|
|
656
|
+
async getJsDeps() {
|
|
657
|
+
const visited = /* @__PURE__ */ new Set();
|
|
658
|
+
const deps = /* @__PURE__ */ new Set();
|
|
659
|
+
this.collectJs(this, deps, visited);
|
|
660
|
+
return Array.from(deps);
|
|
661
|
+
}
|
|
662
|
+
getImportedModules() {
|
|
663
|
+
return this.viteModule.importedModules;
|
|
664
|
+
}
|
|
665
|
+
collectJs(asset, urls, visited) {
|
|
666
|
+
if (!asset) {
|
|
667
|
+
return;
|
|
668
|
+
}
|
|
669
|
+
if (!asset.moduleId) {
|
|
670
|
+
return;
|
|
671
|
+
}
|
|
672
|
+
if (visited.has(asset.moduleId)) {
|
|
673
|
+
return;
|
|
674
|
+
}
|
|
675
|
+
visited.add(asset.moduleId);
|
|
676
|
+
const parts = path4.parse(asset.assetUrl);
|
|
677
|
+
if ([".js", ".jsx", ".ts", ".tsx"].includes(parts.ext) && asset.moduleId.includes("/elements/")) {
|
|
678
|
+
urls.add(asset.assetUrl);
|
|
679
|
+
}
|
|
680
|
+
asset.getImportedModules().forEach((viteModule) => {
|
|
681
|
+
if (viteModule.file) {
|
|
682
|
+
const src = this.assetMap.filePathToSrc(viteModule.file);
|
|
683
|
+
const importedAsset = new DevServerAsset(src, {
|
|
684
|
+
assetMap: this.assetMap,
|
|
685
|
+
viteModule
|
|
686
|
+
});
|
|
687
|
+
this.collectJs(importedAsset, urls, visited);
|
|
688
|
+
}
|
|
689
|
+
});
|
|
690
|
+
}
|
|
691
|
+
collectCss(asset, urls, visited) {
|
|
692
|
+
if (!asset) {
|
|
693
|
+
return;
|
|
694
|
+
}
|
|
695
|
+
if (!asset.assetUrl) {
|
|
696
|
+
return;
|
|
697
|
+
}
|
|
698
|
+
if (visited.has(asset.assetUrl)) {
|
|
699
|
+
return;
|
|
700
|
+
}
|
|
701
|
+
visited.add(asset.assetUrl);
|
|
702
|
+
if (asset.src.endsWith(".scss")) {
|
|
703
|
+
const parts = path4.parse(asset.src);
|
|
704
|
+
if (!parts.name.startsWith("_")) {
|
|
705
|
+
urls.add(asset.assetUrl);
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
asset.getImportedModules().forEach((viteModule) => {
|
|
709
|
+
if (viteModule.file) {
|
|
710
|
+
const src = this.assetMap.filePathToSrc(viteModule.file);
|
|
711
|
+
const importedAsset = new DevServerAsset(src, {
|
|
712
|
+
assetMap: this.assetMap,
|
|
713
|
+
viteModule
|
|
714
|
+
});
|
|
715
|
+
this.collectCss(importedAsset, urls, visited);
|
|
804
716
|
}
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
717
|
+
});
|
|
718
|
+
}
|
|
719
|
+
};
|
|
720
|
+
|
|
721
|
+
// src/utils/ports.ts
|
|
722
|
+
import { createServer } from "node:net";
|
|
723
|
+
function isPortOpen(port) {
|
|
724
|
+
return new Promise((resolve, reject) => {
|
|
725
|
+
const server = createServer();
|
|
726
|
+
server.on("error", (err) => {
|
|
727
|
+
if (err.code === "EADDRINUSE") {
|
|
728
|
+
resolve(false);
|
|
810
729
|
return;
|
|
811
730
|
}
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
Object.keys(sitemap).map(async (urlPath) => {
|
|
823
|
-
const { route, params } = sitemap[urlPath];
|
|
824
|
-
const data = await renderer.renderRoute(route, {
|
|
825
|
-
routeParams: params
|
|
826
|
-
});
|
|
827
|
-
if (data.notFound) {
|
|
828
|
-
return;
|
|
829
|
-
}
|
|
830
|
-
let outFilePath = path5.join(urlPath.slice(1), "index.html");
|
|
831
|
-
if (outFilePath.endsWith("404/index.html")) {
|
|
832
|
-
outFilePath = outFilePath.replace("404/index.html", "404.html");
|
|
833
|
-
}
|
|
834
|
-
const outPath = path5.join(buildDir, outFilePath);
|
|
835
|
-
let html = data.html || "";
|
|
836
|
-
if (rootConfig.prettyHtml !== false) {
|
|
837
|
-
html = await htmlPretty(html, rootConfig.prettyHtmlOptions);
|
|
838
|
-
}
|
|
839
|
-
if (rootConfig.minifyHtml !== false) {
|
|
840
|
-
html = await htmlMinify(html, rootConfig.minifyHtmlOptions);
|
|
731
|
+
reject(err);
|
|
732
|
+
});
|
|
733
|
+
server.on("close", () => {
|
|
734
|
+
resolve(true);
|
|
735
|
+
});
|
|
736
|
+
server.listen(port, () => {
|
|
737
|
+
server.close((err) => {
|
|
738
|
+
if (err) {
|
|
739
|
+
console.log(`error closing server: ${err}`);
|
|
740
|
+
reject(err);
|
|
841
741
|
}
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
742
|
+
});
|
|
743
|
+
});
|
|
744
|
+
});
|
|
745
|
+
}
|
|
746
|
+
async function findOpenPort(min, max) {
|
|
747
|
+
let port = min;
|
|
748
|
+
while (port <= max) {
|
|
749
|
+
const isOpen = await isPortOpen(port);
|
|
750
|
+
if (isOpen) {
|
|
751
|
+
return port;
|
|
752
|
+
}
|
|
753
|
+
port += 1;
|
|
846
754
|
}
|
|
755
|
+
throw new Error(`no ports open between ${min} and ${max}`);
|
|
847
756
|
}
|
|
848
|
-
|
|
849
|
-
|
|
757
|
+
|
|
758
|
+
// src/cli/commands/dev.ts
|
|
759
|
+
var __dirname2 = path5.dirname(fileURLToPath2(import.meta.url));
|
|
760
|
+
async function dev(rootProjectDir, options) {
|
|
761
|
+
process.env.NODE_ENV = "development";
|
|
762
|
+
const rootDir = path5.resolve(rootProjectDir || process.cwd());
|
|
763
|
+
const defaultPort = parseInt(process.env.PORT || "4007");
|
|
764
|
+
const host = (options == null ? void 0 : options.host) || "localhost";
|
|
765
|
+
const port = await findOpenPort(defaultPort, defaultPort + 10);
|
|
766
|
+
console.log();
|
|
767
|
+
console.log(`${dim2("\u2503")} project: ${rootDir}`);
|
|
768
|
+
console.log(`${dim2("\u2503")} server: http://${host}:${port}`);
|
|
769
|
+
console.log(`${dim2("\u2503")} mode: development`);
|
|
770
|
+
console.log();
|
|
771
|
+
const server = await createDevServer({ rootDir, port });
|
|
772
|
+
server.listen(port, host);
|
|
850
773
|
}
|
|
851
|
-
function
|
|
852
|
-
const
|
|
853
|
-
const
|
|
854
|
-
const
|
|
855
|
-
|
|
856
|
-
|
|
774
|
+
async function createDevServer(options) {
|
|
775
|
+
const rootDir = path5.resolve((options == null ? void 0 : options.rootDir) || process.cwd());
|
|
776
|
+
const rootConfig = await loadRootConfig(rootDir, { command: "dev" });
|
|
777
|
+
const port = options == null ? void 0 : options.port;
|
|
778
|
+
const server = express();
|
|
779
|
+
server.disable("x-powered-by");
|
|
780
|
+
server.use(rootProjectMiddleware({ rootConfig }));
|
|
781
|
+
server.use(await viteServerMiddleware({ rootConfig, port }));
|
|
782
|
+
const plugins = rootConfig.plugins || [];
|
|
783
|
+
await configureServerPlugins(
|
|
784
|
+
server,
|
|
785
|
+
async () => {
|
|
786
|
+
var _a;
|
|
787
|
+
const userMiddlewares = ((_a = rootConfig.server) == null ? void 0 : _a.middlewares) || [];
|
|
788
|
+
for (const middleware of userMiddlewares) {
|
|
789
|
+
server.use(middleware);
|
|
790
|
+
}
|
|
791
|
+
server.use(rootDevServerMiddleware());
|
|
792
|
+
server.use(rootDevServer404Middleware());
|
|
793
|
+
server.use(rootDevServer500Middleware());
|
|
794
|
+
},
|
|
795
|
+
plugins,
|
|
796
|
+
{ type: "dev", rootConfig }
|
|
797
|
+
);
|
|
798
|
+
return server;
|
|
799
|
+
}
|
|
800
|
+
async function viteServerMiddleware(options) {
|
|
801
|
+
const rootConfig = options.rootConfig;
|
|
802
|
+
const rootDir = rootConfig.rootDir;
|
|
803
|
+
const elementGraph = await getElements(rootConfig);
|
|
804
|
+
const elements = Object.values(elementGraph.sourceFiles).map((sourceFile) => {
|
|
805
|
+
return sourceFile.relPath;
|
|
806
|
+
});
|
|
807
|
+
const bundleScripts = [];
|
|
808
|
+
if (await isDirectory(path5.join(rootDir, "bundles"))) {
|
|
809
|
+
const bundleFiles = await glob3("bundles/*", { cwd: rootDir });
|
|
810
|
+
bundleFiles.forEach((file) => {
|
|
811
|
+
const parts = path5.parse(file);
|
|
812
|
+
if (isJsFile(parts.base)) {
|
|
813
|
+
bundleScripts.push(file);
|
|
814
|
+
}
|
|
815
|
+
});
|
|
857
816
|
}
|
|
858
|
-
const
|
|
859
|
-
const
|
|
860
|
-
|
|
817
|
+
const optimizeDeps = [...elements, ...bundleScripts];
|
|
818
|
+
const viteServer = await createViteServer(rootConfig, {
|
|
819
|
+
port: options.port,
|
|
820
|
+
optimizeDeps
|
|
821
|
+
});
|
|
822
|
+
return async (req, res, next) => {
|
|
823
|
+
try {
|
|
824
|
+
req.viteServer = viteServer;
|
|
825
|
+
const renderModulePath = path5.resolve(__dirname2, "./render.js");
|
|
826
|
+
const render = await viteServer.ssrLoadModule(
|
|
827
|
+
renderModulePath
|
|
828
|
+
);
|
|
829
|
+
const assetMap = new DevServerAssetMap(
|
|
830
|
+
rootConfig,
|
|
831
|
+
viteServer.moduleGraph
|
|
832
|
+
);
|
|
833
|
+
req.renderer = new render.Renderer(rootConfig, { assetMap, elementGraph });
|
|
834
|
+
viteServer.middlewares(req, res, next);
|
|
835
|
+
} catch (e) {
|
|
836
|
+
next(e);
|
|
837
|
+
}
|
|
838
|
+
};
|
|
861
839
|
}
|
|
862
|
-
function
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
840
|
+
function rootDevServerMiddleware() {
|
|
841
|
+
return async (req, res, next) => {
|
|
842
|
+
const renderer = req.renderer;
|
|
843
|
+
const viteServer = req.viteServer;
|
|
844
|
+
try {
|
|
845
|
+
await renderer.handle(req, res, next);
|
|
846
|
+
} catch (err) {
|
|
847
|
+
viteServer.ssrFixStacktrace(err);
|
|
848
|
+
next(err);
|
|
849
|
+
}
|
|
850
|
+
};
|
|
851
|
+
}
|
|
852
|
+
function rootDevServer404Middleware() {
|
|
853
|
+
return async (req, res) => {
|
|
854
|
+
console.error(`\u2753 404 ${req.originalUrl}`);
|
|
855
|
+
if (req.renderer) {
|
|
856
|
+
const url = req.path;
|
|
857
|
+
const ext = path5.extname(url);
|
|
858
|
+
if (!ext) {
|
|
859
|
+
const renderer = req.renderer;
|
|
860
|
+
const data = await renderer.renderDevServer404(req);
|
|
861
|
+
const html = data.html || "";
|
|
862
|
+
res.status(404).set({ "Content-Type": "text/html" }).end(html);
|
|
863
|
+
return;
|
|
864
|
+
}
|
|
865
|
+
}
|
|
866
|
+
res.status(404).set({ "Content-Type": "text/plain" }).end("404");
|
|
867
|
+
};
|
|
868
|
+
}
|
|
869
|
+
function rootDevServer500Middleware() {
|
|
870
|
+
return async (err, req, res, next) => {
|
|
871
|
+
console.error(`\u2757 500 ${req.originalUrl}`);
|
|
872
|
+
console.error(String(err.stack || err));
|
|
873
|
+
if (req.renderer) {
|
|
874
|
+
const url = req.path;
|
|
875
|
+
const ext = path5.extname(url);
|
|
876
|
+
if (!ext) {
|
|
877
|
+
const renderer = req.renderer;
|
|
878
|
+
const data = await renderer.renderDevServer500(req, err);
|
|
879
|
+
const html = data.html || "";
|
|
880
|
+
res.status(500).set({ "Content-Type": "text/html" }).end(html);
|
|
881
|
+
return;
|
|
882
|
+
}
|
|
883
|
+
}
|
|
884
|
+
next(err);
|
|
885
|
+
};
|
|
868
886
|
}
|
|
869
887
|
|
|
870
888
|
// src/cli/commands/preview.ts
|
|
871
889
|
import path6 from "node:path";
|
|
890
|
+
import compression from "compression";
|
|
872
891
|
import { default as express2 } from "express";
|
|
873
892
|
import { dim as dim3 } from "kleur/colors";
|
|
874
893
|
import sirv from "sirv";
|
|
875
|
-
|
|
876
|
-
async function preview(rootProjectDir) {
|
|
894
|
+
async function preview(rootProjectDir, options) {
|
|
877
895
|
process.env.NODE_ENV = "development";
|
|
878
896
|
const rootDir = path6.resolve(rootProjectDir || process.cwd());
|
|
879
|
-
const server = await
|
|
897
|
+
const server = await createPreviewServer({ rootDir });
|
|
880
898
|
const port = parseInt(process.env.PORT || "4007");
|
|
899
|
+
const host = (options == null ? void 0 : options.host) || "localhost";
|
|
881
900
|
console.log();
|
|
882
901
|
console.log(`${dim3("\u2503")} project: ${rootDir}`);
|
|
883
|
-
console.log(`${dim3("\u2503")} server: http
|
|
902
|
+
console.log(`${dim3("\u2503")} server: http://${host}:${port}`);
|
|
884
903
|
console.log(`${dim3("\u2503")} mode: preview`);
|
|
885
904
|
console.log();
|
|
886
|
-
server.listen(port);
|
|
905
|
+
server.listen(port, host);
|
|
887
906
|
}
|
|
888
|
-
async function
|
|
907
|
+
async function createPreviewServer(options) {
|
|
889
908
|
const rootDir = options.rootDir;
|
|
890
909
|
const rootConfig = await loadRootConfig(rootDir, { command: "preview" });
|
|
891
910
|
const distDir = path6.join(rootDir, "dist");
|
|
@@ -923,9 +942,19 @@ async function rootPreviewRendererMiddleware(options) {
|
|
|
923
942
|
`could not find ${manifestPath}. run \`root build\` before \`root preview\`.`
|
|
924
943
|
);
|
|
925
944
|
}
|
|
945
|
+
const elementGraphJsonPath = path6.join(
|
|
946
|
+
distDir,
|
|
947
|
+
"client/root-element-graph.json"
|
|
948
|
+
);
|
|
949
|
+
if (!await fileExists(elementGraphJsonPath)) {
|
|
950
|
+
throw new Error(
|
|
951
|
+
`could not find ${elementGraphJsonPath}. run \`root build\` before \`root start\`.`
|
|
952
|
+
);
|
|
953
|
+
}
|
|
926
954
|
const rootManifest = await loadJson(manifestPath);
|
|
927
955
|
const assetMap = BuildAssetMap.fromRootManifest(rootConfig, rootManifest);
|
|
928
|
-
const
|
|
956
|
+
const elementGraphJson = await loadJson(elementGraphJsonPath);
|
|
957
|
+
const elementGraph = ElementGraph.fromJson(elementGraphJson);
|
|
929
958
|
const renderer = new render.Renderer(rootConfig, { assetMap, elementGraph });
|
|
930
959
|
return async (req, _, next) => {
|
|
931
960
|
req.renderer = renderer;
|
|
@@ -939,6 +968,8 @@ function rootPreviewServerMiddleware() {
|
|
|
939
968
|
await renderer.handle(req, res, next);
|
|
940
969
|
} catch (e) {
|
|
941
970
|
try {
|
|
971
|
+
console.error(`error rendering ${req.originalUrl}`);
|
|
972
|
+
console.error(e.stack || e);
|
|
942
973
|
const { html } = await renderer.renderError(e);
|
|
943
974
|
res.status(500).set({ "Content-Type": "text/html" }).end(html);
|
|
944
975
|
} catch (e2) {
|
|
@@ -952,14 +983,16 @@ function rootPreviewServerMiddleware() {
|
|
|
952
983
|
function rootPreviewServer404Middleware() {
|
|
953
984
|
return async (req, res) => {
|
|
954
985
|
console.error(`\u2753 404 ${req.originalUrl}`);
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
986
|
+
if (req.renderer) {
|
|
987
|
+
const url = req.path;
|
|
988
|
+
const ext = path6.extname(url);
|
|
989
|
+
if (!ext) {
|
|
990
|
+
const renderer = req.renderer;
|
|
991
|
+
const data = await renderer.renderDevServer404(req);
|
|
992
|
+
const html = data.html || "";
|
|
993
|
+
res.status(404).set({ "Content-Type": "text/html" }).end(html);
|
|
994
|
+
return;
|
|
995
|
+
}
|
|
963
996
|
}
|
|
964
997
|
res.status(404).set({ "Content-Type": "text/plain" }).end("404");
|
|
965
998
|
};
|
|
@@ -968,14 +1001,16 @@ function rootPreviewServer500Middleware() {
|
|
|
968
1001
|
return async (err, req, res, next) => {
|
|
969
1002
|
console.error(`\u2757 500 ${req.originalUrl}`);
|
|
970
1003
|
console.error(String(err.stack || err));
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
1004
|
+
if (req.renderer) {
|
|
1005
|
+
const url = req.path;
|
|
1006
|
+
const ext = path6.extname(url);
|
|
1007
|
+
if (!ext) {
|
|
1008
|
+
const renderer = req.renderer;
|
|
1009
|
+
const data = await renderer.renderDevServer500(req, err);
|
|
1010
|
+
const html = data.html || "";
|
|
1011
|
+
res.status(500).set({ "Content-Type": "text/html" }).end(html);
|
|
1012
|
+
return;
|
|
1013
|
+
}
|
|
979
1014
|
}
|
|
980
1015
|
next(err);
|
|
981
1016
|
};
|
|
@@ -983,23 +1018,24 @@ function rootPreviewServer500Middleware() {
|
|
|
983
1018
|
|
|
984
1019
|
// src/cli/commands/start.ts
|
|
985
1020
|
import path7 from "node:path";
|
|
1021
|
+
import compression2 from "compression";
|
|
986
1022
|
import { default as express3 } from "express";
|
|
987
1023
|
import { dim as dim4 } from "kleur/colors";
|
|
988
1024
|
import sirv2 from "sirv";
|
|
989
|
-
|
|
990
|
-
async function start(rootProjectDir) {
|
|
1025
|
+
async function start(rootProjectDir, options) {
|
|
991
1026
|
process.env.NODE_ENV = "production";
|
|
992
1027
|
const rootDir = path7.resolve(rootProjectDir || process.cwd());
|
|
993
|
-
const server = await
|
|
1028
|
+
const server = await createProdServer({ rootDir });
|
|
994
1029
|
const port = parseInt(process.env.PORT || "4007");
|
|
1030
|
+
const host = (options == null ? void 0 : options.host) || "localhost";
|
|
995
1031
|
console.log();
|
|
996
1032
|
console.log(`${dim4("\u2503")} project: ${rootDir}`);
|
|
997
|
-
console.log(`${dim4("\u2503")} server: http
|
|
1033
|
+
console.log(`${dim4("\u2503")} server: http://${host}:${port}`);
|
|
998
1034
|
console.log(`${dim4("\u2503")} mode: production`);
|
|
999
1035
|
console.log();
|
|
1000
|
-
server.listen(port);
|
|
1036
|
+
server.listen(port, host);
|
|
1001
1037
|
}
|
|
1002
|
-
async function
|
|
1038
|
+
async function createProdServer(options) {
|
|
1003
1039
|
const rootDir = options.rootDir;
|
|
1004
1040
|
const rootConfig = await loadRootConfig(rootDir, { command: "start" });
|
|
1005
1041
|
const distDir = path7.join(rootDir, "dist");
|
|
@@ -1037,9 +1073,19 @@ async function rootProdRendererMiddleware(options) {
|
|
|
1037
1073
|
`could not find ${manifestPath}. run \`root build\` before \`root start\`.`
|
|
1038
1074
|
);
|
|
1039
1075
|
}
|
|
1076
|
+
const elementGraphJsonPath = path7.join(
|
|
1077
|
+
distDir,
|
|
1078
|
+
"client/root-element-graph.json"
|
|
1079
|
+
);
|
|
1080
|
+
if (!await fileExists(elementGraphJsonPath)) {
|
|
1081
|
+
throw new Error(
|
|
1082
|
+
`could not find ${elementGraphJsonPath}. run \`root build\` before \`root start\`.`
|
|
1083
|
+
);
|
|
1084
|
+
}
|
|
1040
1085
|
const rootManifest = await loadJson(manifestPath);
|
|
1041
1086
|
const assetMap = BuildAssetMap.fromRootManifest(rootConfig, rootManifest);
|
|
1042
|
-
const
|
|
1087
|
+
const elementGraphJson = await loadJson(elementGraphJsonPath);
|
|
1088
|
+
const elementGraph = ElementGraph.fromJson(elementGraphJson);
|
|
1043
1089
|
const renderer = new render.Renderer(rootConfig, { assetMap, elementGraph });
|
|
1044
1090
|
return async (req, _, next) => {
|
|
1045
1091
|
req.renderer = renderer;
|
|
@@ -1053,6 +1099,8 @@ function rootProdServerMiddleware() {
|
|
|
1053
1099
|
await renderer.handle(req, res, next);
|
|
1054
1100
|
} catch (e) {
|
|
1055
1101
|
try {
|
|
1102
|
+
console.error(`error rendering ${req.originalUrl}`);
|
|
1103
|
+
console.error(e.stack || e);
|
|
1056
1104
|
const { html } = await renderer.renderError(e);
|
|
1057
1105
|
res.status(500).set({ "Content-Type": "text/html" }).end(html);
|
|
1058
1106
|
} catch (e2) {
|
|
@@ -1100,6 +1148,9 @@ function rootProdServer500Middleware() {
|
|
|
1100
1148
|
}
|
|
1101
1149
|
export {
|
|
1102
1150
|
build,
|
|
1151
|
+
createDevServer,
|
|
1152
|
+
createPreviewServer,
|
|
1153
|
+
createProdServer,
|
|
1103
1154
|
dev,
|
|
1104
1155
|
preview,
|
|
1105
1156
|
start
|