@blinkk/root 1.0.0-alpha.3 → 1.0.0-alpha.31
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-BCRXWKTP.js +156 -0
- package/dist/chunk-BCRXWKTP.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 +812 -207
- 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 +0 -96
- 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,103 +338,269 @@ 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, _c;
|
|
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
|
}
|
|
287
501
|
});
|
|
288
502
|
}
|
|
503
|
+
const noExternalConfig = (_b = viteConfig.ssr) == null ? void 0 : _b.noExternal;
|
|
504
|
+
const noExternal = [];
|
|
505
|
+
if (noExternalConfig) {
|
|
506
|
+
if (Array.isArray(noExternalConfig)) {
|
|
507
|
+
noExternal.push(...noExternalConfig);
|
|
508
|
+
} else {
|
|
509
|
+
noExternal.push(noExternalConfig);
|
|
510
|
+
}
|
|
511
|
+
}
|
|
289
512
|
const viteServer = await createViteServer({
|
|
290
513
|
...viteConfig,
|
|
291
|
-
|
|
514
|
+
mode: "development",
|
|
515
|
+
root: rootDir,
|
|
516
|
+
publicDir: path5.join(rootDir, "public"),
|
|
517
|
+
server: {
|
|
518
|
+
...viteConfig.server || {},
|
|
519
|
+
middlewareMode: true,
|
|
520
|
+
hmr: hmrOptions
|
|
521
|
+
},
|
|
292
522
|
appType: "custom",
|
|
293
523
|
optimizeDeps: {
|
|
294
|
-
|
|
524
|
+
...viteConfig.optimizeDeps || {},
|
|
525
|
+
include: [
|
|
526
|
+
...routeFiles,
|
|
527
|
+
...elements,
|
|
528
|
+
...bundleScripts,
|
|
529
|
+
...((_c = viteConfig.optimizeDeps) == null ? void 0 : _c.include) || []
|
|
530
|
+
]
|
|
295
531
|
},
|
|
296
532
|
ssr: {
|
|
297
|
-
|
|
533
|
+
...viteConfig.ssr || {},
|
|
534
|
+
noExternal: ["@blinkk/root", ...noExternal]
|
|
298
535
|
},
|
|
299
536
|
esbuild: {
|
|
537
|
+
...viteConfig.esbuild || {},
|
|
300
538
|
jsx: "automatic",
|
|
301
539
|
jsxImportSource: "preact"
|
|
302
540
|
},
|
|
303
|
-
plugins: [
|
|
541
|
+
plugins: [
|
|
542
|
+
await pluginRoot({ rootConfig }),
|
|
543
|
+
...viteConfig.plugins || [],
|
|
544
|
+
...getVitePlugins(rootConfig.plugins || [])
|
|
545
|
+
]
|
|
304
546
|
});
|
|
305
|
-
|
|
306
|
-
const url = req.originalUrl;
|
|
307
|
-
const render = await viteServer.ssrLoadModule(renderModulePath);
|
|
308
|
-
const renderer = new render.Renderer(rootConfig);
|
|
547
|
+
return async (req, res, next) => {
|
|
309
548
|
try {
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
549
|
+
req.viteServer = viteServer;
|
|
550
|
+
viteServer.middlewares(req, res, next);
|
|
551
|
+
} catch (e) {
|
|
552
|
+
next(e);
|
|
553
|
+
}
|
|
554
|
+
};
|
|
555
|
+
}
|
|
556
|
+
function rootDevRendererMiddleware() {
|
|
557
|
+
const renderModulePath = path5.resolve(__dirname, "./render.js");
|
|
558
|
+
return async (req, _, next) => {
|
|
559
|
+
const rootConfig = req.rootConfig;
|
|
560
|
+
const viteServer = req.viteServer;
|
|
561
|
+
try {
|
|
562
|
+
const render = await viteServer.ssrLoadModule(renderModulePath);
|
|
563
|
+
const assetMap = new DevServerAssetMap(
|
|
564
|
+
rootConfig,
|
|
565
|
+
viteServer.moduleGraph
|
|
566
|
+
);
|
|
567
|
+
req.renderer = new render.Renderer(rootConfig, { assetMap });
|
|
568
|
+
next();
|
|
569
|
+
} catch (e) {
|
|
570
|
+
next(e);
|
|
571
|
+
}
|
|
572
|
+
};
|
|
573
|
+
}
|
|
574
|
+
function rootDevServerMiddleware() {
|
|
575
|
+
return async (req, res, next) => {
|
|
576
|
+
const url = req.path;
|
|
577
|
+
const renderer = req.renderer;
|
|
578
|
+
const viteServer = req.viteServer;
|
|
579
|
+
const rootConfig = req.rootConfig;
|
|
580
|
+
try {
|
|
581
|
+
const data = await renderer.render(url);
|
|
582
|
+
if (data.notFound || !data.html) {
|
|
583
|
+
next();
|
|
584
|
+
return;
|
|
585
|
+
}
|
|
586
|
+
let html = await viteServer.transformIndexHtml(url, data.html || "");
|
|
587
|
+
if (rootConfig.prettyHtml !== false) {
|
|
588
|
+
html = await htmlPretty(html, rootConfig.prettyHtmlOptions);
|
|
589
|
+
}
|
|
590
|
+
if (rootConfig.minifyHtml !== false) {
|
|
591
|
+
html = await htmlMinify(html, rootConfig.minifyHtmlOptions);
|
|
592
|
+
}
|
|
315
593
|
res.status(200).set({ "Content-Type": "text/html" }).end(html);
|
|
316
594
|
} catch (e) {
|
|
317
595
|
viteServer.ssrFixStacktrace(e);
|
|
596
|
+
console.error(e);
|
|
318
597
|
try {
|
|
319
|
-
|
|
320
|
-
|
|
598
|
+
if (renderer) {
|
|
599
|
+
const { html } = await renderer.renderError(e);
|
|
600
|
+
res.status(500).set({ "Content-Type": "text/html" }).end(html);
|
|
601
|
+
} else {
|
|
602
|
+
next(e);
|
|
603
|
+
}
|
|
321
604
|
} catch (e2) {
|
|
322
605
|
console.error("failed to render custom error");
|
|
323
606
|
console.error(e2);
|
|
@@ -325,49 +608,112 @@ async function getMiddlewares(options) {
|
|
|
325
608
|
}
|
|
326
609
|
}
|
|
327
610
|
};
|
|
328
|
-
return [viteServer.middlewares, rootMiddleware];
|
|
329
611
|
}
|
|
330
|
-
function
|
|
331
|
-
|
|
612
|
+
function rootDevServer404Middleware() {
|
|
613
|
+
return async (req, res) => {
|
|
614
|
+
const url = req.path;
|
|
615
|
+
const ext = path5.extname(url);
|
|
616
|
+
const renderer = req.renderer;
|
|
617
|
+
if (!ext) {
|
|
618
|
+
const data = await renderer.renderDevServer404();
|
|
619
|
+
const html = data.html || "";
|
|
620
|
+
res.status(404).set({ "Content-Type": "text/html" }).end(html);
|
|
621
|
+
return;
|
|
622
|
+
}
|
|
623
|
+
res.status(404).set({ "Content-Type": "text/plain" }).end("404");
|
|
624
|
+
};
|
|
332
625
|
}
|
|
333
626
|
|
|
334
627
|
// src/cli/commands/build.ts
|
|
335
|
-
import
|
|
628
|
+
import path7 from "node:path";
|
|
336
629
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
337
630
|
import fsExtra2 from "fs-extra";
|
|
338
631
|
import glob3 from "tiny-glob";
|
|
339
632
|
import { build as viteBuild } from "vite";
|
|
340
633
|
|
|
341
634
|
// src/render/asset-map/build-asset-map.ts
|
|
342
|
-
import
|
|
635
|
+
import fs3 from "node:fs";
|
|
636
|
+
import path6 from "node:path";
|
|
343
637
|
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
|
-
});
|
|
638
|
+
constructor(rootConfig) {
|
|
639
|
+
this.rootConfig = rootConfig;
|
|
640
|
+
this.srcToAsset = /* @__PURE__ */ new Map();
|
|
351
641
|
}
|
|
352
|
-
async get(
|
|
353
|
-
|
|
642
|
+
async get(src) {
|
|
643
|
+
const asset = this.srcToAsset.get(src);
|
|
644
|
+
if (asset) {
|
|
645
|
+
return asset;
|
|
646
|
+
}
|
|
647
|
+
const realSrc = realPathRelativeTo(this.rootConfig.rootDir, src);
|
|
648
|
+
if (realSrc !== src) {
|
|
649
|
+
const asset2 = this.srcToAsset.get(realSrc);
|
|
650
|
+
if (asset2) {
|
|
651
|
+
return asset2;
|
|
652
|
+
}
|
|
653
|
+
}
|
|
654
|
+
console.log(`could not find build asset: ${src}`);
|
|
655
|
+
return null;
|
|
656
|
+
}
|
|
657
|
+
add(asset) {
|
|
658
|
+
this.srcToAsset.set(asset.src, asset);
|
|
354
659
|
}
|
|
355
660
|
toJson() {
|
|
356
661
|
const result = {};
|
|
357
|
-
for (const
|
|
358
|
-
result[
|
|
662
|
+
for (const src of this.srcToAsset.keys()) {
|
|
663
|
+
result[src] = this.srcToAsset.get(src).toJson();
|
|
359
664
|
}
|
|
360
665
|
return result;
|
|
361
666
|
}
|
|
667
|
+
static fromViteManifest(rootConfig, viteManifest, elementMap) {
|
|
668
|
+
const assetMap = new BuildAssetMap(rootConfig);
|
|
669
|
+
const elementFiles = /* @__PURE__ */ new Set();
|
|
670
|
+
Object.values(elementMap).forEach((elementModule) => {
|
|
671
|
+
elementFiles.add(elementModule.src);
|
|
672
|
+
const realSrc = realPathRelativeTo(rootConfig.rootDir, elementModule.src);
|
|
673
|
+
if (realSrc !== elementModule.src) {
|
|
674
|
+
elementFiles.add(realSrc);
|
|
675
|
+
}
|
|
676
|
+
});
|
|
677
|
+
Object.keys(viteManifest).forEach((manifestKey) => {
|
|
678
|
+
const src = manifestKey;
|
|
679
|
+
const manifestChunk = viteManifest[manifestKey];
|
|
680
|
+
const isElement = elementFiles.has(src);
|
|
681
|
+
const assetData = {
|
|
682
|
+
src,
|
|
683
|
+
assetUrl: `/${manifestChunk.file}`,
|
|
684
|
+
importedModules: manifestChunk.imports || [],
|
|
685
|
+
importedCss: (manifestChunk.css || []).map((relPath) => `/${relPath}`),
|
|
686
|
+
isElement
|
|
687
|
+
};
|
|
688
|
+
assetMap.add(new BuildAsset(assetMap, assetData));
|
|
689
|
+
});
|
|
690
|
+
return assetMap;
|
|
691
|
+
}
|
|
692
|
+
static fromRootManifest(rootConfig, rootManifest) {
|
|
693
|
+
const assetMap = new BuildAssetMap(rootConfig);
|
|
694
|
+
Object.keys(rootManifest).forEach((moduleId) => {
|
|
695
|
+
const assetData = rootManifest[moduleId];
|
|
696
|
+
assetMap.add(new BuildAsset(assetMap, assetData));
|
|
697
|
+
});
|
|
698
|
+
return assetMap;
|
|
699
|
+
}
|
|
362
700
|
};
|
|
701
|
+
function realPathRelativeTo(rootDir, src) {
|
|
702
|
+
const fullPath = path6.resolve(rootDir, src);
|
|
703
|
+
if (!fs3.existsSync(fullPath)) {
|
|
704
|
+
return src;
|
|
705
|
+
}
|
|
706
|
+
const realpath = fs3.realpathSync(path6.resolve(rootDir, src));
|
|
707
|
+
return path6.relative(rootDir, realpath);
|
|
708
|
+
}
|
|
363
709
|
var BuildAsset = class {
|
|
364
|
-
constructor(assetMap,
|
|
710
|
+
constructor(assetMap, assetData) {
|
|
365
711
|
this.assetMap = assetMap;
|
|
366
|
-
this.
|
|
367
|
-
this.
|
|
368
|
-
this.
|
|
369
|
-
this.
|
|
370
|
-
this.
|
|
712
|
+
this.src = assetData.src;
|
|
713
|
+
this.assetUrl = assetData.assetUrl;
|
|
714
|
+
this.importedModules = assetData.importedModules;
|
|
715
|
+
this.importedCss = assetData.importedCss;
|
|
716
|
+
this.isElement = assetData.isElement;
|
|
371
717
|
}
|
|
372
718
|
async getCssDeps() {
|
|
373
719
|
const visited = /* @__PURE__ */ new Set();
|
|
@@ -385,21 +731,22 @@ var BuildAsset = class {
|
|
|
385
731
|
if (!asset) {
|
|
386
732
|
return;
|
|
387
733
|
}
|
|
388
|
-
if (!asset.
|
|
734
|
+
if (!asset.src) {
|
|
389
735
|
return;
|
|
390
736
|
}
|
|
391
|
-
if (visited.has(asset.
|
|
737
|
+
if (visited.has(asset.src)) {
|
|
392
738
|
return;
|
|
393
739
|
}
|
|
394
|
-
visited.add(asset.
|
|
395
|
-
|
|
396
|
-
if ([".js", ".jsx", ".ts", ".tsx"].includes(parts.ext) && asset.moduleId.includes("/elements/")) {
|
|
740
|
+
visited.add(asset.src);
|
|
741
|
+
if (asset.isElement) {
|
|
397
742
|
urls.add(asset.assetUrl);
|
|
398
743
|
}
|
|
399
|
-
await Promise.all(
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
744
|
+
await Promise.all(
|
|
745
|
+
asset.importedModules.map(async (src) => {
|
|
746
|
+
const importedAsset = await this.assetMap.get(src);
|
|
747
|
+
this.collectJs(importedAsset, urls, visited);
|
|
748
|
+
})
|
|
749
|
+
);
|
|
403
750
|
}
|
|
404
751
|
async collectCss(asset, urls, visited) {
|
|
405
752
|
if (!asset) {
|
|
@@ -408,94 +755,112 @@ var BuildAsset = class {
|
|
|
408
755
|
if (!asset.assetUrl) {
|
|
409
756
|
return;
|
|
410
757
|
}
|
|
411
|
-
if (visited.has(asset.
|
|
758
|
+
if (visited.has(asset.src)) {
|
|
412
759
|
return;
|
|
413
760
|
}
|
|
414
|
-
visited.add(asset.
|
|
761
|
+
visited.add(asset.src);
|
|
415
762
|
if (asset.importedCss) {
|
|
416
763
|
asset.importedCss.forEach((cssUrl) => urls.add(cssUrl));
|
|
417
764
|
}
|
|
418
|
-
await Promise.all(
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
765
|
+
await Promise.all(
|
|
766
|
+
asset.importedModules.map(async (moduleId) => {
|
|
767
|
+
const importedAsset = await this.assetMap.get(moduleId);
|
|
768
|
+
this.collectCss(importedAsset, urls, visited);
|
|
769
|
+
})
|
|
770
|
+
);
|
|
422
771
|
}
|
|
423
772
|
toJson() {
|
|
424
773
|
return {
|
|
425
|
-
|
|
774
|
+
src: this.src,
|
|
426
775
|
assetUrl: this.assetUrl,
|
|
427
776
|
importedModules: this.importedModules,
|
|
428
|
-
importedCss: this.importedCss
|
|
777
|
+
importedCss: this.importedCss,
|
|
778
|
+
isElement: this.isElement
|
|
429
779
|
};
|
|
430
780
|
}
|
|
431
781
|
};
|
|
432
782
|
|
|
433
783
|
// src/cli/commands/build.ts
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
}
|
|
784
|
+
import { dim as dim2, cyan } from "kleur/colors";
|
|
785
|
+
var __dirname2 = path7.dirname(fileURLToPath2(import.meta.url));
|
|
786
|
+
async function build(rootProjectDir, options) {
|
|
787
|
+
var _a, _b, _c, _d, _e;
|
|
788
|
+
const rootDir = path7.resolve(rootProjectDir || process.cwd());
|
|
440
789
|
const rootConfig = await loadRootConfig(rootDir);
|
|
441
|
-
const distDir =
|
|
790
|
+
const distDir = path7.join(rootDir, "dist");
|
|
791
|
+
const ssrOnly = (options == null ? void 0 : options.ssrOnly) || false;
|
|
792
|
+
const mode = (options == null ? void 0 : options.mode) || "production";
|
|
793
|
+
console.log();
|
|
794
|
+
console.log(`${dim2("\u2503")} project: ${rootDir}`);
|
|
795
|
+
console.log(`${dim2("\u2503")} output: ${distDir}/html`);
|
|
796
|
+
console.log(`${dim2("\u2503")} mode: ${mode}`);
|
|
797
|
+
console.log();
|
|
442
798
|
await rmDir(distDir);
|
|
443
799
|
await makeDir(distDir);
|
|
444
|
-
const
|
|
445
|
-
if (await isDirectory(
|
|
446
|
-
const pageFiles = await glob3(
|
|
800
|
+
const routeFiles = [];
|
|
801
|
+
if (await isDirectory(path7.join(rootDir, "routes"))) {
|
|
802
|
+
const pageFiles = await glob3("routes/**/*", { cwd: rootDir });
|
|
447
803
|
pageFiles.forEach((file) => {
|
|
448
|
-
const parts =
|
|
804
|
+
const parts = path7.parse(file);
|
|
449
805
|
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);
|
|
806
|
+
routeFiles.push(path7.resolve(rootDir, file));
|
|
461
807
|
}
|
|
462
808
|
});
|
|
463
809
|
}
|
|
810
|
+
const elementsMap = await getElements(rootConfig);
|
|
811
|
+
const elements = Object.values(elementsMap).map(
|
|
812
|
+
(mod) => path7.resolve(rootDir, mod.src)
|
|
813
|
+
);
|
|
464
814
|
const bundleScripts = [];
|
|
465
|
-
if (await isDirectory(
|
|
466
|
-
const bundleFiles = await glob3(
|
|
815
|
+
if (await isDirectory(path7.join(rootDir, "bundles"))) {
|
|
816
|
+
const bundleFiles = await glob3("bundles/*", { cwd: rootDir });
|
|
467
817
|
bundleFiles.forEach((file) => {
|
|
468
|
-
const parts =
|
|
818
|
+
const parts = path7.parse(file);
|
|
469
819
|
if (isJsFile(parts.base)) {
|
|
470
|
-
bundleScripts.push(file);
|
|
820
|
+
bundleScripts.push(path7.resolve(rootDir, file));
|
|
471
821
|
}
|
|
472
822
|
});
|
|
473
823
|
}
|
|
474
824
|
const viteConfig = rootConfig.vite || {};
|
|
825
|
+
const vitePlugins = [
|
|
826
|
+
pluginRoot({ rootConfig }),
|
|
827
|
+
...viteConfig.plugins || [],
|
|
828
|
+
...getVitePlugins(rootConfig.plugins || [])
|
|
829
|
+
];
|
|
475
830
|
const baseConfig = {
|
|
476
831
|
...viteConfig,
|
|
477
832
|
root: rootDir,
|
|
833
|
+
mode,
|
|
478
834
|
esbuild: {
|
|
479
835
|
jsx: "automatic",
|
|
480
836
|
jsxImportSource: "preact",
|
|
481
837
|
treeShaking: true
|
|
482
838
|
},
|
|
483
|
-
plugins:
|
|
839
|
+
plugins: vitePlugins
|
|
484
840
|
};
|
|
841
|
+
const noExternalConfig = (_a = viteConfig.ssr) == null ? void 0 : _a.noExternal;
|
|
842
|
+
const noExternal = [];
|
|
843
|
+
if (noExternalConfig) {
|
|
844
|
+
if (Array.isArray(noExternalConfig)) {
|
|
845
|
+
noExternal.push(...noExternalConfig);
|
|
846
|
+
} else {
|
|
847
|
+
noExternal.push(noExternalConfig);
|
|
848
|
+
}
|
|
849
|
+
}
|
|
485
850
|
await viteBuild({
|
|
486
851
|
...baseConfig,
|
|
487
|
-
mode: "production",
|
|
488
852
|
publicDir: false,
|
|
489
853
|
build: {
|
|
490
854
|
rollupOptions: {
|
|
491
|
-
|
|
855
|
+
...(_b = viteConfig == null ? void 0 : viteConfig.build) == null ? void 0 : _b.rollupOptions,
|
|
856
|
+
input: [path7.resolve(__dirname2, "./render.js")],
|
|
492
857
|
output: {
|
|
493
858
|
format: "esm",
|
|
494
|
-
chunkFileNames: "chunks/[name].[hash].js",
|
|
859
|
+
chunkFileNames: "chunks/[name].[hash].min.js",
|
|
495
860
|
assetFileNames: "assets/[name].[hash][extname]"
|
|
496
861
|
}
|
|
497
862
|
},
|
|
498
|
-
outDir:
|
|
863
|
+
outDir: path7.join(distDir, "server"),
|
|
499
864
|
ssr: true,
|
|
500
865
|
ssrManifest: false,
|
|
501
866
|
cssCodeSplit: true,
|
|
@@ -505,23 +870,26 @@ async function build(rootDir) {
|
|
|
505
870
|
reportCompressedSize: false
|
|
506
871
|
},
|
|
507
872
|
ssr: {
|
|
508
|
-
|
|
873
|
+
...viteConfig.ssr,
|
|
874
|
+
noExternal: ["@blinkk/root", ...noExternal]
|
|
509
875
|
}
|
|
510
876
|
});
|
|
511
877
|
await viteBuild({
|
|
512
878
|
...baseConfig,
|
|
513
|
-
mode: "production",
|
|
514
879
|
publicDir: false,
|
|
515
880
|
build: {
|
|
516
881
|
rollupOptions: {
|
|
517
|
-
|
|
882
|
+
...(_c = viteConfig == null ? void 0 : viteConfig.build) == null ? void 0 : _c.rollupOptions,
|
|
883
|
+
input: [...routeFiles, ...elements, ...bundleScripts],
|
|
518
884
|
output: {
|
|
519
885
|
format: "esm",
|
|
520
|
-
|
|
521
|
-
|
|
886
|
+
entryFileNames: "assets/[name].[hash].min.js",
|
|
887
|
+
chunkFileNames: "chunks/[name].[hash].min.js",
|
|
888
|
+
assetFileNames: "assets/[name].[hash][extname]",
|
|
889
|
+
...(_e = (_d = viteConfig == null ? void 0 : viteConfig.build) == null ? void 0 : _d.rollupOptions) == null ? void 0 : _e.output
|
|
522
890
|
}
|
|
523
891
|
},
|
|
524
|
-
outDir:
|
|
892
|
+
outDir: path7.join(distDir, "client"),
|
|
525
893
|
ssr: false,
|
|
526
894
|
ssrManifest: false,
|
|
527
895
|
manifest: true,
|
|
@@ -532,45 +900,282 @@ async function build(rootDir) {
|
|
|
532
900
|
reportCompressedSize: false
|
|
533
901
|
}
|
|
534
902
|
});
|
|
535
|
-
const
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
const
|
|
539
|
-
|
|
540
|
-
|
|
903
|
+
const viteManifest = await loadJson(
|
|
904
|
+
path7.join(distDir, "client/manifest.json")
|
|
905
|
+
);
|
|
906
|
+
const assetMap = BuildAssetMap.fromViteManifest(
|
|
907
|
+
rootConfig,
|
|
908
|
+
viteManifest,
|
|
909
|
+
elementsMap
|
|
910
|
+
);
|
|
911
|
+
const rootManifest = assetMap.toJson();
|
|
912
|
+
writeFile(
|
|
913
|
+
path7.join(distDir, "client/root-manifest.json"),
|
|
914
|
+
JSON.stringify(rootManifest, null, 2)
|
|
915
|
+
);
|
|
916
|
+
const buildDir = path7.join(distDir, "html");
|
|
917
|
+
const publicDir = path7.join(rootDir, "public");
|
|
918
|
+
if (fsExtra2.existsSync(path7.join(rootDir, "public"))) {
|
|
541
919
|
fsExtra2.copySync(publicDir, buildDir);
|
|
542
920
|
} else {
|
|
543
921
|
makeDir(buildDir);
|
|
544
922
|
}
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
const
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
923
|
+
console.log("\njs/css output:");
|
|
924
|
+
makeDir(path7.join(buildDir, "assets"));
|
|
925
|
+
makeDir(path7.join(buildDir, "chunks"));
|
|
926
|
+
Object.keys(rootManifest).forEach((src) => {
|
|
927
|
+
if (isRouteFile(src)) {
|
|
928
|
+
return;
|
|
929
|
+
}
|
|
930
|
+
const assetData = rootManifest[src];
|
|
931
|
+
const assetRelPath = assetData.assetUrl.slice(1);
|
|
932
|
+
const assetFrom = path7.join(distDir, "client", assetRelPath);
|
|
933
|
+
const assetTo = path7.join(buildDir, assetRelPath);
|
|
934
|
+
fsExtra2.copySync(assetFrom, assetTo);
|
|
935
|
+
printFileOutput(fileSize(assetTo), "dist/html/", assetRelPath);
|
|
936
|
+
});
|
|
937
|
+
if (!ssrOnly) {
|
|
938
|
+
const render = await import(path7.join(distDir, "server/render.js"));
|
|
939
|
+
const renderer = new render.Renderer(rootConfig, { assetMap });
|
|
940
|
+
const sitemap = await renderer.getSitemap();
|
|
941
|
+
console.log("\nhtml output:");
|
|
942
|
+
await Promise.all(
|
|
943
|
+
Object.keys(sitemap).map(async (urlPath) => {
|
|
944
|
+
const { route, params } = sitemap[urlPath];
|
|
945
|
+
const data = await renderer.renderRoute(route, {
|
|
946
|
+
routeParams: params
|
|
947
|
+
});
|
|
948
|
+
let outFilePath = path7.join(urlPath.slice(1), "index.html");
|
|
949
|
+
if (outFilePath.endsWith("404/index.html")) {
|
|
950
|
+
outFilePath = outFilePath.replace("404/index.html", "404.html");
|
|
951
|
+
}
|
|
952
|
+
const outPath = path7.join(buildDir, outFilePath);
|
|
953
|
+
let html = data.html || "";
|
|
954
|
+
if (rootConfig.prettyHtml !== false) {
|
|
955
|
+
html = await htmlPretty(html, rootConfig.prettyHtmlOptions);
|
|
956
|
+
}
|
|
957
|
+
if (rootConfig.minifyHtml !== false) {
|
|
958
|
+
html = await htmlMinify(html, rootConfig.minifyHtmlOptions);
|
|
959
|
+
}
|
|
960
|
+
await writeFile(outPath, html);
|
|
961
|
+
printFileOutput(fileSize(outPath), "dist/html/", outFilePath);
|
|
962
|
+
})
|
|
963
|
+
);
|
|
964
|
+
}
|
|
965
|
+
}
|
|
966
|
+
function isRouteFile(filepath) {
|
|
967
|
+
return filepath.startsWith("routes") && isJsFile(filepath);
|
|
968
|
+
}
|
|
969
|
+
function fileSize(filepath) {
|
|
970
|
+
const stats = fsExtra2.statSync(filepath);
|
|
971
|
+
const bytes = stats.size;
|
|
972
|
+
const k = 1024;
|
|
973
|
+
if (bytes < k) {
|
|
974
|
+
return (bytes / k).toFixed(2) + " kB";
|
|
975
|
+
}
|
|
976
|
+
const units = ["B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
|
|
977
|
+
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
978
|
+
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + " " + units[i];
|
|
979
|
+
}
|
|
980
|
+
function printFileOutput(fileSize2, outputDir, outputFile) {
|
|
981
|
+
const indent = " ".repeat(2);
|
|
982
|
+
const paddedSize = fileSize2.padStart(9, " ");
|
|
983
|
+
console.log(
|
|
984
|
+
`${indent}${dim2(paddedSize)} ${dim2(outputDir)}${cyan(outputFile)}`
|
|
985
|
+
);
|
|
986
|
+
}
|
|
987
|
+
|
|
988
|
+
// src/cli/commands/preview.ts
|
|
989
|
+
import path8 from "node:path";
|
|
990
|
+
import { default as express2 } from "express";
|
|
991
|
+
import { dim as dim3 } from "kleur/colors";
|
|
992
|
+
import sirv from "sirv";
|
|
993
|
+
import compression from "compression";
|
|
994
|
+
async function preview(rootProjectDir) {
|
|
995
|
+
process.env.NODE_ENV = "development";
|
|
996
|
+
const rootDir = path8.resolve(rootProjectDir || process.cwd());
|
|
997
|
+
const server = await createServer3({ rootDir });
|
|
998
|
+
const port = parseInt(process.env.PORT || "4007");
|
|
999
|
+
console.log();
|
|
1000
|
+
console.log(`${dim3("\u2503")} project: ${rootDir}`);
|
|
1001
|
+
console.log(`${dim3("\u2503")} server: http://localhost:${port}`);
|
|
1002
|
+
console.log(`${dim3("\u2503")} mode: staging`);
|
|
1003
|
+
console.log();
|
|
1004
|
+
server.listen(port);
|
|
1005
|
+
}
|
|
1006
|
+
async function createServer3(options) {
|
|
1007
|
+
const rootDir = options.rootDir;
|
|
1008
|
+
const rootConfig = await loadRootConfig(rootDir);
|
|
1009
|
+
const distDir = path8.join(rootDir, "dist");
|
|
1010
|
+
const server = express2();
|
|
1011
|
+
server.disable("x-powered-by");
|
|
1012
|
+
server.use(compression());
|
|
1013
|
+
server.use(rootProjectMiddleware({ rootDir, rootConfig }));
|
|
1014
|
+
server.use(await rootPreviewRendererMiddleware({ rootConfig, distDir }));
|
|
1015
|
+
const plugins = rootConfig.plugins || [];
|
|
1016
|
+
configureServerPlugins(
|
|
1017
|
+
server,
|
|
1018
|
+
async () => {
|
|
1019
|
+
var _a;
|
|
1020
|
+
const userMiddlewares = ((_a = rootConfig.server) == null ? void 0 : _a.middlewares) || [];
|
|
1021
|
+
userMiddlewares.forEach((middleware) => {
|
|
1022
|
+
server.use(middleware);
|
|
1023
|
+
});
|
|
1024
|
+
const publicDir = path8.join(distDir, "html");
|
|
1025
|
+
server.use(sirv(publicDir, { dev: false }));
|
|
1026
|
+
server.use(rootPreviewServerMiddleware());
|
|
1027
|
+
},
|
|
1028
|
+
plugins,
|
|
1029
|
+
{ type: "preview" }
|
|
1030
|
+
);
|
|
1031
|
+
return server;
|
|
1032
|
+
}
|
|
1033
|
+
async function rootPreviewRendererMiddleware(options) {
|
|
1034
|
+
const { distDir, rootConfig } = options;
|
|
1035
|
+
const render = await import(path8.join(distDir, "server/render.js"));
|
|
1036
|
+
const manifestPath = path8.join(distDir, "client/root-manifest.json");
|
|
1037
|
+
if (!await fileExists(manifestPath)) {
|
|
1038
|
+
throw new Error(
|
|
1039
|
+
`could not find ${manifestPath}. run \`root build\` before \`root preview\`.`
|
|
1040
|
+
);
|
|
1041
|
+
}
|
|
1042
|
+
const rootManifest = await loadJson(manifestPath);
|
|
1043
|
+
const assetMap = BuildAssetMap.fromRootManifest(rootConfig, rootManifest);
|
|
1044
|
+
const renderer = new render.Renderer(rootConfig, { assetMap });
|
|
1045
|
+
return async (req, _, next) => {
|
|
1046
|
+
req.renderer = renderer;
|
|
1047
|
+
next();
|
|
1048
|
+
};
|
|
1049
|
+
}
|
|
1050
|
+
function rootPreviewServerMiddleware() {
|
|
1051
|
+
return async (req, res, next) => {
|
|
1052
|
+
const rootConfig = req.rootConfig;
|
|
1053
|
+
const renderer = req.renderer;
|
|
1054
|
+
try {
|
|
1055
|
+
const url = req.path;
|
|
1056
|
+
const data = await renderer.render(url);
|
|
1057
|
+
if (data.notFound || !data.html) {
|
|
1058
|
+
next();
|
|
1059
|
+
return;
|
|
1060
|
+
}
|
|
1061
|
+
let html = data.html || "";
|
|
1062
|
+
if (rootConfig.prettyHtml !== false) {
|
|
1063
|
+
html = await htmlPretty(html, rootConfig.prettyHtmlOptions);
|
|
1064
|
+
}
|
|
1065
|
+
if (rootConfig.minifyHtml !== false) {
|
|
1066
|
+
html = await htmlMinify(html, rootConfig.minifyHtmlOptions);
|
|
1067
|
+
}
|
|
1068
|
+
res.status(200).set({ "Content-Type": "text/html" }).end(html);
|
|
1069
|
+
} catch (e) {
|
|
1070
|
+
try {
|
|
1071
|
+
const { html } = await renderer.renderError(e);
|
|
1072
|
+
res.status(500).set({ "Content-Type": "text/html" }).end(html);
|
|
1073
|
+
} catch (e2) {
|
|
1074
|
+
console.error("failed to render custom error");
|
|
1075
|
+
console.error(e2);
|
|
1076
|
+
next(e);
|
|
1077
|
+
}
|
|
559
1078
|
}
|
|
560
|
-
|
|
561
|
-
await writeFile(outPath, html);
|
|
562
|
-
const relPath = outPath.slice(path6.dirname(distDir).length + 1);
|
|
563
|
-
console.log(`saved ${relPath}`);
|
|
564
|
-
}));
|
|
1079
|
+
};
|
|
565
1080
|
}
|
|
566
1081
|
|
|
567
1082
|
// src/cli/commands/start.ts
|
|
568
|
-
|
|
569
|
-
|
|
1083
|
+
import path9 from "node:path";
|
|
1084
|
+
import { default as express3 } from "express";
|
|
1085
|
+
import { dim as dim4 } from "kleur/colors";
|
|
1086
|
+
import sirv2 from "sirv";
|
|
1087
|
+
import compression2 from "compression";
|
|
1088
|
+
async function start(rootProjectDir) {
|
|
1089
|
+
process.env.NODE_ENV = "production";
|
|
1090
|
+
const rootDir = path9.resolve(rootProjectDir || process.cwd());
|
|
1091
|
+
const server = await createServer4({ rootDir });
|
|
1092
|
+
const port = parseInt(process.env.PORT || "4007");
|
|
1093
|
+
console.log();
|
|
1094
|
+
console.log(`${dim4("\u2503")} project: ${rootDir}`);
|
|
1095
|
+
console.log(`${dim4("\u2503")} server: http://localhost:${port}`);
|
|
1096
|
+
console.log(`${dim4("\u2503")} mode: production`);
|
|
1097
|
+
console.log();
|
|
1098
|
+
server.listen(port);
|
|
1099
|
+
}
|
|
1100
|
+
async function createServer4(options) {
|
|
1101
|
+
const rootDir = options.rootDir;
|
|
1102
|
+
const rootConfig = await loadRootConfig(rootDir);
|
|
1103
|
+
const distDir = path9.join(rootDir, "dist");
|
|
1104
|
+
const server = express3();
|
|
1105
|
+
server.disable("x-powered-by");
|
|
1106
|
+
server.use(compression2());
|
|
1107
|
+
server.use(rootProjectMiddleware({ rootDir, rootConfig }));
|
|
1108
|
+
server.use(await rootProdRendererMiddleware({ rootConfig, distDir }));
|
|
1109
|
+
const plugins = rootConfig.plugins || [];
|
|
1110
|
+
configureServerPlugins(
|
|
1111
|
+
server,
|
|
1112
|
+
async () => {
|
|
1113
|
+
var _a;
|
|
1114
|
+
const userMiddlewares = ((_a = rootConfig.server) == null ? void 0 : _a.middlewares) || [];
|
|
1115
|
+
userMiddlewares.forEach((middleware) => {
|
|
1116
|
+
server.use(middleware);
|
|
1117
|
+
});
|
|
1118
|
+
const publicDir = path9.join(distDir, "html");
|
|
1119
|
+
server.use(sirv2(publicDir, { dev: false }));
|
|
1120
|
+
server.use(rootProdServerMiddleware());
|
|
1121
|
+
},
|
|
1122
|
+
plugins,
|
|
1123
|
+
{ type: "prod" }
|
|
1124
|
+
);
|
|
1125
|
+
return server;
|
|
1126
|
+
}
|
|
1127
|
+
async function rootProdRendererMiddleware(options) {
|
|
1128
|
+
const { distDir, rootConfig } = options;
|
|
1129
|
+
const render = await import(path9.join(distDir, "server/render.js"));
|
|
1130
|
+
const manifestPath = path9.join(distDir, "client/root-manifest.json");
|
|
1131
|
+
if (!await fileExists(manifestPath)) {
|
|
1132
|
+
throw new Error(
|
|
1133
|
+
`could not find ${manifestPath}. run \`root build\` before \`root preview\`.`
|
|
1134
|
+
);
|
|
1135
|
+
}
|
|
1136
|
+
const rootManifest = await loadJson(manifestPath);
|
|
1137
|
+
const assetMap = BuildAssetMap.fromRootManifest(rootConfig, rootManifest);
|
|
1138
|
+
const renderer = new render.Renderer(rootConfig, { assetMap });
|
|
1139
|
+
return async (req, _, next) => {
|
|
1140
|
+
req.renderer = renderer;
|
|
1141
|
+
next();
|
|
1142
|
+
};
|
|
1143
|
+
}
|
|
1144
|
+
function rootProdServerMiddleware() {
|
|
1145
|
+
return async (req, res, next) => {
|
|
1146
|
+
const rootConfig = req.rootConfig;
|
|
1147
|
+
const renderer = req.renderer;
|
|
1148
|
+
try {
|
|
1149
|
+
const url = req.path;
|
|
1150
|
+
const data = await renderer.render(url);
|
|
1151
|
+
if (data.notFound || !data.html) {
|
|
1152
|
+
next();
|
|
1153
|
+
return;
|
|
1154
|
+
}
|
|
1155
|
+
let html = data.html || "";
|
|
1156
|
+
if (rootConfig.prettyHtml !== false) {
|
|
1157
|
+
html = await htmlPretty(html, rootConfig.prettyHtmlOptions);
|
|
1158
|
+
}
|
|
1159
|
+
if (rootConfig.minifyHtml !== false) {
|
|
1160
|
+
html = await htmlMinify(html, rootConfig.minifyHtmlOptions);
|
|
1161
|
+
}
|
|
1162
|
+
res.status(200).set({ "Content-Type": "text/html" }).end(html);
|
|
1163
|
+
} catch (e) {
|
|
1164
|
+
try {
|
|
1165
|
+
const { html } = await renderer.renderError(e);
|
|
1166
|
+
res.status(500).set({ "Content-Type": "text/html" }).end(html);
|
|
1167
|
+
} catch (e2) {
|
|
1168
|
+
console.error("failed to render custom error");
|
|
1169
|
+
console.error(e2);
|
|
1170
|
+
next(e);
|
|
1171
|
+
}
|
|
1172
|
+
}
|
|
1173
|
+
};
|
|
570
1174
|
}
|
|
571
1175
|
export {
|
|
572
1176
|
build,
|
|
573
1177
|
dev,
|
|
1178
|
+
preview,
|
|
574
1179
|
start
|
|
575
1180
|
};
|
|
576
1181
|
//# sourceMappingURL=cli.js.map
|