@blinkk/root 1.0.0-alpha.1 → 1.0.0-alpha.11
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 +540 -199
- package/dist/cli.js.map +1 -1
- package/dist/config-ea7b8b9c.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 +238 -86
- package/dist/render.js.map +1 -1
- package/package.json +19 -22
- 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,51 @@ 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
|
+
await createServer({ rootDir });
|
|
263
456
|
}
|
|
264
457
|
|
|
265
458
|
// src/cli/commands/build.ts
|
|
266
|
-
import
|
|
459
|
+
import path5 from "node:path";
|
|
267
460
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
268
461
|
import fsExtra2 from "fs-extra";
|
|
269
|
-
import
|
|
462
|
+
import glob3 from "tiny-glob";
|
|
270
463
|
import { build as viteBuild } from "vite";
|
|
271
464
|
|
|
272
465
|
// src/render/asset-map/build-asset-map.ts
|
|
273
|
-
import path4 from "path";
|
|
274
466
|
var BuildAssetMap = class {
|
|
275
|
-
constructor(
|
|
276
|
-
this.manifest = manifest;
|
|
467
|
+
constructor() {
|
|
277
468
|
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
469
|
}
|
|
283
470
|
async get(moduleId) {
|
|
284
471
|
return this.moduleIdToAsset.get(moduleId) || null;
|
|
285
472
|
}
|
|
473
|
+
add(asset) {
|
|
474
|
+
this.moduleIdToAsset.set(asset.moduleId, asset);
|
|
475
|
+
}
|
|
286
476
|
toJson() {
|
|
287
477
|
const result = {};
|
|
288
478
|
for (const moduleId of this.moduleIdToAsset.keys()) {
|
|
@@ -290,15 +480,46 @@ var BuildAssetMap = class {
|
|
|
290
480
|
}
|
|
291
481
|
return result;
|
|
292
482
|
}
|
|
483
|
+
static fromViteManifest(viteManifest, elementMap) {
|
|
484
|
+
const assetMap = new BuildAssetMap();
|
|
485
|
+
const elementModuleIds = /* @__PURE__ */ new Set();
|
|
486
|
+
Object.values(elementMap).forEach(
|
|
487
|
+
(moduleId) => elementModuleIds.add(moduleId)
|
|
488
|
+
);
|
|
489
|
+
Object.keys(viteManifest).forEach((manifestKey) => {
|
|
490
|
+
const moduleId = `/${manifestKey}`;
|
|
491
|
+
const manifestChunk = viteManifest[manifestKey];
|
|
492
|
+
const isElement = elementModuleIds.has(moduleId);
|
|
493
|
+
const assetData = {
|
|
494
|
+
moduleId,
|
|
495
|
+
assetUrl: `/${manifestChunk.file}`,
|
|
496
|
+
importedModules: (manifestChunk.imports || []).map(
|
|
497
|
+
(relPath) => `/${relPath}`
|
|
498
|
+
),
|
|
499
|
+
importedCss: (manifestChunk.css || []).map((relPath) => `/${relPath}`),
|
|
500
|
+
isElement
|
|
501
|
+
};
|
|
502
|
+
assetMap.add(new BuildAsset(assetMap, assetData));
|
|
503
|
+
});
|
|
504
|
+
return assetMap;
|
|
505
|
+
}
|
|
506
|
+
static fromRootManifest(rootManifest) {
|
|
507
|
+
const assetMap = new BuildAssetMap();
|
|
508
|
+
Object.keys(rootManifest).forEach((moduleId) => {
|
|
509
|
+
const assetData = rootManifest[moduleId];
|
|
510
|
+
assetMap.add(new BuildAsset(assetMap, assetData));
|
|
511
|
+
});
|
|
512
|
+
return assetMap;
|
|
513
|
+
}
|
|
293
514
|
};
|
|
294
515
|
var BuildAsset = class {
|
|
295
|
-
constructor(assetMap,
|
|
516
|
+
constructor(assetMap, assetData) {
|
|
296
517
|
this.assetMap = assetMap;
|
|
297
|
-
this.moduleId = moduleId;
|
|
298
|
-
this.
|
|
299
|
-
this.
|
|
300
|
-
this.
|
|
301
|
-
this.
|
|
518
|
+
this.moduleId = assetData.moduleId;
|
|
519
|
+
this.assetUrl = assetData.assetUrl;
|
|
520
|
+
this.importedModules = assetData.importedModules;
|
|
521
|
+
this.importedCss = assetData.importedCss;
|
|
522
|
+
this.isElement = assetData.isElement;
|
|
302
523
|
}
|
|
303
524
|
async getCssDeps() {
|
|
304
525
|
const visited = /* @__PURE__ */ new Set();
|
|
@@ -323,14 +544,15 @@ var BuildAsset = class {
|
|
|
323
544
|
return;
|
|
324
545
|
}
|
|
325
546
|
visited.add(asset.moduleId);
|
|
326
|
-
|
|
327
|
-
if ([".ts", ".tsx"].includes(parts.ext) && asset.moduleId.includes("/elements/")) {
|
|
547
|
+
if (asset.isElement) {
|
|
328
548
|
urls.add(asset.assetUrl);
|
|
329
549
|
}
|
|
330
|
-
await Promise.all(
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
550
|
+
await Promise.all(
|
|
551
|
+
asset.importedModules.map(async (moduleId) => {
|
|
552
|
+
const importedAsset = await this.assetMap.get(moduleId);
|
|
553
|
+
this.collectJs(importedAsset, urls, visited);
|
|
554
|
+
})
|
|
555
|
+
);
|
|
334
556
|
}
|
|
335
557
|
async collectCss(asset, urls, visited) {
|
|
336
558
|
if (!asset) {
|
|
@@ -346,102 +568,90 @@ var BuildAsset = class {
|
|
|
346
568
|
if (asset.importedCss) {
|
|
347
569
|
asset.importedCss.forEach((cssUrl) => urls.add(cssUrl));
|
|
348
570
|
}
|
|
349
|
-
await Promise.all(
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
571
|
+
await Promise.all(
|
|
572
|
+
asset.importedModules.map(async (moduleId) => {
|
|
573
|
+
const importedAsset = await this.assetMap.get(moduleId);
|
|
574
|
+
this.collectCss(importedAsset, urls, visited);
|
|
575
|
+
})
|
|
576
|
+
);
|
|
353
577
|
}
|
|
354
578
|
toJson() {
|
|
355
579
|
return {
|
|
356
580
|
moduleId: this.moduleId,
|
|
357
581
|
assetUrl: this.assetUrl,
|
|
358
582
|
importedModules: this.importedModules,
|
|
359
|
-
importedCss: this.importedCss
|
|
583
|
+
importedCss: this.importedCss,
|
|
584
|
+
isElement: this.isElement
|
|
360
585
|
};
|
|
361
586
|
}
|
|
362
587
|
};
|
|
363
588
|
|
|
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
589
|
// src/cli/commands/build.ts
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
rootDir = process.cwd();
|
|
414
|
-
}
|
|
590
|
+
import { dim as dim2 } from "kleur/colors";
|
|
591
|
+
var __dirname2 = path5.dirname(fileURLToPath2(import.meta.url));
|
|
592
|
+
async function build(rootProjectDir, options) {
|
|
593
|
+
var _a, _b;
|
|
594
|
+
const rootDir = path5.resolve(rootProjectDir || process.cwd());
|
|
415
595
|
const rootConfig = await loadRootConfig(rootDir);
|
|
416
|
-
const distDir =
|
|
596
|
+
const distDir = path5.join(rootDir, "dist");
|
|
597
|
+
const ssrOnly = (options == null ? void 0 : options.ssrOnly) || false;
|
|
598
|
+
const mode = (options == null ? void 0 : options.mode) || "production";
|
|
599
|
+
console.log();
|
|
600
|
+
console.log(`${dim2("\u2503")} project: ${rootDir}`);
|
|
601
|
+
console.log(`${dim2("\u2503")} output: ${distDir}/html`);
|
|
602
|
+
console.log(`${dim2("\u2503")} mode: ${mode}`);
|
|
603
|
+
console.log();
|
|
417
604
|
await rmDir(distDir);
|
|
418
605
|
await makeDir(distDir);
|
|
419
606
|
const pages = [];
|
|
420
|
-
if (await isDirectory(
|
|
421
|
-
const pageFiles = await
|
|
607
|
+
if (await isDirectory(path5.join(rootDir, "routes"))) {
|
|
608
|
+
const pageFiles = await glob3(path5.join(rootDir, "routes/**/*"));
|
|
422
609
|
pageFiles.forEach((file) => {
|
|
423
|
-
const parts =
|
|
424
|
-
if (!parts.name.startsWith("_") &&
|
|
610
|
+
const parts = path5.parse(file);
|
|
611
|
+
if (!parts.name.startsWith("_") && isJsFile(parts.base)) {
|
|
425
612
|
pages.push(file);
|
|
426
613
|
}
|
|
427
614
|
});
|
|
428
615
|
}
|
|
616
|
+
const elementsDirs = [path5.join(rootDir, "elements")];
|
|
617
|
+
const elementsInclude = ((_a = rootConfig.elements) == null ? void 0 : _a.include) || [];
|
|
618
|
+
const excludePatterns = ((_b = rootConfig.elements) == null ? void 0 : _b.exclude) || [];
|
|
619
|
+
const excludeElement = (moduleId) => {
|
|
620
|
+
return excludePatterns.some((pattern) => Boolean(moduleId.match(pattern)));
|
|
621
|
+
};
|
|
622
|
+
for (const dirPath of elementsInclude) {
|
|
623
|
+
const elementsDir = path5.resolve(rootDir, dirPath);
|
|
624
|
+
if (!elementsDir.startsWith(rootDir)) {
|
|
625
|
+
throw new Error(
|
|
626
|
+
`the elements dir (${dirPath}) should be relative to the project's root dir (${rootDir})`
|
|
627
|
+
);
|
|
628
|
+
}
|
|
629
|
+
elementsDirs.push(elementsDir);
|
|
630
|
+
}
|
|
429
631
|
const elements = [];
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
const
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
632
|
+
const elementMap = {};
|
|
633
|
+
for (const dirPath of elementsDirs) {
|
|
634
|
+
if (await isDirectory(dirPath)) {
|
|
635
|
+
const elementFiles = await glob3("**/*", { cwd: dirPath });
|
|
636
|
+
elementFiles.forEach((file) => {
|
|
637
|
+
const parts = path5.parse(file);
|
|
638
|
+
if (isJsFile(parts.base)) {
|
|
639
|
+
const fullPath = path5.join(dirPath, file);
|
|
640
|
+
const moduleId = fullPath.slice(rootDir.length);
|
|
641
|
+
if (!excludeElement(moduleId)) {
|
|
642
|
+
elements.push(fullPath);
|
|
643
|
+
elementMap[parts.name] = moduleId;
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
});
|
|
647
|
+
}
|
|
438
648
|
}
|
|
439
649
|
const bundleScripts = [];
|
|
440
|
-
if (await isDirectory(
|
|
441
|
-
const bundleFiles = await
|
|
650
|
+
if (await isDirectory(path5.join(rootDir, "bundles"))) {
|
|
651
|
+
const bundleFiles = await glob3(path5.join(rootDir, "bundles/*"));
|
|
442
652
|
bundleFiles.forEach((file) => {
|
|
443
|
-
const parts =
|
|
444
|
-
if (
|
|
653
|
+
const parts = path5.parse(file);
|
|
654
|
+
if (isJsFile(parts.base)) {
|
|
445
655
|
bundleScripts.push(file);
|
|
446
656
|
}
|
|
447
657
|
});
|
|
@@ -450,27 +660,27 @@ async function build(rootDir) {
|
|
|
450
660
|
const baseConfig = {
|
|
451
661
|
...viteConfig,
|
|
452
662
|
root: rootDir,
|
|
663
|
+
mode,
|
|
453
664
|
esbuild: {
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
665
|
+
jsx: "automatic",
|
|
666
|
+
jsxImportSource: "preact",
|
|
667
|
+
treeShaking: true
|
|
457
668
|
},
|
|
458
|
-
plugins: [...viteConfig.plugins || [], pluginRoot()]
|
|
669
|
+
plugins: [...viteConfig.plugins || [], pluginRoot({ rootDir, rootConfig })]
|
|
459
670
|
};
|
|
460
671
|
await viteBuild({
|
|
461
672
|
...baseConfig,
|
|
462
|
-
mode: "production",
|
|
463
673
|
publicDir: false,
|
|
464
674
|
build: {
|
|
465
675
|
rollupOptions: {
|
|
466
|
-
input: [
|
|
676
|
+
input: [path5.resolve(__dirname2, "./render.js")],
|
|
467
677
|
output: {
|
|
468
678
|
format: "esm",
|
|
469
679
|
chunkFileNames: "chunks/[name].[hash].js",
|
|
470
680
|
assetFileNames: "assets/[name].[hash][extname]"
|
|
471
681
|
}
|
|
472
682
|
},
|
|
473
|
-
outDir:
|
|
683
|
+
outDir: path5.join(distDir, "server"),
|
|
474
684
|
ssr: true,
|
|
475
685
|
ssrManifest: false,
|
|
476
686
|
cssCodeSplit: true,
|
|
@@ -478,11 +688,13 @@ async function build(rootDir) {
|
|
|
478
688
|
minify: false,
|
|
479
689
|
polyfillModulePreload: false,
|
|
480
690
|
reportCompressedSize: false
|
|
691
|
+
},
|
|
692
|
+
ssr: {
|
|
693
|
+
noExternal: ["@blinkk/root"]
|
|
481
694
|
}
|
|
482
695
|
});
|
|
483
696
|
await viteBuild({
|
|
484
697
|
...baseConfig,
|
|
485
|
-
mode: "production",
|
|
486
698
|
publicDir: false,
|
|
487
699
|
build: {
|
|
488
700
|
rollupOptions: {
|
|
@@ -493,7 +705,7 @@ async function build(rootDir) {
|
|
|
493
705
|
assetFileNames: "assets/[name].[hash][extname]"
|
|
494
706
|
}
|
|
495
707
|
},
|
|
496
|
-
outDir:
|
|
708
|
+
outDir: path5.join(distDir, "client"),
|
|
497
709
|
ssr: false,
|
|
498
710
|
ssrManifest: false,
|
|
499
711
|
manifest: true,
|
|
@@ -504,45 +716,174 @@ async function build(rootDir) {
|
|
|
504
716
|
reportCompressedSize: false
|
|
505
717
|
}
|
|
506
718
|
});
|
|
507
|
-
const
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
const
|
|
511
|
-
|
|
512
|
-
|
|
719
|
+
const viteManifest = await loadJson(
|
|
720
|
+
path5.join(distDir, "client/manifest.json")
|
|
721
|
+
);
|
|
722
|
+
const assetMap = BuildAssetMap.fromViteManifest(viteManifest, elementMap);
|
|
723
|
+
writeFile(
|
|
724
|
+
path5.join(distDir, "client/root-manifest.json"),
|
|
725
|
+
JSON.stringify(assetMap.toJson(), null, 2)
|
|
726
|
+
);
|
|
727
|
+
const buildDir = path5.join(distDir, "html");
|
|
728
|
+
const publicDir = path5.join(rootDir, "public");
|
|
729
|
+
if (fsExtra2.existsSync(path5.join(rootDir, "public"))) {
|
|
513
730
|
fsExtra2.copySync(publicDir, buildDir);
|
|
514
731
|
} else {
|
|
515
732
|
makeDir(buildDir);
|
|
516
733
|
}
|
|
517
|
-
copyDir(
|
|
518
|
-
copyDir(
|
|
734
|
+
copyDir(path5.join(distDir, "client/assets"), path5.join(buildDir, "assets"));
|
|
735
|
+
copyDir(path5.join(distDir, "client/chunks"), path5.join(buildDir, "chunks"));
|
|
736
|
+
if (!ssrOnly) {
|
|
737
|
+
const render = await import(path5.join(distDir, "server/render.js"));
|
|
738
|
+
const renderer = new render.Renderer(rootConfig);
|
|
739
|
+
const sitemap = await renderer.getSitemap();
|
|
740
|
+
await Promise.all(
|
|
741
|
+
Object.keys(sitemap).map(async (urlPath) => {
|
|
742
|
+
const { route, params } = sitemap[urlPath];
|
|
743
|
+
const data = await renderer.renderRoute(route, {
|
|
744
|
+
assetMap,
|
|
745
|
+
routeParams: params
|
|
746
|
+
});
|
|
747
|
+
let outPath = path5.join(distDir, `html${urlPath}`, "index.html");
|
|
748
|
+
if (outPath.endsWith("404/index.html")) {
|
|
749
|
+
outPath = outPath.replace("404/index.html", "404.html");
|
|
750
|
+
}
|
|
751
|
+
const html = await htmlMinify(data.html || "");
|
|
752
|
+
await writeFile(outPath, html);
|
|
753
|
+
const relPath = outPath.slice(path5.dirname(distDir).length + 1);
|
|
754
|
+
console.log(`saved ${relPath}`);
|
|
755
|
+
})
|
|
756
|
+
);
|
|
757
|
+
}
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
// src/cli/commands/preview.ts
|
|
761
|
+
import path6 from "node:path";
|
|
762
|
+
import { default as express2 } from "express";
|
|
763
|
+
import { dim as dim3 } from "kleur/colors";
|
|
764
|
+
async function preview(rootProjectDir) {
|
|
765
|
+
var _a;
|
|
766
|
+
process.env.NODE_ENV = "development";
|
|
767
|
+
const rootDir = path6.resolve(rootProjectDir || process.cwd());
|
|
768
|
+
const rootConfig = await loadRootConfig(rootDir);
|
|
769
|
+
const distDir = path6.join(rootDir, "dist");
|
|
519
770
|
const render = await import(path6.join(distDir, "server/render.js"));
|
|
520
771
|
const renderer = new render.Renderer(rootConfig);
|
|
521
|
-
const
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
772
|
+
const manifestPath = path6.join(distDir, "client/root-manifest.json");
|
|
773
|
+
if (!await fileExists(manifestPath)) {
|
|
774
|
+
throw new Error(
|
|
775
|
+
`could not find ${manifestPath}. run \`root build\` before \`root preview\`.`
|
|
776
|
+
);
|
|
777
|
+
}
|
|
778
|
+
const rootManifest = await loadJson(manifestPath);
|
|
779
|
+
const assetMap = BuildAssetMap.fromRootManifest(rootManifest);
|
|
780
|
+
const app = express2();
|
|
781
|
+
app.disable("x-powered-by");
|
|
782
|
+
const userMiddlewares = ((_a = rootConfig.server) == null ? void 0 : _a.middlewares) || [];
|
|
783
|
+
userMiddlewares.forEach((middleware) => {
|
|
784
|
+
app.use(middleware);
|
|
785
|
+
});
|
|
786
|
+
const publicDir = path6.join(distDir, "html");
|
|
787
|
+
app.use(express2.static(publicDir));
|
|
788
|
+
app.use(async (req, res, next) => {
|
|
789
|
+
try {
|
|
790
|
+
const url = req.originalUrl;
|
|
791
|
+
const data = await renderer.render(url, {
|
|
792
|
+
assetMap
|
|
793
|
+
});
|
|
794
|
+
if (data.notFound || !data.html) {
|
|
795
|
+
next();
|
|
796
|
+
return;
|
|
797
|
+
}
|
|
798
|
+
let html = data.html || "";
|
|
799
|
+
if (rootConfig.minifyHtml !== false) {
|
|
800
|
+
html = await htmlMinify(html);
|
|
801
|
+
}
|
|
802
|
+
res.status(200).set({ "Content-Type": "text/html" }).end(html);
|
|
803
|
+
} catch (e) {
|
|
804
|
+
try {
|
|
805
|
+
const { html } = await renderer.renderError(e);
|
|
806
|
+
res.status(500).set({ "Content-Type": "text/html" }).end(html);
|
|
807
|
+
} catch (e2) {
|
|
808
|
+
console.error("failed to render custom error");
|
|
809
|
+
console.error(e2);
|
|
810
|
+
next(e);
|
|
811
|
+
}
|
|
812
|
+
}
|
|
813
|
+
});
|
|
814
|
+
const port = parseInt(process.env.PORT || "4007");
|
|
815
|
+
console.log();
|
|
816
|
+
console.log(`${dim3("\u2503")} project: ${rootDir}`);
|
|
817
|
+
console.log(`${dim3("\u2503")} server: http://localhost:${port}`);
|
|
818
|
+
console.log();
|
|
819
|
+
app.listen(port);
|
|
537
820
|
}
|
|
538
821
|
|
|
539
822
|
// src/cli/commands/start.ts
|
|
540
|
-
|
|
541
|
-
|
|
823
|
+
import path7 from "node:path";
|
|
824
|
+
import { default as express3 } from "express";
|
|
825
|
+
import { dim as dim4 } from "kleur/colors";
|
|
826
|
+
async function start(rootProjectDir) {
|
|
827
|
+
var _a;
|
|
828
|
+
process.env.NODE_ENV = "production";
|
|
829
|
+
const rootDir = path7.resolve(rootProjectDir || process.cwd());
|
|
830
|
+
const rootConfig = await loadRootConfig(rootDir);
|
|
831
|
+
const distDir = path7.join(rootDir, "dist");
|
|
832
|
+
const render = await import(path7.join(distDir, "server/render.js"));
|
|
833
|
+
const renderer = new render.Renderer(rootConfig);
|
|
834
|
+
const manifestPath = path7.join(distDir, "client/root-manifest.json");
|
|
835
|
+
if (!await fileExists(manifestPath)) {
|
|
836
|
+
throw new Error(
|
|
837
|
+
`could not find ${manifestPath}. run \`root build\` before \`root start\`.`
|
|
838
|
+
);
|
|
839
|
+
}
|
|
840
|
+
const rootManifest = await loadJson(manifestPath);
|
|
841
|
+
const assetMap = BuildAssetMap.fromRootManifest(rootManifest);
|
|
842
|
+
const app = express3();
|
|
843
|
+
app.disable("x-powered-by");
|
|
844
|
+
const userMiddlewares = ((_a = rootConfig.server) == null ? void 0 : _a.middlewares) || [];
|
|
845
|
+
userMiddlewares.forEach((middleware) => {
|
|
846
|
+
app.use(middleware);
|
|
847
|
+
});
|
|
848
|
+
const publicDir = path7.join(distDir, "html");
|
|
849
|
+
app.use(express3.static(publicDir));
|
|
850
|
+
app.use(async (req, res, next) => {
|
|
851
|
+
try {
|
|
852
|
+
const url = req.originalUrl;
|
|
853
|
+
const data = await renderer.render(url, {
|
|
854
|
+
assetMap
|
|
855
|
+
});
|
|
856
|
+
if (data.notFound || !data.html) {
|
|
857
|
+
next();
|
|
858
|
+
return;
|
|
859
|
+
}
|
|
860
|
+
let html = data.html || "";
|
|
861
|
+
if (rootConfig.minifyHtml !== false) {
|
|
862
|
+
html = await htmlMinify(html);
|
|
863
|
+
}
|
|
864
|
+
res.status(200).set({ "Content-Type": "text/html" }).end(html);
|
|
865
|
+
} catch (e) {
|
|
866
|
+
try {
|
|
867
|
+
const { html } = await renderer.renderError(e);
|
|
868
|
+
res.status(500).set({ "Content-Type": "text/html" }).end(html);
|
|
869
|
+
} catch (e2) {
|
|
870
|
+
console.error("failed to render custom error");
|
|
871
|
+
console.error(e2);
|
|
872
|
+
next(e);
|
|
873
|
+
}
|
|
874
|
+
}
|
|
875
|
+
});
|
|
876
|
+
const port = parseInt(process.env.PORT || "4007");
|
|
877
|
+
console.log();
|
|
878
|
+
console.log(`${dim4("\u2503")} project: ${rootDir}`);
|
|
879
|
+
console.log(`${dim4("\u2503")} server: http://localhost:${port}`);
|
|
880
|
+
console.log();
|
|
881
|
+
app.listen(port);
|
|
542
882
|
}
|
|
543
883
|
export {
|
|
544
884
|
build,
|
|
545
885
|
dev,
|
|
886
|
+
preview,
|
|
546
887
|
start
|
|
547
888
|
};
|
|
548
889
|
//# sourceMappingURL=cli.js.map
|