@blinkk/root 1.0.0-alpha.1 → 1.0.0-alpha.10
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 +34 -16
- package/dist/{chunk-4SVK7R4Z.js → chunk-ZV52A6YZ.js} +42 -22
- package/dist/chunk-ZV52A6YZ.js.map +1 -0
- package/dist/cli.d.ts +10 -4
- package/dist/cli.js +544 -199
- package/dist/cli.js.map +1 -1
- package/dist/config-8ddb0478.d.ts +81 -0
- package/dist/core.d.ts +7 -6
- package/dist/core.js +3 -3
- package/dist/core.js.map +1 -1
- package/dist/render.d.ts +9 -16
- package/dist/render.js +236 -86
- package/dist/render.js.map +1 -1
- package/package.json +14 -10
- package/dist/chunk-4SVK7R4Z.js.map +0 -1
- package/dist/config-5b8f6033.d.ts +0 -15
package/dist/cli.js
CHANGED
|
@@ -1,74 +1,165 @@
|
|
|
1
1
|
// src/cli/commands/dev.ts
|
|
2
|
-
import
|
|
2
|
+
import path4 from "node:path";
|
|
3
3
|
import { fileURLToPath } from "node:url";
|
|
4
4
|
import { default as express } from "express";
|
|
5
5
|
import { createServer as createViteServer } from "vite";
|
|
6
6
|
|
|
7
7
|
// src/render/vite-plugin-root.ts
|
|
8
|
-
import
|
|
8
|
+
import path2 from "path";
|
|
9
9
|
import glob from "tiny-glob";
|
|
10
|
-
|
|
10
|
+
|
|
11
|
+
// src/core/fsutils.ts
|
|
12
|
+
import { promises as fs } from "node:fs";
|
|
13
|
+
import path from "node:path";
|
|
14
|
+
import fsExtra from "fs-extra";
|
|
15
|
+
function isJsFile(filename) {
|
|
16
|
+
return !!filename.match(/\.(j|t)sx?$/);
|
|
17
|
+
}
|
|
18
|
+
async function writeFile(filepath, content) {
|
|
19
|
+
const dirPath = path.dirname(filepath);
|
|
20
|
+
await makeDir(dirPath);
|
|
21
|
+
await fs.writeFile(filepath, content);
|
|
22
|
+
}
|
|
23
|
+
async function makeDir(dirpath) {
|
|
24
|
+
try {
|
|
25
|
+
await fs.access(dirpath);
|
|
26
|
+
} catch (e) {
|
|
27
|
+
await fs.mkdir(dirpath, { recursive: true });
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
async function copyDir(srcdir, dstdir) {
|
|
31
|
+
if (!fsExtra.existsSync(srcdir)) {
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
fsExtra.copySync(srcdir, dstdir, { recursive: true, overwrite: true });
|
|
35
|
+
}
|
|
36
|
+
async function rmDir(dirpath) {
|
|
37
|
+
await fs.rm(dirpath, { recursive: true, force: true });
|
|
38
|
+
}
|
|
39
|
+
async function loadJson(filepath) {
|
|
40
|
+
const content = await fs.readFile(filepath, "utf-8");
|
|
41
|
+
return JSON.parse(content);
|
|
42
|
+
}
|
|
43
|
+
async function isDirectory(dirpath) {
|
|
44
|
+
return fs.stat(dirpath).then((fsStat) => {
|
|
45
|
+
return fsStat.isDirectory();
|
|
46
|
+
}).catch((err) => {
|
|
47
|
+
if (err.code === "ENOENT") {
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
throw err;
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
function fileExists(filepath) {
|
|
54
|
+
return fs.access(filepath).then(() => true).catch(() => false);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// src/render/vite-plugin-root.ts
|
|
58
|
+
var JSX_ELEMENTS_REGEX = /jsxs?\("(\w[\w-]+\w)"/g;
|
|
59
|
+
var HTML_ELEMENTS_REGEX = /<(\w[\w-]+\w)/g;
|
|
11
60
|
function pluginRoot(options) {
|
|
61
|
+
var _a, _b;
|
|
62
|
+
const elementsVirtualId = "virtual:root-elements";
|
|
63
|
+
const resolvedElementsVirtualId = "\0" + elementsVirtualId;
|
|
12
64
|
const rootDir = (options == null ? void 0 : options.rootDir) || process.cwd();
|
|
13
|
-
|
|
14
|
-
|
|
65
|
+
const rootConfig = (options == null ? void 0 : options.rootConfig) || {};
|
|
66
|
+
const elementsDirs = [path2.join(rootDir, "elements")];
|
|
67
|
+
const includeDirs = ((_a = rootConfig.elements) == null ? void 0 : _a.include) || [];
|
|
68
|
+
includeDirs.forEach((dirPath) => {
|
|
69
|
+
const elementsDir = path2.resolve(rootDir, dirPath);
|
|
70
|
+
if (!elementsDir.startsWith(rootDir)) {
|
|
71
|
+
throw new Error(
|
|
72
|
+
`the elements dir (${dirPath}) should be relative to the project's root dir (${rootDir})`
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
elementsDirs.push(elementsDir);
|
|
76
|
+
});
|
|
77
|
+
const excludePatterns = ((_b = rootConfig.elements) == null ? void 0 : _b.exclude) || [];
|
|
78
|
+
const excludeElement = (moduleId) => {
|
|
79
|
+
return excludePatterns.some((pattern) => Boolean(moduleId.match(pattern)));
|
|
80
|
+
};
|
|
15
81
|
let elementMap;
|
|
16
82
|
async function updateElementMap() {
|
|
17
83
|
elementMap = {};
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
84
|
+
await Promise.all(
|
|
85
|
+
elementsDirs.map(async (dirPath) => {
|
|
86
|
+
const dirExists = await isDirectory(dirPath);
|
|
87
|
+
if (!dirExists) {
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
const files = await glob("**/*", { cwd: dirPath });
|
|
91
|
+
files.forEach((file) => {
|
|
92
|
+
const parts = path2.parse(file);
|
|
93
|
+
if (isJsFile(parts.base)) {
|
|
94
|
+
const fullPath = path2.join(dirPath, file);
|
|
95
|
+
const moduleId = fullPath.slice(rootDir.length);
|
|
96
|
+
if (!excludeElement(moduleId)) {
|
|
97
|
+
elementMap[parts.name] = moduleId;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
})
|
|
102
|
+
);
|
|
25
103
|
}
|
|
26
|
-
async function getElementImport(
|
|
104
|
+
async function getElementImport(tagname) {
|
|
27
105
|
if (!elementMap) {
|
|
28
106
|
await updateElementMap();
|
|
29
107
|
}
|
|
30
|
-
if (
|
|
31
|
-
|
|
32
|
-
if (server && server.moduleGraph) {
|
|
33
|
-
const moduleSet = server.moduleGraph.getModulesByFile(filePath);
|
|
34
|
-
if (moduleSet && moduleSet.size > 0) {
|
|
35
|
-
const module = moduleSet.values().next().value;
|
|
36
|
-
return module.url;
|
|
37
|
-
}
|
|
38
|
-
}
|
|
108
|
+
if (tagname in elementMap) {
|
|
109
|
+
return elementMap[tagname];
|
|
39
110
|
}
|
|
40
111
|
return null;
|
|
41
112
|
}
|
|
113
|
+
function isCustomElement(id) {
|
|
114
|
+
if (!isJsFile(id)) {
|
|
115
|
+
return false;
|
|
116
|
+
}
|
|
117
|
+
return elementsDirs.some((elementsDir) => {
|
|
118
|
+
return id.startsWith(elementsDir);
|
|
119
|
+
});
|
|
120
|
+
}
|
|
42
121
|
return {
|
|
43
122
|
name: "vite-plugin-root",
|
|
44
|
-
|
|
45
|
-
|
|
123
|
+
resolveId(id) {
|
|
124
|
+
if (id === elementsVirtualId) {
|
|
125
|
+
return resolvedElementsVirtualId;
|
|
126
|
+
}
|
|
127
|
+
return null;
|
|
46
128
|
},
|
|
47
|
-
|
|
48
|
-
|
|
129
|
+
async load(id) {
|
|
130
|
+
if (id === resolvedElementsVirtualId) {
|
|
131
|
+
await updateElementMap();
|
|
132
|
+
return `export const elementsMap = ${JSON.stringify(elementMap)}`;
|
|
133
|
+
}
|
|
134
|
+
return null;
|
|
49
135
|
},
|
|
50
136
|
async transform(src, id) {
|
|
51
|
-
if (
|
|
52
|
-
const idParts =
|
|
137
|
+
if (isCustomElement(id)) {
|
|
138
|
+
const idParts = path2.parse(id);
|
|
53
139
|
const deps = /* @__PURE__ */ new Set();
|
|
54
|
-
const
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
140
|
+
const tagnames = [
|
|
141
|
+
...src.matchAll(JSX_ELEMENTS_REGEX),
|
|
142
|
+
...src.matchAll(HTML_ELEMENTS_REGEX)
|
|
143
|
+
];
|
|
144
|
+
for (const match of tagnames) {
|
|
145
|
+
const tagname = match[1];
|
|
146
|
+
if (!tagname.includes("-")) {
|
|
58
147
|
continue;
|
|
59
148
|
}
|
|
60
|
-
if (
|
|
149
|
+
if (tagname === idParts.name) {
|
|
61
150
|
continue;
|
|
62
151
|
}
|
|
63
|
-
deps.add(
|
|
152
|
+
deps.add(tagname);
|
|
64
153
|
}
|
|
65
154
|
const importUrls = [];
|
|
66
|
-
await Promise.all(
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
155
|
+
await Promise.all(
|
|
156
|
+
Array.from(deps).map(async (tagname) => {
|
|
157
|
+
const importUrl = await getElementImport(tagname);
|
|
158
|
+
if (importUrl) {
|
|
159
|
+
importUrls.push(importUrl);
|
|
160
|
+
}
|
|
161
|
+
})
|
|
162
|
+
);
|
|
72
163
|
if (importUrls.length > 0) {
|
|
73
164
|
const importLines = importUrls.map((url) => `import '${url}';`).join("\n");
|
|
74
165
|
const code = `${src}
|
|
@@ -80,16 +171,13 @@ ${importLines}
|
|
|
80
171
|
}
|
|
81
172
|
return null;
|
|
82
173
|
}
|
|
174
|
+
return null;
|
|
83
175
|
}
|
|
84
176
|
};
|
|
85
177
|
}
|
|
86
|
-
function isJsFile(file) {
|
|
87
|
-
return !!file.match(/\.(j|t)sx?$/);
|
|
88
|
-
}
|
|
89
|
-
var vite_plugin_root_default = pluginRoot;
|
|
90
178
|
|
|
91
179
|
// src/render/asset-map/dev-asset-map.ts
|
|
92
|
-
import
|
|
180
|
+
import path3 from "node:path";
|
|
93
181
|
var DevServerAssetMap = class {
|
|
94
182
|
constructor(moduleGraph) {
|
|
95
183
|
this.moduleGraph = moduleGraph;
|
|
@@ -97,7 +185,12 @@ var DevServerAssetMap = class {
|
|
|
97
185
|
async get(moduleId) {
|
|
98
186
|
const viteModule = await this.moduleGraph.getModuleByUrl(moduleId);
|
|
99
187
|
if (!viteModule || !viteModule.id) {
|
|
100
|
-
return
|
|
188
|
+
return {
|
|
189
|
+
moduleId,
|
|
190
|
+
assetUrl: moduleId,
|
|
191
|
+
getCssDeps: async () => [],
|
|
192
|
+
getJsDeps: async () => [moduleId]
|
|
193
|
+
};
|
|
101
194
|
}
|
|
102
195
|
return new DevServerAsset(this, viteModule);
|
|
103
196
|
}
|
|
@@ -135,7 +228,7 @@ var DevServerAsset = class {
|
|
|
135
228
|
return;
|
|
136
229
|
}
|
|
137
230
|
visited.add(asset.moduleId);
|
|
138
|
-
const parts =
|
|
231
|
+
const parts = path3.parse(asset.assetUrl);
|
|
139
232
|
if ([".js", ".jsx", ".ts", ".tsx"].includes(parts.ext) && asset.moduleId.includes("/elements/")) {
|
|
140
233
|
urls.add(asset.assetUrl);
|
|
141
234
|
}
|
|
@@ -158,7 +251,7 @@ var DevServerAsset = class {
|
|
|
158
251
|
}
|
|
159
252
|
visited.add(asset.assetUrl);
|
|
160
253
|
if (asset.moduleId.endsWith(".scss")) {
|
|
161
|
-
const parts =
|
|
254
|
+
const parts = path3.parse(asset.assetUrl);
|
|
162
255
|
if (!parts.name.startsWith("_")) {
|
|
163
256
|
urls.add(asset.assetUrl);
|
|
164
257
|
}
|
|
@@ -193,62 +286,141 @@ async function loadRootConfig(rootDir) {
|
|
|
193
286
|
// src/render/html-minify.ts
|
|
194
287
|
import { minify } from "html-minifier-terser";
|
|
195
288
|
async function htmlMinify(html) {
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
289
|
+
try {
|
|
290
|
+
const min = await minify(html, {
|
|
291
|
+
collapseWhitespace: true,
|
|
292
|
+
removeComments: true,
|
|
293
|
+
preserveLineBreaks: true
|
|
294
|
+
});
|
|
295
|
+
return min.trimStart();
|
|
296
|
+
} catch (e) {
|
|
297
|
+
console.error("failed to minify html:", e);
|
|
298
|
+
return html;
|
|
299
|
+
}
|
|
202
300
|
}
|
|
203
301
|
|
|
204
302
|
// src/cli/commands/dev.ts
|
|
205
|
-
|
|
303
|
+
import glob2 from "tiny-glob";
|
|
304
|
+
import { dim } from "kleur/colors";
|
|
305
|
+
var __dirname = path4.dirname(fileURLToPath(import.meta.url));
|
|
206
306
|
async function createServer(options) {
|
|
307
|
+
const rootDir = (options == null ? void 0 : options.rootDir) || process.cwd();
|
|
207
308
|
const app = express();
|
|
309
|
+
app.disable("x-powered-by");
|
|
208
310
|
app.use(express.static("public"));
|
|
209
|
-
const middlewares = await getMiddlewares({ rootDir
|
|
311
|
+
const middlewares = await getMiddlewares({ rootDir });
|
|
210
312
|
middlewares.forEach((middleware) => app.use(middleware));
|
|
211
313
|
const port = parseInt(process.env.PORT || "4007");
|
|
212
|
-
const version = process.env.npm_package_version || "dev";
|
|
213
|
-
console.log(`\u{1F333} Root.js v${version}`);
|
|
214
314
|
console.log();
|
|
215
|
-
console.log(
|
|
315
|
+
console.log(`${dim("\u2503")} project: ${rootDir}`);
|
|
316
|
+
console.log(`${dim("\u2503")} server: http://localhost:${port}`);
|
|
317
|
+
console.log();
|
|
216
318
|
app.listen(port);
|
|
217
319
|
}
|
|
218
320
|
async function getMiddlewares(options) {
|
|
219
|
-
|
|
321
|
+
var _a, _b, _c;
|
|
322
|
+
const rootDir = path4.resolve((options == null ? void 0 : options.rootDir) || process.cwd());
|
|
220
323
|
const rootConfig = await loadRootConfig(rootDir);
|
|
221
324
|
const viteConfig = rootConfig.vite || {};
|
|
222
|
-
const renderModulePath =
|
|
325
|
+
const renderModulePath = path4.resolve(__dirname, "./render.js");
|
|
326
|
+
const pages = [];
|
|
327
|
+
if (await isDirectory(path4.join(rootDir, "routes"))) {
|
|
328
|
+
const pageFiles = await glob2("routes/**/*", { cwd: rootDir });
|
|
329
|
+
pageFiles.forEach((file) => {
|
|
330
|
+
const parts = path4.parse(file);
|
|
331
|
+
if (!parts.name.startsWith("_") && isJsFile(parts.base)) {
|
|
332
|
+
pages.push(file);
|
|
333
|
+
}
|
|
334
|
+
});
|
|
335
|
+
}
|
|
336
|
+
const elementsDirs = [path4.join(rootDir, "elements")];
|
|
337
|
+
const elementsInclude = ((_a = rootConfig.elements) == null ? void 0 : _a.include) || [];
|
|
338
|
+
const excludePatterns = ((_b = rootConfig.elements) == null ? void 0 : _b.exclude) || [];
|
|
339
|
+
const excludeElement = (moduleId) => {
|
|
340
|
+
return excludePatterns.some((pattern) => Boolean(moduleId.match(pattern)));
|
|
341
|
+
};
|
|
342
|
+
for (const dirPath of elementsInclude) {
|
|
343
|
+
const elementsDir = path4.resolve(rootDir, dirPath);
|
|
344
|
+
if (!elementsDir.startsWith(rootDir)) {
|
|
345
|
+
throw new Error(
|
|
346
|
+
`the elements dir (${dirPath}) should be relative to the project's root dir (${rootDir})`
|
|
347
|
+
);
|
|
348
|
+
}
|
|
349
|
+
elementsDirs.push(elementsDir);
|
|
350
|
+
}
|
|
351
|
+
const elements = [];
|
|
352
|
+
for (const dirPath of elementsDirs) {
|
|
353
|
+
if (await isDirectory(dirPath)) {
|
|
354
|
+
const elementFiles = await glob2("**/*", { cwd: dirPath });
|
|
355
|
+
elementFiles.forEach((file) => {
|
|
356
|
+
const parts = path4.parse(file);
|
|
357
|
+
if (isJsFile(parts.base)) {
|
|
358
|
+
const fullPath = path4.join(dirPath, file);
|
|
359
|
+
const moduleId = fullPath.slice(rootDir.length);
|
|
360
|
+
if (!excludeElement(moduleId)) {
|
|
361
|
+
elements.push(moduleId.slice(1));
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
});
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
const bundleScripts = [];
|
|
368
|
+
if (await isDirectory(path4.join(rootDir, "bundles"))) {
|
|
369
|
+
const bundleFiles = await glob2(path4.join(rootDir, "bundles/*"));
|
|
370
|
+
bundleFiles.forEach((file) => {
|
|
371
|
+
const parts = path4.parse(file);
|
|
372
|
+
if (isJsFile(parts.base)) {
|
|
373
|
+
bundleScripts.push(file);
|
|
374
|
+
}
|
|
375
|
+
});
|
|
376
|
+
}
|
|
223
377
|
const viteServer = await createViteServer({
|
|
224
378
|
...viteConfig,
|
|
379
|
+
mode: "development",
|
|
380
|
+
root: rootDir,
|
|
225
381
|
server: { middlewareMode: true },
|
|
226
382
|
appType: "custom",
|
|
227
383
|
optimizeDeps: {
|
|
228
|
-
include: [
|
|
384
|
+
include: [...pages, ...elements, ...bundleScripts]
|
|
385
|
+
},
|
|
386
|
+
ssr: {
|
|
387
|
+
noExternal: ["@blinkk/root"]
|
|
229
388
|
},
|
|
230
389
|
esbuild: {
|
|
231
390
|
jsx: "automatic",
|
|
232
391
|
jsxImportSource: "preact"
|
|
233
392
|
},
|
|
234
|
-
plugins: [...viteConfig.plugins || [],
|
|
393
|
+
plugins: [...viteConfig.plugins || [], pluginRoot({ rootDir, rootConfig })]
|
|
235
394
|
});
|
|
236
395
|
const rootMiddleware = async (req, res, next) => {
|
|
237
396
|
const url = req.originalUrl;
|
|
238
|
-
|
|
239
|
-
const renderer = new render.Renderer(rootConfig);
|
|
397
|
+
let renderer = null;
|
|
240
398
|
try {
|
|
399
|
+
const render = await viteServer.ssrLoadModule(renderModulePath);
|
|
400
|
+
renderer = new render.Renderer(rootConfig);
|
|
241
401
|
const assetMap = new DevServerAssetMap(viteServer.moduleGraph);
|
|
242
402
|
const data = await renderer.render(url, {
|
|
243
403
|
assetMap
|
|
244
404
|
});
|
|
245
|
-
|
|
405
|
+
if (data.notFound || !data.html) {
|
|
406
|
+
next();
|
|
407
|
+
return;
|
|
408
|
+
}
|
|
409
|
+
let html = await viteServer.transformIndexHtml(url, data.html || "");
|
|
410
|
+
if (rootConfig.minifyHtml !== false) {
|
|
411
|
+
html = await htmlMinify(html);
|
|
412
|
+
}
|
|
246
413
|
res.status(200).set({ "Content-Type": "text/html" }).end(html);
|
|
247
414
|
} catch (e) {
|
|
248
415
|
viteServer.ssrFixStacktrace(e);
|
|
416
|
+
console.error(e);
|
|
249
417
|
try {
|
|
250
|
-
|
|
251
|
-
|
|
418
|
+
if (renderer) {
|
|
419
|
+
const { html } = await renderer.renderError(e);
|
|
420
|
+
res.status(500).set({ "Content-Type": "text/html" }).end(html);
|
|
421
|
+
} else {
|
|
422
|
+
next(e);
|
|
423
|
+
}
|
|
252
424
|
} catch (e2) {
|
|
253
425
|
console.error("failed to render custom error");
|
|
254
426
|
console.error(e2);
|
|
@@ -256,33 +428,55 @@ async function getMiddlewares(options) {
|
|
|
256
428
|
}
|
|
257
429
|
}
|
|
258
430
|
};
|
|
259
|
-
|
|
431
|
+
const notFoundMiddleware = async (req, res) => {
|
|
432
|
+
const url = req.originalUrl;
|
|
433
|
+
const ext = path4.extname(url);
|
|
434
|
+
if (!ext) {
|
|
435
|
+
const render = await viteServer.ssrLoadModule(renderModulePath);
|
|
436
|
+
const renderer = new render.Renderer(rootConfig);
|
|
437
|
+
const data = await renderer.renderDevNotFound();
|
|
438
|
+
const html = data.html || "";
|
|
439
|
+
res.status(404).set({ "Content-Type": "text/html" }).end(html);
|
|
440
|
+
return;
|
|
441
|
+
}
|
|
442
|
+
res.status(404).set({ "Content-Type": "text/plain" }).end("404");
|
|
443
|
+
};
|
|
444
|
+
const userMiddlewares = ((_c = rootConfig.server) == null ? void 0 : _c.middlewares) || [];
|
|
445
|
+
return [
|
|
446
|
+
...userMiddlewares,
|
|
447
|
+
viteServer.middlewares,
|
|
448
|
+
rootMiddleware,
|
|
449
|
+
notFoundMiddleware
|
|
450
|
+
];
|
|
260
451
|
}
|
|
261
|
-
function dev(
|
|
262
|
-
|
|
452
|
+
async function dev(rootProjectDir) {
|
|
453
|
+
process.env.NODE_ENV = "development";
|
|
454
|
+
const rootDir = path4.resolve(rootProjectDir || process.cwd());
|
|
455
|
+
try {
|
|
456
|
+
await createServer({ rootDir });
|
|
457
|
+
} catch (err) {
|
|
458
|
+
console.error("an error occurred");
|
|
459
|
+
}
|
|
263
460
|
}
|
|
264
461
|
|
|
265
462
|
// src/cli/commands/build.ts
|
|
266
|
-
import
|
|
463
|
+
import path5 from "node:path";
|
|
267
464
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
268
465
|
import fsExtra2 from "fs-extra";
|
|
269
|
-
import
|
|
466
|
+
import glob3 from "tiny-glob";
|
|
270
467
|
import { build as viteBuild } from "vite";
|
|
271
468
|
|
|
272
469
|
// src/render/asset-map/build-asset-map.ts
|
|
273
|
-
import path4 from "path";
|
|
274
470
|
var BuildAssetMap = class {
|
|
275
|
-
constructor(
|
|
276
|
-
this.manifest = manifest;
|
|
471
|
+
constructor() {
|
|
277
472
|
this.moduleIdToAsset = /* @__PURE__ */ new Map();
|
|
278
|
-
Object.keys(this.manifest).forEach((manifestKey) => {
|
|
279
|
-
const moduleId = `/${manifestKey}`;
|
|
280
|
-
this.moduleIdToAsset.set(moduleId, new BuildAsset(this, moduleId, this.manifest[manifestKey]));
|
|
281
|
-
});
|
|
282
473
|
}
|
|
283
474
|
async get(moduleId) {
|
|
284
475
|
return this.moduleIdToAsset.get(moduleId) || null;
|
|
285
476
|
}
|
|
477
|
+
add(asset) {
|
|
478
|
+
this.moduleIdToAsset.set(asset.moduleId, asset);
|
|
479
|
+
}
|
|
286
480
|
toJson() {
|
|
287
481
|
const result = {};
|
|
288
482
|
for (const moduleId of this.moduleIdToAsset.keys()) {
|
|
@@ -290,15 +484,46 @@ var BuildAssetMap = class {
|
|
|
290
484
|
}
|
|
291
485
|
return result;
|
|
292
486
|
}
|
|
487
|
+
static fromViteManifest(viteManifest, elementMap) {
|
|
488
|
+
const assetMap = new BuildAssetMap();
|
|
489
|
+
const elementModuleIds = /* @__PURE__ */ new Set();
|
|
490
|
+
Object.values(elementMap).forEach(
|
|
491
|
+
(moduleId) => elementModuleIds.add(moduleId)
|
|
492
|
+
);
|
|
493
|
+
Object.keys(viteManifest).forEach((manifestKey) => {
|
|
494
|
+
const moduleId = `/${manifestKey}`;
|
|
495
|
+
const manifestChunk = viteManifest[manifestKey];
|
|
496
|
+
const isElement = elementModuleIds.has(moduleId);
|
|
497
|
+
const assetData = {
|
|
498
|
+
moduleId,
|
|
499
|
+
assetUrl: `/${manifestChunk.file}`,
|
|
500
|
+
importedModules: (manifestChunk.imports || []).map(
|
|
501
|
+
(relPath) => `/${relPath}`
|
|
502
|
+
),
|
|
503
|
+
importedCss: (manifestChunk.css || []).map((relPath) => `/${relPath}`),
|
|
504
|
+
isElement
|
|
505
|
+
};
|
|
506
|
+
assetMap.add(new BuildAsset(assetMap, assetData));
|
|
507
|
+
});
|
|
508
|
+
return assetMap;
|
|
509
|
+
}
|
|
510
|
+
static fromRootManifest(rootManifest) {
|
|
511
|
+
const assetMap = new BuildAssetMap();
|
|
512
|
+
Object.keys(rootManifest).forEach((moduleId) => {
|
|
513
|
+
const assetData = rootManifest[moduleId];
|
|
514
|
+
assetMap.add(new BuildAsset(assetMap, assetData));
|
|
515
|
+
});
|
|
516
|
+
return assetMap;
|
|
517
|
+
}
|
|
293
518
|
};
|
|
294
519
|
var BuildAsset = class {
|
|
295
|
-
constructor(assetMap,
|
|
520
|
+
constructor(assetMap, assetData) {
|
|
296
521
|
this.assetMap = assetMap;
|
|
297
|
-
this.moduleId = moduleId;
|
|
298
|
-
this.
|
|
299
|
-
this.
|
|
300
|
-
this.
|
|
301
|
-
this.
|
|
522
|
+
this.moduleId = assetData.moduleId;
|
|
523
|
+
this.assetUrl = assetData.assetUrl;
|
|
524
|
+
this.importedModules = assetData.importedModules;
|
|
525
|
+
this.importedCss = assetData.importedCss;
|
|
526
|
+
this.isElement = assetData.isElement;
|
|
302
527
|
}
|
|
303
528
|
async getCssDeps() {
|
|
304
529
|
const visited = /* @__PURE__ */ new Set();
|
|
@@ -323,14 +548,15 @@ var BuildAsset = class {
|
|
|
323
548
|
return;
|
|
324
549
|
}
|
|
325
550
|
visited.add(asset.moduleId);
|
|
326
|
-
|
|
327
|
-
if ([".ts", ".tsx"].includes(parts.ext) && asset.moduleId.includes("/elements/")) {
|
|
551
|
+
if (asset.isElement) {
|
|
328
552
|
urls.add(asset.assetUrl);
|
|
329
553
|
}
|
|
330
|
-
await Promise.all(
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
554
|
+
await Promise.all(
|
|
555
|
+
asset.importedModules.map(async (moduleId) => {
|
|
556
|
+
const importedAsset = await this.assetMap.get(moduleId);
|
|
557
|
+
this.collectJs(importedAsset, urls, visited);
|
|
558
|
+
})
|
|
559
|
+
);
|
|
334
560
|
}
|
|
335
561
|
async collectCss(asset, urls, visited) {
|
|
336
562
|
if (!asset) {
|
|
@@ -346,102 +572,90 @@ var BuildAsset = class {
|
|
|
346
572
|
if (asset.importedCss) {
|
|
347
573
|
asset.importedCss.forEach((cssUrl) => urls.add(cssUrl));
|
|
348
574
|
}
|
|
349
|
-
await Promise.all(
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
575
|
+
await Promise.all(
|
|
576
|
+
asset.importedModules.map(async (moduleId) => {
|
|
577
|
+
const importedAsset = await this.assetMap.get(moduleId);
|
|
578
|
+
this.collectCss(importedAsset, urls, visited);
|
|
579
|
+
})
|
|
580
|
+
);
|
|
353
581
|
}
|
|
354
582
|
toJson() {
|
|
355
583
|
return {
|
|
356
584
|
moduleId: this.moduleId,
|
|
357
585
|
assetUrl: this.assetUrl,
|
|
358
586
|
importedModules: this.importedModules,
|
|
359
|
-
importedCss: this.importedCss
|
|
587
|
+
importedCss: this.importedCss,
|
|
588
|
+
isElement: this.isElement
|
|
360
589
|
};
|
|
361
590
|
}
|
|
362
591
|
};
|
|
363
592
|
|
|
364
|
-
// src/core/fsutils.ts
|
|
365
|
-
import { promises as fs } from "node:fs";
|
|
366
|
-
import path5 from "node:path";
|
|
367
|
-
import fsExtra from "fs-extra";
|
|
368
|
-
function isJsFile2(file) {
|
|
369
|
-
return !!file.match(/\.(j|t)sx?$/);
|
|
370
|
-
}
|
|
371
|
-
async function writeFile(filePath, content) {
|
|
372
|
-
const dirPath = path5.dirname(filePath);
|
|
373
|
-
await makeDir(dirPath);
|
|
374
|
-
await fs.writeFile(filePath, content);
|
|
375
|
-
}
|
|
376
|
-
async function makeDir(dirPath) {
|
|
377
|
-
try {
|
|
378
|
-
await fs.access(dirPath);
|
|
379
|
-
} catch (e) {
|
|
380
|
-
await fs.mkdir(dirPath, { recursive: true });
|
|
381
|
-
}
|
|
382
|
-
}
|
|
383
|
-
async function copyDir(srcDir, dstDir) {
|
|
384
|
-
if (!fsExtra.existsSync(srcDir)) {
|
|
385
|
-
return;
|
|
386
|
-
}
|
|
387
|
-
fsExtra.copySync(srcDir, dstDir, { recursive: true, overwrite: true });
|
|
388
|
-
}
|
|
389
|
-
async function rmDir(dirPath) {
|
|
390
|
-
await fs.rm(dirPath, { recursive: true, force: true });
|
|
391
|
-
}
|
|
392
|
-
async function loadJson(filePath) {
|
|
393
|
-
const content = await fs.readFile(filePath, "utf-8");
|
|
394
|
-
return JSON.parse(content);
|
|
395
|
-
}
|
|
396
|
-
async function isDirectory(dirPath) {
|
|
397
|
-
return fs.stat(dirPath).then((fsStat) => {
|
|
398
|
-
return fsStat.isDirectory();
|
|
399
|
-
}).catch((err) => {
|
|
400
|
-
if (err.code === "ENOENT") {
|
|
401
|
-
return false;
|
|
402
|
-
}
|
|
403
|
-
throw err;
|
|
404
|
-
});
|
|
405
|
-
}
|
|
406
|
-
|
|
407
593
|
// src/cli/commands/build.ts
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
rootDir = process.cwd();
|
|
414
|
-
}
|
|
594
|
+
import { dim as dim2 } from "kleur/colors";
|
|
595
|
+
var __dirname2 = path5.dirname(fileURLToPath2(import.meta.url));
|
|
596
|
+
async function build(rootProjectDir, options) {
|
|
597
|
+
var _a, _b;
|
|
598
|
+
const rootDir = path5.resolve(rootProjectDir || process.cwd());
|
|
415
599
|
const rootConfig = await loadRootConfig(rootDir);
|
|
416
|
-
const distDir =
|
|
600
|
+
const distDir = path5.join(rootDir, "dist");
|
|
601
|
+
const ssrOnly = (options == null ? void 0 : options.ssrOnly) || false;
|
|
602
|
+
const mode = (options == null ? void 0 : options.mode) || "production";
|
|
603
|
+
console.log();
|
|
604
|
+
console.log(`${dim2("\u2503")} project: ${rootDir}`);
|
|
605
|
+
console.log(`${dim2("\u2503")} output: ${distDir}/html`);
|
|
606
|
+
console.log(`${dim2("\u2503")} mode: ${mode}`);
|
|
607
|
+
console.log();
|
|
417
608
|
await rmDir(distDir);
|
|
418
609
|
await makeDir(distDir);
|
|
419
610
|
const pages = [];
|
|
420
|
-
if (await isDirectory(
|
|
421
|
-
const pageFiles = await
|
|
611
|
+
if (await isDirectory(path5.join(rootDir, "routes"))) {
|
|
612
|
+
const pageFiles = await glob3(path5.join(rootDir, "routes/**/*"));
|
|
422
613
|
pageFiles.forEach((file) => {
|
|
423
|
-
const parts =
|
|
424
|
-
if (!parts.name.startsWith("_") &&
|
|
614
|
+
const parts = path5.parse(file);
|
|
615
|
+
if (!parts.name.startsWith("_") && isJsFile(parts.base)) {
|
|
425
616
|
pages.push(file);
|
|
426
617
|
}
|
|
427
618
|
});
|
|
428
619
|
}
|
|
620
|
+
const elementsDirs = [path5.join(rootDir, "elements")];
|
|
621
|
+
const elementsInclude = ((_a = rootConfig.elements) == null ? void 0 : _a.include) || [];
|
|
622
|
+
const excludePatterns = ((_b = rootConfig.elements) == null ? void 0 : _b.exclude) || [];
|
|
623
|
+
const excludeElement = (moduleId) => {
|
|
624
|
+
return excludePatterns.some((pattern) => Boolean(moduleId.match(pattern)));
|
|
625
|
+
};
|
|
626
|
+
for (const dirPath of elementsInclude) {
|
|
627
|
+
const elementsDir = path5.resolve(rootDir, dirPath);
|
|
628
|
+
if (!elementsDir.startsWith(rootDir)) {
|
|
629
|
+
throw new Error(
|
|
630
|
+
`the elements dir (${dirPath}) should be relative to the project's root dir (${rootDir})`
|
|
631
|
+
);
|
|
632
|
+
}
|
|
633
|
+
elementsDirs.push(elementsDir);
|
|
634
|
+
}
|
|
429
635
|
const elements = [];
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
const
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
636
|
+
const elementMap = {};
|
|
637
|
+
for (const dirPath of elementsDirs) {
|
|
638
|
+
if (await isDirectory(dirPath)) {
|
|
639
|
+
const elementFiles = await glob3("**/*", { cwd: dirPath });
|
|
640
|
+
elementFiles.forEach((file) => {
|
|
641
|
+
const parts = path5.parse(file);
|
|
642
|
+
if (isJsFile(parts.base)) {
|
|
643
|
+
const fullPath = path5.join(dirPath, file);
|
|
644
|
+
const moduleId = fullPath.slice(rootDir.length);
|
|
645
|
+
if (!excludeElement(moduleId)) {
|
|
646
|
+
elements.push(fullPath);
|
|
647
|
+
elementMap[parts.name] = moduleId;
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
});
|
|
651
|
+
}
|
|
438
652
|
}
|
|
439
653
|
const bundleScripts = [];
|
|
440
|
-
if (await isDirectory(
|
|
441
|
-
const bundleFiles = await
|
|
654
|
+
if (await isDirectory(path5.join(rootDir, "bundles"))) {
|
|
655
|
+
const bundleFiles = await glob3(path5.join(rootDir, "bundles/*"));
|
|
442
656
|
bundleFiles.forEach((file) => {
|
|
443
|
-
const parts =
|
|
444
|
-
if (
|
|
657
|
+
const parts = path5.parse(file);
|
|
658
|
+
if (isJsFile(parts.base)) {
|
|
445
659
|
bundleScripts.push(file);
|
|
446
660
|
}
|
|
447
661
|
});
|
|
@@ -450,27 +664,27 @@ async function build(rootDir) {
|
|
|
450
664
|
const baseConfig = {
|
|
451
665
|
...viteConfig,
|
|
452
666
|
root: rootDir,
|
|
667
|
+
mode,
|
|
453
668
|
esbuild: {
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
669
|
+
jsx: "automatic",
|
|
670
|
+
jsxImportSource: "preact",
|
|
671
|
+
treeShaking: true
|
|
457
672
|
},
|
|
458
|
-
plugins: [...viteConfig.plugins || [], pluginRoot()]
|
|
673
|
+
plugins: [...viteConfig.plugins || [], pluginRoot({ rootDir, rootConfig })]
|
|
459
674
|
};
|
|
460
675
|
await viteBuild({
|
|
461
676
|
...baseConfig,
|
|
462
|
-
mode: "production",
|
|
463
677
|
publicDir: false,
|
|
464
678
|
build: {
|
|
465
679
|
rollupOptions: {
|
|
466
|
-
input: [
|
|
680
|
+
input: [path5.resolve(__dirname2, "./render.js")],
|
|
467
681
|
output: {
|
|
468
682
|
format: "esm",
|
|
469
683
|
chunkFileNames: "chunks/[name].[hash].js",
|
|
470
684
|
assetFileNames: "assets/[name].[hash][extname]"
|
|
471
685
|
}
|
|
472
686
|
},
|
|
473
|
-
outDir:
|
|
687
|
+
outDir: path5.join(distDir, "server"),
|
|
474
688
|
ssr: true,
|
|
475
689
|
ssrManifest: false,
|
|
476
690
|
cssCodeSplit: true,
|
|
@@ -478,11 +692,13 @@ async function build(rootDir) {
|
|
|
478
692
|
minify: false,
|
|
479
693
|
polyfillModulePreload: false,
|
|
480
694
|
reportCompressedSize: false
|
|
695
|
+
},
|
|
696
|
+
ssr: {
|
|
697
|
+
noExternal: ["@blinkk/root"]
|
|
481
698
|
}
|
|
482
699
|
});
|
|
483
700
|
await viteBuild({
|
|
484
701
|
...baseConfig,
|
|
485
|
-
mode: "production",
|
|
486
702
|
publicDir: false,
|
|
487
703
|
build: {
|
|
488
704
|
rollupOptions: {
|
|
@@ -493,7 +709,7 @@ async function build(rootDir) {
|
|
|
493
709
|
assetFileNames: "assets/[name].[hash][extname]"
|
|
494
710
|
}
|
|
495
711
|
},
|
|
496
|
-
outDir:
|
|
712
|
+
outDir: path5.join(distDir, "client"),
|
|
497
713
|
ssr: false,
|
|
498
714
|
ssrManifest: false,
|
|
499
715
|
manifest: true,
|
|
@@ -504,45 +720,174 @@ async function build(rootDir) {
|
|
|
504
720
|
reportCompressedSize: false
|
|
505
721
|
}
|
|
506
722
|
});
|
|
507
|
-
const
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
const
|
|
511
|
-
|
|
512
|
-
|
|
723
|
+
const viteManifest = await loadJson(
|
|
724
|
+
path5.join(distDir, "client/manifest.json")
|
|
725
|
+
);
|
|
726
|
+
const assetMap = BuildAssetMap.fromViteManifest(viteManifest, elementMap);
|
|
727
|
+
writeFile(
|
|
728
|
+
path5.join(distDir, "client/root-manifest.json"),
|
|
729
|
+
JSON.stringify(assetMap.toJson(), null, 2)
|
|
730
|
+
);
|
|
731
|
+
const buildDir = path5.join(distDir, "html");
|
|
732
|
+
const publicDir = path5.join(rootDir, "public");
|
|
733
|
+
if (fsExtra2.existsSync(path5.join(rootDir, "public"))) {
|
|
513
734
|
fsExtra2.copySync(publicDir, buildDir);
|
|
514
735
|
} else {
|
|
515
736
|
makeDir(buildDir);
|
|
516
737
|
}
|
|
517
|
-
copyDir(
|
|
518
|
-
copyDir(
|
|
738
|
+
copyDir(path5.join(distDir, "client/assets"), path5.join(buildDir, "assets"));
|
|
739
|
+
copyDir(path5.join(distDir, "client/chunks"), path5.join(buildDir, "chunks"));
|
|
740
|
+
if (!ssrOnly) {
|
|
741
|
+
const render = await import(path5.join(distDir, "server/render.js"));
|
|
742
|
+
const renderer = new render.Renderer(rootConfig);
|
|
743
|
+
const sitemap = await renderer.getSitemap();
|
|
744
|
+
await Promise.all(
|
|
745
|
+
Object.keys(sitemap).map(async (urlPath) => {
|
|
746
|
+
const { route, params } = sitemap[urlPath];
|
|
747
|
+
const data = await renderer.renderRoute(route, {
|
|
748
|
+
assetMap,
|
|
749
|
+
routeParams: params
|
|
750
|
+
});
|
|
751
|
+
let outPath = path5.join(distDir, `html${urlPath}`, "index.html");
|
|
752
|
+
if (outPath.endsWith("404/index.html")) {
|
|
753
|
+
outPath = outPath.replace("404/index.html", "404.html");
|
|
754
|
+
}
|
|
755
|
+
const html = await htmlMinify(data.html || "");
|
|
756
|
+
await writeFile(outPath, html);
|
|
757
|
+
const relPath = outPath.slice(path5.dirname(distDir).length + 1);
|
|
758
|
+
console.log(`saved ${relPath}`);
|
|
759
|
+
})
|
|
760
|
+
);
|
|
761
|
+
}
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
// src/cli/commands/preview.ts
|
|
765
|
+
import path6 from "node:path";
|
|
766
|
+
import { default as express2 } from "express";
|
|
767
|
+
import { dim as dim3 } from "kleur/colors";
|
|
768
|
+
async function preview(rootProjectDir) {
|
|
769
|
+
var _a;
|
|
770
|
+
process.env.NODE_ENV = "development";
|
|
771
|
+
const rootDir = path6.resolve(rootProjectDir || process.cwd());
|
|
772
|
+
const rootConfig = await loadRootConfig(rootDir);
|
|
773
|
+
const distDir = path6.join(rootDir, "dist");
|
|
519
774
|
const render = await import(path6.join(distDir, "server/render.js"));
|
|
520
775
|
const renderer = new render.Renderer(rootConfig);
|
|
521
|
-
const
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
776
|
+
const manifestPath = path6.join(distDir, "client/root-manifest.json");
|
|
777
|
+
if (!await fileExists(manifestPath)) {
|
|
778
|
+
throw new Error(
|
|
779
|
+
`could not find ${manifestPath}. run \`root build\` before \`root preview\`.`
|
|
780
|
+
);
|
|
781
|
+
}
|
|
782
|
+
const rootManifest = await loadJson(manifestPath);
|
|
783
|
+
const assetMap = BuildAssetMap.fromRootManifest(rootManifest);
|
|
784
|
+
const app = express2();
|
|
785
|
+
app.disable("x-powered-by");
|
|
786
|
+
const userMiddlewares = ((_a = rootConfig.server) == null ? void 0 : _a.middlewares) || [];
|
|
787
|
+
userMiddlewares.forEach((middleware) => {
|
|
788
|
+
app.use(middleware);
|
|
789
|
+
});
|
|
790
|
+
const publicDir = path6.join(distDir, "html");
|
|
791
|
+
app.use(express2.static(publicDir));
|
|
792
|
+
app.use(async (req, res, next) => {
|
|
793
|
+
try {
|
|
794
|
+
const url = req.originalUrl;
|
|
795
|
+
const data = await renderer.render(url, {
|
|
796
|
+
assetMap
|
|
797
|
+
});
|
|
798
|
+
if (data.notFound || !data.html) {
|
|
799
|
+
next();
|
|
800
|
+
return;
|
|
801
|
+
}
|
|
802
|
+
let html = data.html || "";
|
|
803
|
+
if (rootConfig.minifyHtml !== false) {
|
|
804
|
+
html = await htmlMinify(html);
|
|
805
|
+
}
|
|
806
|
+
res.status(200).set({ "Content-Type": "text/html" }).end(html);
|
|
807
|
+
} catch (e) {
|
|
808
|
+
try {
|
|
809
|
+
const { html } = await renderer.renderError(e);
|
|
810
|
+
res.status(500).set({ "Content-Type": "text/html" }).end(html);
|
|
811
|
+
} catch (e2) {
|
|
812
|
+
console.error("failed to render custom error");
|
|
813
|
+
console.error(e2);
|
|
814
|
+
next(e);
|
|
815
|
+
}
|
|
816
|
+
}
|
|
817
|
+
});
|
|
818
|
+
const port = parseInt(process.env.PORT || "4007");
|
|
819
|
+
console.log();
|
|
820
|
+
console.log(`${dim3("\u2503")} project: ${rootDir}`);
|
|
821
|
+
console.log(`${dim3("\u2503")} server: http://localhost:${port}`);
|
|
822
|
+
console.log();
|
|
823
|
+
app.listen(port);
|
|
537
824
|
}
|
|
538
825
|
|
|
539
826
|
// src/cli/commands/start.ts
|
|
540
|
-
|
|
541
|
-
|
|
827
|
+
import path7 from "node:path";
|
|
828
|
+
import { default as express3 } from "express";
|
|
829
|
+
import { dim as dim4 } from "kleur/colors";
|
|
830
|
+
async function start(rootProjectDir) {
|
|
831
|
+
var _a;
|
|
832
|
+
process.env.NODE_ENV = "production";
|
|
833
|
+
const rootDir = path7.resolve(rootProjectDir || process.cwd());
|
|
834
|
+
const rootConfig = await loadRootConfig(rootDir);
|
|
835
|
+
const distDir = path7.join(rootDir, "dist");
|
|
836
|
+
const render = await import(path7.join(distDir, "server/render.js"));
|
|
837
|
+
const renderer = new render.Renderer(rootConfig);
|
|
838
|
+
const manifestPath = path7.join(distDir, "client/root-manifest.json");
|
|
839
|
+
if (!await fileExists(manifestPath)) {
|
|
840
|
+
throw new Error(
|
|
841
|
+
`could not find ${manifestPath}. run \`root build\` before \`root start\`.`
|
|
842
|
+
);
|
|
843
|
+
}
|
|
844
|
+
const rootManifest = await loadJson(manifestPath);
|
|
845
|
+
const assetMap = BuildAssetMap.fromRootManifest(rootManifest);
|
|
846
|
+
const app = express3();
|
|
847
|
+
app.disable("x-powered-by");
|
|
848
|
+
const userMiddlewares = ((_a = rootConfig.server) == null ? void 0 : _a.middlewares) || [];
|
|
849
|
+
userMiddlewares.forEach((middleware) => {
|
|
850
|
+
app.use(middleware);
|
|
851
|
+
});
|
|
852
|
+
const publicDir = path7.join(distDir, "html");
|
|
853
|
+
app.use(express3.static(publicDir));
|
|
854
|
+
app.use(async (req, res, next) => {
|
|
855
|
+
try {
|
|
856
|
+
const url = req.originalUrl;
|
|
857
|
+
const data = await renderer.render(url, {
|
|
858
|
+
assetMap
|
|
859
|
+
});
|
|
860
|
+
if (data.notFound || !data.html) {
|
|
861
|
+
next();
|
|
862
|
+
return;
|
|
863
|
+
}
|
|
864
|
+
let html = data.html || "";
|
|
865
|
+
if (rootConfig.minifyHtml !== false) {
|
|
866
|
+
html = await htmlMinify(html);
|
|
867
|
+
}
|
|
868
|
+
res.status(200).set({ "Content-Type": "text/html" }).end(html);
|
|
869
|
+
} catch (e) {
|
|
870
|
+
try {
|
|
871
|
+
const { html } = await renderer.renderError(e);
|
|
872
|
+
res.status(500).set({ "Content-Type": "text/html" }).end(html);
|
|
873
|
+
} catch (e2) {
|
|
874
|
+
console.error("failed to render custom error");
|
|
875
|
+
console.error(e2);
|
|
876
|
+
next(e);
|
|
877
|
+
}
|
|
878
|
+
}
|
|
879
|
+
});
|
|
880
|
+
const port = parseInt(process.env.PORT || "4007");
|
|
881
|
+
console.log();
|
|
882
|
+
console.log(`${dim4("\u2503")} project: ${rootDir}`);
|
|
883
|
+
console.log(`${dim4("\u2503")} server: http://localhost:${port}`);
|
|
884
|
+
console.log();
|
|
885
|
+
app.listen(port);
|
|
542
886
|
}
|
|
543
887
|
export {
|
|
544
888
|
build,
|
|
545
889
|
dev,
|
|
890
|
+
preview,
|
|
546
891
|
start
|
|
547
892
|
};
|
|
548
893
|
//# sourceMappingURL=cli.js.map
|