@blinkk/root 1.0.0-alpha.3 → 1.0.0-alpha.30
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 +27 -16
- package/dist/{chunk-CDPH3RKE.js → chunk-MLJ4KUD5.js} +72 -15
- package/dist/chunk-MLJ4KUD5.js.map +1 -0
- package/dist/chunk-ZB7R6ZOY.js +31 -0
- package/dist/chunk-ZB7R6ZOY.js.map +1 -0
- package/dist/cli.d.ts +10 -4
- package/dist/cli.js +791 -205
- package/dist/cli.js.map +1 -1
- package/dist/config-0a9ae264.d.ts +232 -0
- package/dist/core.d.ts +52 -5
- package/dist/core.js +17 -1
- package/dist/core.js.map +1 -1
- package/dist/render.d.ts +5 -57
- package/dist/render.js +297 -117
- package/dist/render.js.map +1 -1
- package/package.json +20 -21
- package/dist/chunk-CDPH3RKE.js.map +0 -1
- package/dist/types-d6c0705e.d.ts +0 -27
package/dist/cli.js
CHANGED
|
@@ -1,12 +1,22 @@
|
|
|
1
|
+
import {
|
|
2
|
+
configureServerPlugins,
|
|
3
|
+
getVitePlugins
|
|
4
|
+
} from "./chunk-ZB7R6ZOY.js";
|
|
5
|
+
|
|
1
6
|
// src/cli/commands/dev.ts
|
|
2
|
-
import
|
|
7
|
+
import path5 from "node:path";
|
|
3
8
|
import { fileURLToPath } from "node:url";
|
|
4
9
|
import { default as express } from "express";
|
|
5
10
|
import { createServer as createViteServer } from "vite";
|
|
6
11
|
|
|
7
12
|
// src/render/vite-plugin-root.ts
|
|
8
|
-
import
|
|
13
|
+
import path3 from "node:path";
|
|
14
|
+
|
|
15
|
+
// src/core/elements.ts
|
|
16
|
+
import fs2 from "node:fs";
|
|
17
|
+
import path2 from "node:path";
|
|
9
18
|
import glob from "tiny-glob";
|
|
19
|
+
import { searchForWorkspaceRoot } from "vite";
|
|
10
20
|
|
|
11
21
|
// src/core/fsutils.ts
|
|
12
22
|
import { promises as fs } from "node:fs";
|
|
@@ -27,12 +37,6 @@ async function makeDir(dirpath) {
|
|
|
27
37
|
await fs.mkdir(dirpath, { recursive: true });
|
|
28
38
|
}
|
|
29
39
|
}
|
|
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
40
|
async function rmDir(dirpath) {
|
|
37
41
|
await fs.rm(dirpath, { recursive: true, force: true });
|
|
38
42
|
}
|
|
@@ -50,42 +54,114 @@ async function isDirectory(dirpath) {
|
|
|
50
54
|
throw err;
|
|
51
55
|
});
|
|
52
56
|
}
|
|
57
|
+
function fileExists(filepath) {
|
|
58
|
+
return fs.access(filepath).then(() => true).catch(() => false);
|
|
59
|
+
}
|
|
60
|
+
async function directoryContains(dirpath, subpath) {
|
|
61
|
+
const outer = await fs.realpath(dirpath);
|
|
62
|
+
const inner = await fs.realpath(subpath);
|
|
63
|
+
const rel = path.relative(outer, inner);
|
|
64
|
+
return !rel.startsWith("..");
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// src/core/elements.ts
|
|
68
|
+
async function getElements(rootConfig) {
|
|
69
|
+
var _a, _b;
|
|
70
|
+
const rootDir = rootConfig.rootDir;
|
|
71
|
+
const workspaceRoot = searchForWorkspaceRoot(rootDir);
|
|
72
|
+
const elementsDirs = [path2.join(rootDir, "elements")];
|
|
73
|
+
const elementsInclude = ((_a = rootConfig.elements) == null ? void 0 : _a.include) || [];
|
|
74
|
+
const excludePatterns = ((_b = rootConfig.elements) == null ? void 0 : _b.exclude) || [];
|
|
75
|
+
const excludeElement = (moduleId) => {
|
|
76
|
+
return excludePatterns.some((pattern) => Boolean(moduleId.match(pattern)));
|
|
77
|
+
};
|
|
78
|
+
for (const dirPath of elementsInclude) {
|
|
79
|
+
const elementsDir = path2.resolve(rootDir, dirPath);
|
|
80
|
+
if (!directoryContains(rootDir, elementsDir)) {
|
|
81
|
+
throw new Error(
|
|
82
|
+
`the elements dir (${dirPath}) should be within the project's workspace (${workspaceRoot})`
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
elementsDirs.push(elementsDir);
|
|
86
|
+
}
|
|
87
|
+
const elementMap = {};
|
|
88
|
+
for (const dirPath of elementsDirs) {
|
|
89
|
+
if (await isDirectory(dirPath)) {
|
|
90
|
+
const elementFiles = await glob("**/*", { cwd: dirPath });
|
|
91
|
+
elementFiles.forEach((file) => {
|
|
92
|
+
const parts = path2.parse(file);
|
|
93
|
+
if (isJsFile(parts.base)) {
|
|
94
|
+
const filePath = path2.join(dirPath, file);
|
|
95
|
+
const src = path2.relative(rootDir, filePath);
|
|
96
|
+
const realPath = fs2.realpathSync(filePath);
|
|
97
|
+
if (!excludeElement(src)) {
|
|
98
|
+
elementMap[parts.name] = {
|
|
99
|
+
src,
|
|
100
|
+
filePath,
|
|
101
|
+
realPath
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return elementMap;
|
|
109
|
+
}
|
|
53
110
|
|
|
54
111
|
// src/render/vite-plugin-root.ts
|
|
55
112
|
var JSX_ELEMENTS_REGEX = /jsxs?\("(\w[\w-]+\w)"/g;
|
|
56
113
|
var HTML_ELEMENTS_REGEX = /<(\w[\w-]+\w)/g;
|
|
57
114
|
function pluginRoot(options) {
|
|
58
|
-
const
|
|
59
|
-
|
|
115
|
+
const elementsVirtualId = "virtual:root-elements";
|
|
116
|
+
const resolvedElementsVirtualId = "\0" + elementsVirtualId;
|
|
117
|
+
const rootConfig = options.rootConfig;
|
|
118
|
+
let tagNameToElement;
|
|
119
|
+
const customElementFiles = /* @__PURE__ */ new Set();
|
|
60
120
|
async function updateElementMap() {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
elementMap[parts.name] = `/${file}`;
|
|
67
|
-
}
|
|
121
|
+
tagNameToElement = await getElements(rootConfig);
|
|
122
|
+
customElementFiles.clear();
|
|
123
|
+
Object.values(tagNameToElement).forEach((elementModule) => {
|
|
124
|
+
customElementFiles.add(elementModule.filePath);
|
|
125
|
+
customElementFiles.add(elementModule.realPath);
|
|
68
126
|
});
|
|
69
|
-
console.log(JSON.stringify(elementMap));
|
|
70
127
|
}
|
|
71
128
|
async function getElementImport(tagname) {
|
|
72
|
-
if (!
|
|
129
|
+
if (!tagNameToElement) {
|
|
73
130
|
await updateElementMap();
|
|
74
131
|
}
|
|
75
|
-
if (tagname in
|
|
76
|
-
|
|
132
|
+
if (tagname in tagNameToElement) {
|
|
133
|
+
const elementModule = tagNameToElement[tagname];
|
|
134
|
+
if (elementModule.filePath === elementModule.realPath) {
|
|
135
|
+
return elementModule.src;
|
|
136
|
+
}
|
|
77
137
|
}
|
|
78
138
|
return null;
|
|
79
139
|
}
|
|
140
|
+
function isCustomElement(id) {
|
|
141
|
+
if (!isJsFile(id)) {
|
|
142
|
+
return false;
|
|
143
|
+
}
|
|
144
|
+
return customElementFiles.has(id);
|
|
145
|
+
}
|
|
80
146
|
return {
|
|
81
147
|
name: "vite-plugin-root",
|
|
82
|
-
|
|
83
|
-
if (
|
|
84
|
-
return
|
|
148
|
+
resolveId(id) {
|
|
149
|
+
if (id === elementsVirtualId) {
|
|
150
|
+
return resolvedElementsVirtualId;
|
|
85
151
|
}
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
152
|
+
return null;
|
|
153
|
+
},
|
|
154
|
+
async load(id) {
|
|
155
|
+
if (id === resolvedElementsVirtualId) {
|
|
156
|
+
await updateElementMap();
|
|
157
|
+
return `export const elementsMap = ${JSON.stringify(tagNameToElement)}`;
|
|
158
|
+
}
|
|
159
|
+
return null;
|
|
160
|
+
},
|
|
161
|
+
async transform(src, id) {
|
|
162
|
+
if (isCustomElement(id)) {
|
|
163
|
+
await updateElementMap();
|
|
164
|
+
const idParts = path3.parse(id);
|
|
89
165
|
const deps = /* @__PURE__ */ new Set();
|
|
90
166
|
const tagnames = [
|
|
91
167
|
...src.matchAll(JSX_ELEMENTS_REGEX),
|
|
@@ -102,46 +178,79 @@ function pluginRoot(options) {
|
|
|
102
178
|
deps.add(tagname);
|
|
103
179
|
}
|
|
104
180
|
const importUrls = [];
|
|
105
|
-
await Promise.all(
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
181
|
+
await Promise.all(
|
|
182
|
+
Array.from(deps).map(async (tagname) => {
|
|
183
|
+
const importUrl = await getElementImport(tagname);
|
|
184
|
+
if (importUrl) {
|
|
185
|
+
importUrls.push(importUrl);
|
|
186
|
+
}
|
|
187
|
+
})
|
|
188
|
+
);
|
|
111
189
|
if (importUrls.length > 0) {
|
|
112
|
-
const importLines = importUrls.map((url) => `import '
|
|
190
|
+
const importLines = importUrls.map((url) => `import '/${url}';`).join("\n");
|
|
113
191
|
const code = `${src}
|
|
114
192
|
|
|
115
193
|
// autogenerated by root:
|
|
116
194
|
${importLines}
|
|
117
195
|
`;
|
|
118
|
-
console.log(code);
|
|
119
196
|
return { code };
|
|
120
197
|
}
|
|
121
198
|
return null;
|
|
122
199
|
}
|
|
200
|
+
return null;
|
|
123
201
|
}
|
|
124
202
|
};
|
|
125
203
|
}
|
|
126
204
|
|
|
127
205
|
// src/render/asset-map/dev-asset-map.ts
|
|
128
|
-
import
|
|
206
|
+
import path4 from "node:path";
|
|
207
|
+
import { searchForWorkspaceRoot as searchForWorkspaceRoot2 } from "vite";
|
|
129
208
|
var DevServerAssetMap = class {
|
|
130
|
-
constructor(moduleGraph) {
|
|
209
|
+
constructor(rootConfig, moduleGraph) {
|
|
210
|
+
this.rootConfig = rootConfig;
|
|
131
211
|
this.moduleGraph = moduleGraph;
|
|
132
212
|
}
|
|
133
|
-
async get(
|
|
134
|
-
const
|
|
135
|
-
|
|
136
|
-
|
|
213
|
+
async get(src) {
|
|
214
|
+
const file = path4.resolve(this.rootConfig.rootDir, src);
|
|
215
|
+
const viteModules = this.moduleGraph.getModulesByFile(file);
|
|
216
|
+
if (viteModules && viteModules.size > 0) {
|
|
217
|
+
const [viteModule] = viteModules;
|
|
218
|
+
return new DevServerAsset(src, {
|
|
219
|
+
assetMap: this,
|
|
220
|
+
viteModule
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
if (file.startsWith(this.rootConfig.rootDir)) {
|
|
224
|
+
const assetUrl = file.slice(this.rootConfig.rootDir.length);
|
|
225
|
+
return {
|
|
226
|
+
src,
|
|
227
|
+
assetUrl,
|
|
228
|
+
getCssDeps: async () => [],
|
|
229
|
+
getJsDeps: async () => [assetUrl]
|
|
230
|
+
};
|
|
137
231
|
}
|
|
138
|
-
|
|
232
|
+
const workspaceRoot = searchForWorkspaceRoot2(this.rootConfig.rootDir);
|
|
233
|
+
if (await directoryContains(workspaceRoot, file)) {
|
|
234
|
+
const assetUrl = `/@fs/${file}`;
|
|
235
|
+
return {
|
|
236
|
+
src,
|
|
237
|
+
assetUrl,
|
|
238
|
+
getCssDeps: async () => [],
|
|
239
|
+
getJsDeps: async () => [assetUrl]
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
console.log(`could not find asset in asset map: ${src}`);
|
|
243
|
+
return null;
|
|
244
|
+
}
|
|
245
|
+
filePathToSrc(file) {
|
|
246
|
+
return path4.relative(this.rootConfig.rootDir, file);
|
|
139
247
|
}
|
|
140
248
|
};
|
|
141
249
|
var DevServerAsset = class {
|
|
142
|
-
constructor(
|
|
143
|
-
this.
|
|
144
|
-
this.
|
|
250
|
+
constructor(src, options) {
|
|
251
|
+
this.src = src;
|
|
252
|
+
this.assetMap = options.assetMap;
|
|
253
|
+
this.viteModule = options.viteModule;
|
|
145
254
|
this.moduleId = this.viteModule.id;
|
|
146
255
|
this.assetUrl = this.viteModule.url;
|
|
147
256
|
}
|
|
@@ -171,13 +280,17 @@ var DevServerAsset = class {
|
|
|
171
280
|
return;
|
|
172
281
|
}
|
|
173
282
|
visited.add(asset.moduleId);
|
|
174
|
-
const parts =
|
|
283
|
+
const parts = path4.parse(asset.assetUrl);
|
|
175
284
|
if ([".js", ".jsx", ".ts", ".tsx"].includes(parts.ext) && asset.moduleId.includes("/elements/")) {
|
|
176
285
|
urls.add(asset.assetUrl);
|
|
177
286
|
}
|
|
178
287
|
asset.getImportedModules().forEach((viteModule) => {
|
|
179
|
-
if (viteModule.
|
|
180
|
-
const
|
|
288
|
+
if (viteModule.file) {
|
|
289
|
+
const src = this.assetMap.filePathToSrc(viteModule.file);
|
|
290
|
+
const importedAsset = new DevServerAsset(src, {
|
|
291
|
+
assetMap: this.assetMap,
|
|
292
|
+
viteModule
|
|
293
|
+
});
|
|
181
294
|
this.collectJs(importedAsset, urls, visited);
|
|
182
295
|
}
|
|
183
296
|
});
|
|
@@ -193,15 +306,19 @@ var DevServerAsset = class {
|
|
|
193
306
|
return;
|
|
194
307
|
}
|
|
195
308
|
visited.add(asset.assetUrl);
|
|
196
|
-
if (asset.
|
|
197
|
-
const parts =
|
|
309
|
+
if (asset.src.endsWith(".scss")) {
|
|
310
|
+
const parts = path4.parse(asset.src);
|
|
198
311
|
if (!parts.name.startsWith("_")) {
|
|
199
312
|
urls.add(asset.assetUrl);
|
|
200
313
|
}
|
|
201
314
|
}
|
|
202
315
|
asset.getImportedModules().forEach((viteModule) => {
|
|
203
|
-
if (viteModule.
|
|
204
|
-
const
|
|
316
|
+
if (viteModule.file) {
|
|
317
|
+
const src = this.assetMap.filePathToSrc(viteModule.file);
|
|
318
|
+
const importedAsset = new DevServerAsset(src, {
|
|
319
|
+
assetMap: this.assetMap,
|
|
320
|
+
viteModule
|
|
321
|
+
});
|
|
205
322
|
this.collectCss(importedAsset, urls, visited);
|
|
206
323
|
}
|
|
207
324
|
});
|
|
@@ -221,66 +338,163 @@ async function loadRootConfig(rootDir) {
|
|
|
221
338
|
const configBundle = await bundleRequire({
|
|
222
339
|
filepath: configPath
|
|
223
340
|
});
|
|
224
|
-
return configBundle.mod.default || {};
|
|
341
|
+
return Object.assign({}, configBundle.mod.default || {}, { rootDir });
|
|
225
342
|
}
|
|
226
|
-
return {};
|
|
343
|
+
return { rootDir };
|
|
227
344
|
}
|
|
228
345
|
|
|
229
346
|
// src/render/html-minify.ts
|
|
230
347
|
import { minify } from "html-minifier-terser";
|
|
231
|
-
async function htmlMinify(html) {
|
|
232
|
-
const
|
|
348
|
+
async function htmlMinify(html, options) {
|
|
349
|
+
const minifyOptions = options || {
|
|
233
350
|
collapseWhitespace: true,
|
|
234
351
|
removeComments: true,
|
|
235
352
|
preserveLineBreaks: true
|
|
236
|
-
}
|
|
237
|
-
|
|
353
|
+
};
|
|
354
|
+
try {
|
|
355
|
+
const min = await minify(html, minifyOptions);
|
|
356
|
+
return min.trimStart();
|
|
357
|
+
} catch (e) {
|
|
358
|
+
console.error("failed to minify html:", e);
|
|
359
|
+
return html;
|
|
360
|
+
}
|
|
238
361
|
}
|
|
239
362
|
|
|
240
363
|
// src/cli/commands/dev.ts
|
|
241
364
|
import glob2 from "tiny-glob";
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
365
|
+
import { dim } from "kleur/colors";
|
|
366
|
+
|
|
367
|
+
// src/core/middleware.ts
|
|
368
|
+
function rootProjectMiddleware(options) {
|
|
369
|
+
return (req, _, next) => {
|
|
370
|
+
req.rootConfig = Object.assign({}, options.rootConfig, {
|
|
371
|
+
rootDir: options.rootDir
|
|
372
|
+
});
|
|
373
|
+
next();
|
|
374
|
+
};
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
// src/cli/ports.ts
|
|
378
|
+
import { createServer } from "node:net";
|
|
379
|
+
function isPortOpen(port) {
|
|
380
|
+
return new Promise((resolve, reject) => {
|
|
381
|
+
const server = createServer();
|
|
382
|
+
server.on("error", (err) => {
|
|
383
|
+
if (err.code === "EADDRINUSE") {
|
|
384
|
+
resolve(false);
|
|
385
|
+
return;
|
|
386
|
+
}
|
|
387
|
+
reject(err);
|
|
388
|
+
});
|
|
389
|
+
server.on("close", () => {
|
|
390
|
+
resolve(true);
|
|
391
|
+
});
|
|
392
|
+
server.listen(port, () => {
|
|
393
|
+
server.close((err) => {
|
|
394
|
+
if (err) {
|
|
395
|
+
console.log(`error closing server: ${err}`);
|
|
396
|
+
reject(err);
|
|
397
|
+
}
|
|
398
|
+
});
|
|
399
|
+
});
|
|
400
|
+
});
|
|
401
|
+
}
|
|
402
|
+
async function findOpenPort(min, max) {
|
|
403
|
+
let port = min;
|
|
404
|
+
while (port <= max) {
|
|
405
|
+
const isOpen = await isPortOpen(port);
|
|
406
|
+
if (isOpen) {
|
|
407
|
+
return port;
|
|
408
|
+
}
|
|
409
|
+
port += 1;
|
|
410
|
+
}
|
|
411
|
+
throw new Error(`no ports open between ${min} and ${max}`);
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
// src/render/html-pretty.ts
|
|
415
|
+
import { default as beautify } from "js-beautify";
|
|
416
|
+
async function htmlPretty(html, options) {
|
|
417
|
+
const prettyOptions = options || {
|
|
418
|
+
indent_size: 0,
|
|
419
|
+
end_with_newline: true,
|
|
420
|
+
extra_liners: []
|
|
421
|
+
};
|
|
422
|
+
try {
|
|
423
|
+
const output = beautify.html(html, prettyOptions);
|
|
424
|
+
return output.trimStart();
|
|
425
|
+
} catch (e) {
|
|
426
|
+
console.error("failed to pretty html:", e);
|
|
427
|
+
return html;
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
// src/cli/commands/dev.ts
|
|
432
|
+
var __dirname = path5.dirname(fileURLToPath(import.meta.url));
|
|
433
|
+
async function dev(rootProjectDir) {
|
|
434
|
+
process.env.NODE_ENV = "development";
|
|
435
|
+
const rootDir = path5.resolve(rootProjectDir || process.cwd());
|
|
436
|
+
const defaultPort = parseInt(process.env.PORT || "4007");
|
|
437
|
+
const port = await findOpenPort(defaultPort, defaultPort + 10);
|
|
438
|
+
console.log();
|
|
439
|
+
console.log(`${dim("\u2503")} project: ${rootDir}`);
|
|
440
|
+
console.log(`${dim("\u2503")} server: http://localhost:${port}`);
|
|
441
|
+
console.log(`${dim("\u2503")} mode: development`);
|
|
250
442
|
console.log();
|
|
251
|
-
|
|
252
|
-
|
|
443
|
+
const server = await createServer2({ rootDir, port });
|
|
444
|
+
server.listen(port);
|
|
253
445
|
}
|
|
254
|
-
async function
|
|
255
|
-
const rootDir = (options == null ? void 0 : options.rootDir) || process.cwd();
|
|
446
|
+
async function createServer2(options) {
|
|
447
|
+
const rootDir = path5.resolve((options == null ? void 0 : options.rootDir) || process.cwd());
|
|
256
448
|
const rootConfig = await loadRootConfig(rootDir);
|
|
449
|
+
const port = options == null ? void 0 : options.port;
|
|
450
|
+
const server = express();
|
|
451
|
+
server.disable("x-powered-by");
|
|
452
|
+
server.use(rootProjectMiddleware({ rootDir, rootConfig }));
|
|
453
|
+
server.use(await viteServerMiddleware({ rootDir, rootConfig, port }));
|
|
454
|
+
server.use(rootDevRendererMiddleware());
|
|
455
|
+
const plugins = rootConfig.plugins || [];
|
|
456
|
+
await configureServerPlugins(
|
|
457
|
+
server,
|
|
458
|
+
async () => {
|
|
459
|
+
var _a;
|
|
460
|
+
const userMiddlewares = ((_a = rootConfig.server) == null ? void 0 : _a.middlewares) || [];
|
|
461
|
+
for (const middleware of userMiddlewares) {
|
|
462
|
+
server.use(middleware);
|
|
463
|
+
}
|
|
464
|
+
server.use(rootDevServerMiddleware());
|
|
465
|
+
server.use(rootDevServer404Middleware());
|
|
466
|
+
},
|
|
467
|
+
plugins,
|
|
468
|
+
{ type: "dev" }
|
|
469
|
+
);
|
|
470
|
+
return server;
|
|
471
|
+
}
|
|
472
|
+
async function viteServerMiddleware(options) {
|
|
473
|
+
var _a, _b;
|
|
474
|
+
const rootDir = options.rootDir;
|
|
475
|
+
const rootConfig = options.rootConfig;
|
|
257
476
|
const viteConfig = rootConfig.vite || {};
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
477
|
+
let hmrOptions = (_a = viteConfig.server) == null ? void 0 : _a.hmr;
|
|
478
|
+
if (typeof hmrOptions === "undefined" && options.port) {
|
|
479
|
+
hmrOptions = { port: options.port + 10 };
|
|
480
|
+
}
|
|
481
|
+
const routeFiles = [];
|
|
482
|
+
if (await isDirectory(path5.join(rootDir, "routes"))) {
|
|
483
|
+
const pageFiles = await glob2("routes/**/*", { cwd: rootDir });
|
|
262
484
|
pageFiles.forEach((file) => {
|
|
263
|
-
const parts =
|
|
485
|
+
const parts = path5.parse(file);
|
|
264
486
|
if (!parts.name.startsWith("_") && isJsFile(parts.base)) {
|
|
265
|
-
|
|
266
|
-
}
|
|
267
|
-
});
|
|
268
|
-
}
|
|
269
|
-
const elements = [];
|
|
270
|
-
if (await isDirectory(path4.join(rootDir, "elements"))) {
|
|
271
|
-
const elementFiles = await glob2(path4.join(rootDir, "elements/**/*"));
|
|
272
|
-
elementFiles.forEach((file) => {
|
|
273
|
-
const parts = path4.parse(file);
|
|
274
|
-
if (isJsFile(parts.base)) {
|
|
275
|
-
elements.push(file);
|
|
487
|
+
routeFiles.push(file);
|
|
276
488
|
}
|
|
277
489
|
});
|
|
278
490
|
}
|
|
491
|
+
const elementsMap = await getElements(rootConfig);
|
|
492
|
+
const elements = Object.values(elementsMap).map((mod) => mod.src);
|
|
279
493
|
const bundleScripts = [];
|
|
280
|
-
if (await isDirectory(
|
|
281
|
-
const bundleFiles = await glob2(
|
|
494
|
+
if (await isDirectory(path5.join(rootDir, "bundles"))) {
|
|
495
|
+
const bundleFiles = await glob2("bundles/*", { cwd: rootDir });
|
|
282
496
|
bundleFiles.forEach((file) => {
|
|
283
|
-
const parts =
|
|
497
|
+
const parts = path5.parse(file);
|
|
284
498
|
if (isJsFile(parts.base)) {
|
|
285
499
|
bundleScripts.push(file);
|
|
286
500
|
}
|
|
@@ -288,36 +502,96 @@ async function getMiddlewares(options) {
|
|
|
288
502
|
}
|
|
289
503
|
const viteServer = await createViteServer({
|
|
290
504
|
...viteConfig,
|
|
291
|
-
|
|
505
|
+
mode: "development",
|
|
506
|
+
root: rootDir,
|
|
507
|
+
publicDir: path5.join(rootDir, "public"),
|
|
508
|
+
server: {
|
|
509
|
+
...viteConfig.server || {},
|
|
510
|
+
middlewareMode: true,
|
|
511
|
+
hmr: hmrOptions
|
|
512
|
+
},
|
|
292
513
|
appType: "custom",
|
|
293
514
|
optimizeDeps: {
|
|
294
|
-
|
|
515
|
+
...viteConfig.optimizeDeps || {},
|
|
516
|
+
include: [
|
|
517
|
+
...routeFiles,
|
|
518
|
+
...elements,
|
|
519
|
+
...bundleScripts,
|
|
520
|
+
...((_b = viteConfig.optimizeDeps) == null ? void 0 : _b.include) || []
|
|
521
|
+
]
|
|
295
522
|
},
|
|
296
523
|
ssr: {
|
|
524
|
+
...viteConfig.ssr || {},
|
|
297
525
|
noExternal: ["@blinkk/root"]
|
|
298
526
|
},
|
|
299
527
|
esbuild: {
|
|
528
|
+
...viteConfig.esbuild || {},
|
|
300
529
|
jsx: "automatic",
|
|
301
530
|
jsxImportSource: "preact"
|
|
302
531
|
},
|
|
303
|
-
plugins: [
|
|
532
|
+
plugins: [
|
|
533
|
+
await pluginRoot({ rootConfig }),
|
|
534
|
+
...viteConfig.plugins || [],
|
|
535
|
+
...getVitePlugins(rootConfig.plugins || [])
|
|
536
|
+
]
|
|
304
537
|
});
|
|
305
|
-
|
|
306
|
-
const url = req.originalUrl;
|
|
307
|
-
const render = await viteServer.ssrLoadModule(renderModulePath);
|
|
308
|
-
const renderer = new render.Renderer(rootConfig);
|
|
538
|
+
return async (req, res, next) => {
|
|
309
539
|
try {
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
540
|
+
req.viteServer = viteServer;
|
|
541
|
+
viteServer.middlewares(req, res, next);
|
|
542
|
+
} catch (e) {
|
|
543
|
+
next(e);
|
|
544
|
+
}
|
|
545
|
+
};
|
|
546
|
+
}
|
|
547
|
+
function rootDevRendererMiddleware() {
|
|
548
|
+
const renderModulePath = path5.resolve(__dirname, "./render.js");
|
|
549
|
+
return async (req, _, next) => {
|
|
550
|
+
const rootConfig = req.rootConfig;
|
|
551
|
+
const viteServer = req.viteServer;
|
|
552
|
+
try {
|
|
553
|
+
const render = await viteServer.ssrLoadModule(renderModulePath);
|
|
554
|
+
const assetMap = new DevServerAssetMap(
|
|
555
|
+
rootConfig,
|
|
556
|
+
viteServer.moduleGraph
|
|
557
|
+
);
|
|
558
|
+
req.renderer = new render.Renderer(rootConfig, { assetMap });
|
|
559
|
+
next();
|
|
560
|
+
} catch (e) {
|
|
561
|
+
next(e);
|
|
562
|
+
}
|
|
563
|
+
};
|
|
564
|
+
}
|
|
565
|
+
function rootDevServerMiddleware() {
|
|
566
|
+
return async (req, res, next) => {
|
|
567
|
+
const url = req.path;
|
|
568
|
+
const renderer = req.renderer;
|
|
569
|
+
const viteServer = req.viteServer;
|
|
570
|
+
const rootConfig = req.rootConfig;
|
|
571
|
+
try {
|
|
572
|
+
const data = await renderer.render(url);
|
|
573
|
+
if (data.notFound || !data.html) {
|
|
574
|
+
next();
|
|
575
|
+
return;
|
|
576
|
+
}
|
|
577
|
+
let html = await viteServer.transformIndexHtml(url, data.html || "");
|
|
578
|
+
if (rootConfig.prettyHtml !== false) {
|
|
579
|
+
html = await htmlPretty(html, rootConfig.prettyHtmlOptions);
|
|
580
|
+
}
|
|
581
|
+
if (rootConfig.minifyHtml !== false) {
|
|
582
|
+
html = await htmlMinify(html, rootConfig.minifyHtmlOptions);
|
|
583
|
+
}
|
|
315
584
|
res.status(200).set({ "Content-Type": "text/html" }).end(html);
|
|
316
585
|
} catch (e) {
|
|
317
586
|
viteServer.ssrFixStacktrace(e);
|
|
587
|
+
console.error(e);
|
|
318
588
|
try {
|
|
319
|
-
|
|
320
|
-
|
|
589
|
+
if (renderer) {
|
|
590
|
+
const { html } = await renderer.renderError(e);
|
|
591
|
+
res.status(500).set({ "Content-Type": "text/html" }).end(html);
|
|
592
|
+
} else {
|
|
593
|
+
next(e);
|
|
594
|
+
}
|
|
321
595
|
} catch (e2) {
|
|
322
596
|
console.error("failed to render custom error");
|
|
323
597
|
console.error(e2);
|
|
@@ -325,49 +599,112 @@ async function getMiddlewares(options) {
|
|
|
325
599
|
}
|
|
326
600
|
}
|
|
327
601
|
};
|
|
328
|
-
return [viteServer.middlewares, rootMiddleware];
|
|
329
602
|
}
|
|
330
|
-
function
|
|
331
|
-
|
|
603
|
+
function rootDevServer404Middleware() {
|
|
604
|
+
return async (req, res) => {
|
|
605
|
+
const url = req.path;
|
|
606
|
+
const ext = path5.extname(url);
|
|
607
|
+
const renderer = req.renderer;
|
|
608
|
+
if (!ext) {
|
|
609
|
+
const data = await renderer.renderDevServer404();
|
|
610
|
+
const html = data.html || "";
|
|
611
|
+
res.status(404).set({ "Content-Type": "text/html" }).end(html);
|
|
612
|
+
return;
|
|
613
|
+
}
|
|
614
|
+
res.status(404).set({ "Content-Type": "text/plain" }).end("404");
|
|
615
|
+
};
|
|
332
616
|
}
|
|
333
617
|
|
|
334
618
|
// src/cli/commands/build.ts
|
|
335
|
-
import
|
|
619
|
+
import path7 from "node:path";
|
|
336
620
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
337
621
|
import fsExtra2 from "fs-extra";
|
|
338
622
|
import glob3 from "tiny-glob";
|
|
339
623
|
import { build as viteBuild } from "vite";
|
|
340
624
|
|
|
341
625
|
// src/render/asset-map/build-asset-map.ts
|
|
342
|
-
import
|
|
626
|
+
import fs3 from "node:fs";
|
|
627
|
+
import path6 from "node:path";
|
|
343
628
|
var BuildAssetMap = class {
|
|
344
|
-
constructor(
|
|
345
|
-
this.
|
|
346
|
-
this.
|
|
347
|
-
Object.keys(this.manifest).forEach((manifestKey) => {
|
|
348
|
-
const moduleId = `/${manifestKey}`;
|
|
349
|
-
this.moduleIdToAsset.set(moduleId, new BuildAsset(this, moduleId, this.manifest[manifestKey]));
|
|
350
|
-
});
|
|
629
|
+
constructor(rootConfig) {
|
|
630
|
+
this.rootConfig = rootConfig;
|
|
631
|
+
this.srcToAsset = /* @__PURE__ */ new Map();
|
|
351
632
|
}
|
|
352
|
-
async get(
|
|
353
|
-
|
|
633
|
+
async get(src) {
|
|
634
|
+
const asset = this.srcToAsset.get(src);
|
|
635
|
+
if (asset) {
|
|
636
|
+
return asset;
|
|
637
|
+
}
|
|
638
|
+
const realSrc = realPathRelativeTo(this.rootConfig.rootDir, src);
|
|
639
|
+
if (realSrc !== src) {
|
|
640
|
+
const asset2 = this.srcToAsset.get(realSrc);
|
|
641
|
+
if (asset2) {
|
|
642
|
+
return asset2;
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
console.log(`could not find build asset: ${src}`);
|
|
646
|
+
return null;
|
|
647
|
+
}
|
|
648
|
+
add(asset) {
|
|
649
|
+
this.srcToAsset.set(asset.src, asset);
|
|
354
650
|
}
|
|
355
651
|
toJson() {
|
|
356
652
|
const result = {};
|
|
357
|
-
for (const
|
|
358
|
-
result[
|
|
653
|
+
for (const src of this.srcToAsset.keys()) {
|
|
654
|
+
result[src] = this.srcToAsset.get(src).toJson();
|
|
359
655
|
}
|
|
360
656
|
return result;
|
|
361
657
|
}
|
|
658
|
+
static fromViteManifest(rootConfig, viteManifest, elementMap) {
|
|
659
|
+
const assetMap = new BuildAssetMap(rootConfig);
|
|
660
|
+
const elementFiles = /* @__PURE__ */ new Set();
|
|
661
|
+
Object.values(elementMap).forEach((elementModule) => {
|
|
662
|
+
elementFiles.add(elementModule.src);
|
|
663
|
+
const realSrc = realPathRelativeTo(rootConfig.rootDir, elementModule.src);
|
|
664
|
+
if (realSrc !== elementModule.src) {
|
|
665
|
+
elementFiles.add(realSrc);
|
|
666
|
+
}
|
|
667
|
+
});
|
|
668
|
+
Object.keys(viteManifest).forEach((manifestKey) => {
|
|
669
|
+
const src = manifestKey;
|
|
670
|
+
const manifestChunk = viteManifest[manifestKey];
|
|
671
|
+
const isElement = elementFiles.has(src);
|
|
672
|
+
const assetData = {
|
|
673
|
+
src,
|
|
674
|
+
assetUrl: `/${manifestChunk.file}`,
|
|
675
|
+
importedModules: manifestChunk.imports || [],
|
|
676
|
+
importedCss: (manifestChunk.css || []).map((relPath) => `/${relPath}`),
|
|
677
|
+
isElement
|
|
678
|
+
};
|
|
679
|
+
assetMap.add(new BuildAsset(assetMap, assetData));
|
|
680
|
+
});
|
|
681
|
+
return assetMap;
|
|
682
|
+
}
|
|
683
|
+
static fromRootManifest(rootConfig, rootManifest) {
|
|
684
|
+
const assetMap = new BuildAssetMap(rootConfig);
|
|
685
|
+
Object.keys(rootManifest).forEach((moduleId) => {
|
|
686
|
+
const assetData = rootManifest[moduleId];
|
|
687
|
+
assetMap.add(new BuildAsset(assetMap, assetData));
|
|
688
|
+
});
|
|
689
|
+
return assetMap;
|
|
690
|
+
}
|
|
362
691
|
};
|
|
692
|
+
function realPathRelativeTo(rootDir, src) {
|
|
693
|
+
const fullPath = path6.resolve(rootDir, src);
|
|
694
|
+
if (!fs3.existsSync(fullPath)) {
|
|
695
|
+
return src;
|
|
696
|
+
}
|
|
697
|
+
const realpath = fs3.realpathSync(path6.resolve(rootDir, src));
|
|
698
|
+
return path6.relative(rootDir, realpath);
|
|
699
|
+
}
|
|
363
700
|
var BuildAsset = class {
|
|
364
|
-
constructor(assetMap,
|
|
701
|
+
constructor(assetMap, assetData) {
|
|
365
702
|
this.assetMap = assetMap;
|
|
366
|
-
this.
|
|
367
|
-
this.
|
|
368
|
-
this.
|
|
369
|
-
this.
|
|
370
|
-
this.
|
|
703
|
+
this.src = assetData.src;
|
|
704
|
+
this.assetUrl = assetData.assetUrl;
|
|
705
|
+
this.importedModules = assetData.importedModules;
|
|
706
|
+
this.importedCss = assetData.importedCss;
|
|
707
|
+
this.isElement = assetData.isElement;
|
|
371
708
|
}
|
|
372
709
|
async getCssDeps() {
|
|
373
710
|
const visited = /* @__PURE__ */ new Set();
|
|
@@ -385,21 +722,22 @@ var BuildAsset = class {
|
|
|
385
722
|
if (!asset) {
|
|
386
723
|
return;
|
|
387
724
|
}
|
|
388
|
-
if (!asset.
|
|
725
|
+
if (!asset.src) {
|
|
389
726
|
return;
|
|
390
727
|
}
|
|
391
|
-
if (visited.has(asset.
|
|
728
|
+
if (visited.has(asset.src)) {
|
|
392
729
|
return;
|
|
393
730
|
}
|
|
394
|
-
visited.add(asset.
|
|
395
|
-
|
|
396
|
-
if ([".js", ".jsx", ".ts", ".tsx"].includes(parts.ext) && asset.moduleId.includes("/elements/")) {
|
|
731
|
+
visited.add(asset.src);
|
|
732
|
+
if (asset.isElement) {
|
|
397
733
|
urls.add(asset.assetUrl);
|
|
398
734
|
}
|
|
399
|
-
await Promise.all(
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
735
|
+
await Promise.all(
|
|
736
|
+
asset.importedModules.map(async (src) => {
|
|
737
|
+
const importedAsset = await this.assetMap.get(src);
|
|
738
|
+
this.collectJs(importedAsset, urls, visited);
|
|
739
|
+
})
|
|
740
|
+
);
|
|
403
741
|
}
|
|
404
742
|
async collectCss(asset, urls, visited) {
|
|
405
743
|
if (!asset) {
|
|
@@ -408,94 +746,103 @@ var BuildAsset = class {
|
|
|
408
746
|
if (!asset.assetUrl) {
|
|
409
747
|
return;
|
|
410
748
|
}
|
|
411
|
-
if (visited.has(asset.
|
|
749
|
+
if (visited.has(asset.src)) {
|
|
412
750
|
return;
|
|
413
751
|
}
|
|
414
|
-
visited.add(asset.
|
|
752
|
+
visited.add(asset.src);
|
|
415
753
|
if (asset.importedCss) {
|
|
416
754
|
asset.importedCss.forEach((cssUrl) => urls.add(cssUrl));
|
|
417
755
|
}
|
|
418
|
-
await Promise.all(
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
756
|
+
await Promise.all(
|
|
757
|
+
asset.importedModules.map(async (moduleId) => {
|
|
758
|
+
const importedAsset = await this.assetMap.get(moduleId);
|
|
759
|
+
this.collectCss(importedAsset, urls, visited);
|
|
760
|
+
})
|
|
761
|
+
);
|
|
422
762
|
}
|
|
423
763
|
toJson() {
|
|
424
764
|
return {
|
|
425
|
-
|
|
765
|
+
src: this.src,
|
|
426
766
|
assetUrl: this.assetUrl,
|
|
427
767
|
importedModules: this.importedModules,
|
|
428
|
-
importedCss: this.importedCss
|
|
768
|
+
importedCss: this.importedCss,
|
|
769
|
+
isElement: this.isElement
|
|
429
770
|
};
|
|
430
771
|
}
|
|
431
772
|
};
|
|
432
773
|
|
|
433
774
|
// src/cli/commands/build.ts
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
}
|
|
775
|
+
import { dim as dim2, cyan } from "kleur/colors";
|
|
776
|
+
var __dirname2 = path7.dirname(fileURLToPath2(import.meta.url));
|
|
777
|
+
async function build(rootProjectDir, options) {
|
|
778
|
+
var _a, _b, _c, _d;
|
|
779
|
+
const rootDir = path7.resolve(rootProjectDir || process.cwd());
|
|
440
780
|
const rootConfig = await loadRootConfig(rootDir);
|
|
441
|
-
const distDir =
|
|
781
|
+
const distDir = path7.join(rootDir, "dist");
|
|
782
|
+
const ssrOnly = (options == null ? void 0 : options.ssrOnly) || false;
|
|
783
|
+
const mode = (options == null ? void 0 : options.mode) || "production";
|
|
784
|
+
console.log();
|
|
785
|
+
console.log(`${dim2("\u2503")} project: ${rootDir}`);
|
|
786
|
+
console.log(`${dim2("\u2503")} output: ${distDir}/html`);
|
|
787
|
+
console.log(`${dim2("\u2503")} mode: ${mode}`);
|
|
788
|
+
console.log();
|
|
442
789
|
await rmDir(distDir);
|
|
443
790
|
await makeDir(distDir);
|
|
444
|
-
const
|
|
445
|
-
if (await isDirectory(
|
|
446
|
-
const pageFiles = await glob3(
|
|
791
|
+
const routeFiles = [];
|
|
792
|
+
if (await isDirectory(path7.join(rootDir, "routes"))) {
|
|
793
|
+
const pageFiles = await glob3("routes/**/*", { cwd: rootDir });
|
|
447
794
|
pageFiles.forEach((file) => {
|
|
448
|
-
const parts =
|
|
795
|
+
const parts = path7.parse(file);
|
|
449
796
|
if (!parts.name.startsWith("_") && isJsFile(parts.base)) {
|
|
450
|
-
|
|
451
|
-
}
|
|
452
|
-
});
|
|
453
|
-
}
|
|
454
|
-
const elements = [];
|
|
455
|
-
if (await isDirectory(path6.join(rootDir, "elements"))) {
|
|
456
|
-
const elementFiles = await glob3(path6.join(rootDir, "elements/**/*"));
|
|
457
|
-
elementFiles.forEach((file) => {
|
|
458
|
-
const parts = path6.parse(file);
|
|
459
|
-
if (isJsFile(parts.base)) {
|
|
460
|
-
elements.push(file);
|
|
797
|
+
routeFiles.push(path7.resolve(rootDir, file));
|
|
461
798
|
}
|
|
462
799
|
});
|
|
463
800
|
}
|
|
801
|
+
const elementsMap = await getElements(rootConfig);
|
|
802
|
+
const elements = Object.values(elementsMap).map(
|
|
803
|
+
(mod) => path7.resolve(rootDir, mod.src)
|
|
804
|
+
);
|
|
464
805
|
const bundleScripts = [];
|
|
465
|
-
if (await isDirectory(
|
|
466
|
-
const bundleFiles = await glob3(
|
|
806
|
+
if (await isDirectory(path7.join(rootDir, "bundles"))) {
|
|
807
|
+
const bundleFiles = await glob3("bundles/*", { cwd: rootDir });
|
|
467
808
|
bundleFiles.forEach((file) => {
|
|
468
|
-
const parts =
|
|
809
|
+
const parts = path7.parse(file);
|
|
469
810
|
if (isJsFile(parts.base)) {
|
|
470
|
-
bundleScripts.push(file);
|
|
811
|
+
bundleScripts.push(path7.resolve(rootDir, file));
|
|
471
812
|
}
|
|
472
813
|
});
|
|
473
814
|
}
|
|
474
815
|
const viteConfig = rootConfig.vite || {};
|
|
816
|
+
const vitePlugins = [
|
|
817
|
+
pluginRoot({ rootConfig }),
|
|
818
|
+
...viteConfig.plugins || [],
|
|
819
|
+
...getVitePlugins(rootConfig.plugins || [])
|
|
820
|
+
];
|
|
475
821
|
const baseConfig = {
|
|
476
822
|
...viteConfig,
|
|
477
823
|
root: rootDir,
|
|
824
|
+
mode,
|
|
478
825
|
esbuild: {
|
|
479
826
|
jsx: "automatic",
|
|
480
827
|
jsxImportSource: "preact",
|
|
481
828
|
treeShaking: true
|
|
482
829
|
},
|
|
483
|
-
plugins:
|
|
830
|
+
plugins: vitePlugins
|
|
484
831
|
};
|
|
485
832
|
await viteBuild({
|
|
486
833
|
...baseConfig,
|
|
487
|
-
mode: "production",
|
|
488
834
|
publicDir: false,
|
|
489
835
|
build: {
|
|
490
836
|
rollupOptions: {
|
|
491
|
-
|
|
837
|
+
...(_a = viteConfig == null ? void 0 : viteConfig.build) == null ? void 0 : _a.rollupOptions,
|
|
838
|
+
input: [path7.resolve(__dirname2, "./render.js")],
|
|
492
839
|
output: {
|
|
493
840
|
format: "esm",
|
|
494
|
-
chunkFileNames: "chunks/[name].[hash].js",
|
|
841
|
+
chunkFileNames: "chunks/[name].[hash].min.js",
|
|
495
842
|
assetFileNames: "assets/[name].[hash][extname]"
|
|
496
843
|
}
|
|
497
844
|
},
|
|
498
|
-
outDir:
|
|
845
|
+
outDir: path7.join(distDir, "server"),
|
|
499
846
|
ssr: true,
|
|
500
847
|
ssrManifest: false,
|
|
501
848
|
cssCodeSplit: true,
|
|
@@ -510,18 +857,20 @@ async function build(rootDir) {
|
|
|
510
857
|
});
|
|
511
858
|
await viteBuild({
|
|
512
859
|
...baseConfig,
|
|
513
|
-
mode: "production",
|
|
514
860
|
publicDir: false,
|
|
515
861
|
build: {
|
|
516
862
|
rollupOptions: {
|
|
517
|
-
|
|
863
|
+
...(_b = viteConfig == null ? void 0 : viteConfig.build) == null ? void 0 : _b.rollupOptions,
|
|
864
|
+
input: [...routeFiles, ...elements, ...bundleScripts],
|
|
518
865
|
output: {
|
|
519
866
|
format: "esm",
|
|
520
|
-
|
|
521
|
-
|
|
867
|
+
entryFileNames: "assets/[name].[hash].min.js",
|
|
868
|
+
chunkFileNames: "chunks/[name].[hash].min.js",
|
|
869
|
+
assetFileNames: "assets/[name].[hash][extname]",
|
|
870
|
+
...(_d = (_c = viteConfig == null ? void 0 : viteConfig.build) == null ? void 0 : _c.rollupOptions) == null ? void 0 : _d.output
|
|
522
871
|
}
|
|
523
872
|
},
|
|
524
|
-
outDir:
|
|
873
|
+
outDir: path7.join(distDir, "client"),
|
|
525
874
|
ssr: false,
|
|
526
875
|
ssrManifest: false,
|
|
527
876
|
manifest: true,
|
|
@@ -532,45 +881,282 @@ async function build(rootDir) {
|
|
|
532
881
|
reportCompressedSize: false
|
|
533
882
|
}
|
|
534
883
|
});
|
|
535
|
-
const
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
const
|
|
539
|
-
|
|
540
|
-
|
|
884
|
+
const viteManifest = await loadJson(
|
|
885
|
+
path7.join(distDir, "client/manifest.json")
|
|
886
|
+
);
|
|
887
|
+
const assetMap = BuildAssetMap.fromViteManifest(
|
|
888
|
+
rootConfig,
|
|
889
|
+
viteManifest,
|
|
890
|
+
elementsMap
|
|
891
|
+
);
|
|
892
|
+
const rootManifest = assetMap.toJson();
|
|
893
|
+
writeFile(
|
|
894
|
+
path7.join(distDir, "client/root-manifest.json"),
|
|
895
|
+
JSON.stringify(rootManifest, null, 2)
|
|
896
|
+
);
|
|
897
|
+
const buildDir = path7.join(distDir, "html");
|
|
898
|
+
const publicDir = path7.join(rootDir, "public");
|
|
899
|
+
if (fsExtra2.existsSync(path7.join(rootDir, "public"))) {
|
|
541
900
|
fsExtra2.copySync(publicDir, buildDir);
|
|
542
901
|
} else {
|
|
543
902
|
makeDir(buildDir);
|
|
544
903
|
}
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
const
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
904
|
+
console.log("\njs/css output:");
|
|
905
|
+
makeDir(path7.join(buildDir, "assets"));
|
|
906
|
+
makeDir(path7.join(buildDir, "chunks"));
|
|
907
|
+
Object.keys(rootManifest).forEach((src) => {
|
|
908
|
+
if (isRouteFile(src)) {
|
|
909
|
+
return;
|
|
910
|
+
}
|
|
911
|
+
const assetData = rootManifest[src];
|
|
912
|
+
const assetRelPath = assetData.assetUrl.slice(1);
|
|
913
|
+
const assetFrom = path7.join(distDir, "client", assetRelPath);
|
|
914
|
+
const assetTo = path7.join(buildDir, assetRelPath);
|
|
915
|
+
fsExtra2.copySync(assetFrom, assetTo);
|
|
916
|
+
printFileOutput(fileSize(assetTo), "dist/html/", assetRelPath);
|
|
917
|
+
});
|
|
918
|
+
if (!ssrOnly) {
|
|
919
|
+
const render = await import(path7.join(distDir, "server/render.js"));
|
|
920
|
+
const renderer = new render.Renderer(rootConfig, { assetMap });
|
|
921
|
+
const sitemap = await renderer.getSitemap();
|
|
922
|
+
console.log("\nhtml output:");
|
|
923
|
+
await Promise.all(
|
|
924
|
+
Object.keys(sitemap).map(async (urlPath) => {
|
|
925
|
+
const { route, params } = sitemap[urlPath];
|
|
926
|
+
const data = await renderer.renderRoute(route, {
|
|
927
|
+
routeParams: params
|
|
928
|
+
});
|
|
929
|
+
let outFilePath = path7.join(urlPath.slice(1), "index.html");
|
|
930
|
+
if (outFilePath.endsWith("404/index.html")) {
|
|
931
|
+
outFilePath = outFilePath.replace("404/index.html", "404.html");
|
|
932
|
+
}
|
|
933
|
+
const outPath = path7.join(buildDir, outFilePath);
|
|
934
|
+
let html = data.html || "";
|
|
935
|
+
if (rootConfig.prettyHtml !== false) {
|
|
936
|
+
html = await htmlPretty(html, rootConfig.prettyHtmlOptions);
|
|
937
|
+
}
|
|
938
|
+
if (rootConfig.minifyHtml !== false) {
|
|
939
|
+
html = await htmlMinify(html, rootConfig.minifyHtmlOptions);
|
|
940
|
+
}
|
|
941
|
+
await writeFile(outPath, html);
|
|
942
|
+
printFileOutput(fileSize(outPath), "dist/html/", outFilePath);
|
|
943
|
+
})
|
|
944
|
+
);
|
|
945
|
+
}
|
|
946
|
+
}
|
|
947
|
+
function isRouteFile(filepath) {
|
|
948
|
+
return filepath.startsWith("routes") && isJsFile(filepath);
|
|
949
|
+
}
|
|
950
|
+
function fileSize(filepath) {
|
|
951
|
+
const stats = fsExtra2.statSync(filepath);
|
|
952
|
+
const bytes = stats.size;
|
|
953
|
+
const k = 1024;
|
|
954
|
+
if (bytes < k) {
|
|
955
|
+
return (bytes / k).toFixed(2) + " kB";
|
|
956
|
+
}
|
|
957
|
+
const units = ["B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
|
|
958
|
+
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
959
|
+
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + " " + units[i];
|
|
960
|
+
}
|
|
961
|
+
function printFileOutput(fileSize2, outputDir, outputFile) {
|
|
962
|
+
const indent = " ".repeat(2);
|
|
963
|
+
const paddedSize = fileSize2.padStart(9, " ");
|
|
964
|
+
console.log(
|
|
965
|
+
`${indent}${dim2(paddedSize)} ${dim2(outputDir)}${cyan(outputFile)}`
|
|
966
|
+
);
|
|
967
|
+
}
|
|
968
|
+
|
|
969
|
+
// src/cli/commands/preview.ts
|
|
970
|
+
import path8 from "node:path";
|
|
971
|
+
import { default as express2 } from "express";
|
|
972
|
+
import { dim as dim3 } from "kleur/colors";
|
|
973
|
+
import sirv from "sirv";
|
|
974
|
+
import compression from "compression";
|
|
975
|
+
async function preview(rootProjectDir) {
|
|
976
|
+
process.env.NODE_ENV = "development";
|
|
977
|
+
const rootDir = path8.resolve(rootProjectDir || process.cwd());
|
|
978
|
+
const server = await createServer3({ rootDir });
|
|
979
|
+
const port = parseInt(process.env.PORT || "4007");
|
|
980
|
+
console.log();
|
|
981
|
+
console.log(`${dim3("\u2503")} project: ${rootDir}`);
|
|
982
|
+
console.log(`${dim3("\u2503")} server: http://localhost:${port}`);
|
|
983
|
+
console.log(`${dim3("\u2503")} mode: staging`);
|
|
984
|
+
console.log();
|
|
985
|
+
server.listen(port);
|
|
986
|
+
}
|
|
987
|
+
async function createServer3(options) {
|
|
988
|
+
const rootDir = options.rootDir;
|
|
989
|
+
const rootConfig = await loadRootConfig(rootDir);
|
|
990
|
+
const distDir = path8.join(rootDir, "dist");
|
|
991
|
+
const server = express2();
|
|
992
|
+
server.disable("x-powered-by");
|
|
993
|
+
server.use(compression());
|
|
994
|
+
server.use(rootProjectMiddleware({ rootDir, rootConfig }));
|
|
995
|
+
server.use(await rootPreviewRendererMiddleware({ rootConfig, distDir }));
|
|
996
|
+
const plugins = rootConfig.plugins || [];
|
|
997
|
+
configureServerPlugins(
|
|
998
|
+
server,
|
|
999
|
+
async () => {
|
|
1000
|
+
var _a;
|
|
1001
|
+
const userMiddlewares = ((_a = rootConfig.server) == null ? void 0 : _a.middlewares) || [];
|
|
1002
|
+
userMiddlewares.forEach((middleware) => {
|
|
1003
|
+
server.use(middleware);
|
|
1004
|
+
});
|
|
1005
|
+
const publicDir = path8.join(distDir, "html");
|
|
1006
|
+
server.use(sirv(publicDir, { dev: false }));
|
|
1007
|
+
server.use(rootPreviewServerMiddleware());
|
|
1008
|
+
},
|
|
1009
|
+
plugins,
|
|
1010
|
+
{ type: "preview" }
|
|
1011
|
+
);
|
|
1012
|
+
return server;
|
|
1013
|
+
}
|
|
1014
|
+
async function rootPreviewRendererMiddleware(options) {
|
|
1015
|
+
const { distDir, rootConfig } = options;
|
|
1016
|
+
const render = await import(path8.join(distDir, "server/render.js"));
|
|
1017
|
+
const manifestPath = path8.join(distDir, "client/root-manifest.json");
|
|
1018
|
+
if (!await fileExists(manifestPath)) {
|
|
1019
|
+
throw new Error(
|
|
1020
|
+
`could not find ${manifestPath}. run \`root build\` before \`root preview\`.`
|
|
1021
|
+
);
|
|
1022
|
+
}
|
|
1023
|
+
const rootManifest = await loadJson(manifestPath);
|
|
1024
|
+
const assetMap = BuildAssetMap.fromRootManifest(rootConfig, rootManifest);
|
|
1025
|
+
const renderer = new render.Renderer(rootConfig, { assetMap });
|
|
1026
|
+
return async (req, _, next) => {
|
|
1027
|
+
req.renderer = renderer;
|
|
1028
|
+
next();
|
|
1029
|
+
};
|
|
1030
|
+
}
|
|
1031
|
+
function rootPreviewServerMiddleware() {
|
|
1032
|
+
return async (req, res, next) => {
|
|
1033
|
+
const rootConfig = req.rootConfig;
|
|
1034
|
+
const renderer = req.renderer;
|
|
1035
|
+
try {
|
|
1036
|
+
const url = req.path;
|
|
1037
|
+
const data = await renderer.render(url);
|
|
1038
|
+
if (data.notFound || !data.html) {
|
|
1039
|
+
next();
|
|
1040
|
+
return;
|
|
1041
|
+
}
|
|
1042
|
+
let html = data.html || "";
|
|
1043
|
+
if (rootConfig.prettyHtml !== false) {
|
|
1044
|
+
html = await htmlPretty(html, rootConfig.prettyHtmlOptions);
|
|
1045
|
+
}
|
|
1046
|
+
if (rootConfig.minifyHtml !== false) {
|
|
1047
|
+
html = await htmlMinify(html, rootConfig.minifyHtmlOptions);
|
|
1048
|
+
}
|
|
1049
|
+
res.status(200).set({ "Content-Type": "text/html" }).end(html);
|
|
1050
|
+
} catch (e) {
|
|
1051
|
+
try {
|
|
1052
|
+
const { html } = await renderer.renderError(e);
|
|
1053
|
+
res.status(500).set({ "Content-Type": "text/html" }).end(html);
|
|
1054
|
+
} catch (e2) {
|
|
1055
|
+
console.error("failed to render custom error");
|
|
1056
|
+
console.error(e2);
|
|
1057
|
+
next(e);
|
|
1058
|
+
}
|
|
559
1059
|
}
|
|
560
|
-
|
|
561
|
-
await writeFile(outPath, html);
|
|
562
|
-
const relPath = outPath.slice(path6.dirname(distDir).length + 1);
|
|
563
|
-
console.log(`saved ${relPath}`);
|
|
564
|
-
}));
|
|
1060
|
+
};
|
|
565
1061
|
}
|
|
566
1062
|
|
|
567
1063
|
// src/cli/commands/start.ts
|
|
568
|
-
|
|
569
|
-
|
|
1064
|
+
import path9 from "node:path";
|
|
1065
|
+
import { default as express3 } from "express";
|
|
1066
|
+
import { dim as dim4 } from "kleur/colors";
|
|
1067
|
+
import sirv2 from "sirv";
|
|
1068
|
+
import compression2 from "compression";
|
|
1069
|
+
async function start(rootProjectDir) {
|
|
1070
|
+
process.env.NODE_ENV = "production";
|
|
1071
|
+
const rootDir = path9.resolve(rootProjectDir || process.cwd());
|
|
1072
|
+
const server = await createServer4({ rootDir });
|
|
1073
|
+
const port = parseInt(process.env.PORT || "4007");
|
|
1074
|
+
console.log();
|
|
1075
|
+
console.log(`${dim4("\u2503")} project: ${rootDir}`);
|
|
1076
|
+
console.log(`${dim4("\u2503")} server: http://localhost:${port}`);
|
|
1077
|
+
console.log(`${dim4("\u2503")} mode: production`);
|
|
1078
|
+
console.log();
|
|
1079
|
+
server.listen(port);
|
|
1080
|
+
}
|
|
1081
|
+
async function createServer4(options) {
|
|
1082
|
+
const rootDir = options.rootDir;
|
|
1083
|
+
const rootConfig = await loadRootConfig(rootDir);
|
|
1084
|
+
const distDir = path9.join(rootDir, "dist");
|
|
1085
|
+
const server = express3();
|
|
1086
|
+
server.disable("x-powered-by");
|
|
1087
|
+
server.use(compression2());
|
|
1088
|
+
server.use(rootProjectMiddleware({ rootDir, rootConfig }));
|
|
1089
|
+
server.use(await rootProdRendererMiddleware({ rootConfig, distDir }));
|
|
1090
|
+
const plugins = rootConfig.plugins || [];
|
|
1091
|
+
configureServerPlugins(
|
|
1092
|
+
server,
|
|
1093
|
+
async () => {
|
|
1094
|
+
var _a;
|
|
1095
|
+
const userMiddlewares = ((_a = rootConfig.server) == null ? void 0 : _a.middlewares) || [];
|
|
1096
|
+
userMiddlewares.forEach((middleware) => {
|
|
1097
|
+
server.use(middleware);
|
|
1098
|
+
});
|
|
1099
|
+
const publicDir = path9.join(distDir, "html");
|
|
1100
|
+
server.use(sirv2(publicDir, { dev: false }));
|
|
1101
|
+
server.use(rootProdServerMiddleware());
|
|
1102
|
+
},
|
|
1103
|
+
plugins,
|
|
1104
|
+
{ type: "prod" }
|
|
1105
|
+
);
|
|
1106
|
+
return server;
|
|
1107
|
+
}
|
|
1108
|
+
async function rootProdRendererMiddleware(options) {
|
|
1109
|
+
const { distDir, rootConfig } = options;
|
|
1110
|
+
const render = await import(path9.join(distDir, "server/render.js"));
|
|
1111
|
+
const manifestPath = path9.join(distDir, "client/root-manifest.json");
|
|
1112
|
+
if (!await fileExists(manifestPath)) {
|
|
1113
|
+
throw new Error(
|
|
1114
|
+
`could not find ${manifestPath}. run \`root build\` before \`root preview\`.`
|
|
1115
|
+
);
|
|
1116
|
+
}
|
|
1117
|
+
const rootManifest = await loadJson(manifestPath);
|
|
1118
|
+
const assetMap = BuildAssetMap.fromRootManifest(rootConfig, rootManifest);
|
|
1119
|
+
const renderer = new render.Renderer(rootConfig, { assetMap });
|
|
1120
|
+
return async (req, _, next) => {
|
|
1121
|
+
req.renderer = renderer;
|
|
1122
|
+
next();
|
|
1123
|
+
};
|
|
1124
|
+
}
|
|
1125
|
+
function rootProdServerMiddleware() {
|
|
1126
|
+
return async (req, res, next) => {
|
|
1127
|
+
const rootConfig = req.rootConfig;
|
|
1128
|
+
const renderer = req.renderer;
|
|
1129
|
+
try {
|
|
1130
|
+
const url = req.path;
|
|
1131
|
+
const data = await renderer.render(url);
|
|
1132
|
+
if (data.notFound || !data.html) {
|
|
1133
|
+
next();
|
|
1134
|
+
return;
|
|
1135
|
+
}
|
|
1136
|
+
let html = data.html || "";
|
|
1137
|
+
if (rootConfig.prettyHtml !== false) {
|
|
1138
|
+
html = await htmlPretty(html, rootConfig.prettyHtmlOptions);
|
|
1139
|
+
}
|
|
1140
|
+
if (rootConfig.minifyHtml !== false) {
|
|
1141
|
+
html = await htmlMinify(html, rootConfig.minifyHtmlOptions);
|
|
1142
|
+
}
|
|
1143
|
+
res.status(200).set({ "Content-Type": "text/html" }).end(html);
|
|
1144
|
+
} catch (e) {
|
|
1145
|
+
try {
|
|
1146
|
+
const { html } = await renderer.renderError(e);
|
|
1147
|
+
res.status(500).set({ "Content-Type": "text/html" }).end(html);
|
|
1148
|
+
} catch (e2) {
|
|
1149
|
+
console.error("failed to render custom error");
|
|
1150
|
+
console.error(e2);
|
|
1151
|
+
next(e);
|
|
1152
|
+
}
|
|
1153
|
+
}
|
|
1154
|
+
};
|
|
570
1155
|
}
|
|
571
1156
|
export {
|
|
572
1157
|
build,
|
|
573
1158
|
dev,
|
|
1159
|
+
preview,
|
|
574
1160
|
start
|
|
575
1161
|
};
|
|
576
1162
|
//# sourceMappingURL=cli.js.map
|