@blinkk/root 1.0.0-beta.2 → 1.0.0-beta.4
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/dist/{chunk-GGQGZ7ZE.js → chunk-WVRC46JG.js} +18 -18
- package/dist/chunk-WVRC46JG.js.map +1 -0
- package/dist/cli.d.ts +19 -2
- package/dist/cli.js +632 -627
- package/dist/cli.js.map +1 -1
- package/dist/core.d.ts +2 -2
- package/dist/node.d.ts +1 -1
- package/dist/render.d.ts +1 -1
- package/dist/render.js +51 -22
- package/dist/render.js.map +1 -1
- package/dist/{config-872b068d.d.ts → types-47b9b530.d.ts} +131 -131
- package/package.json +1 -1
- package/dist/chunk-GGQGZ7ZE.js.map +0 -1
package/dist/cli.js
CHANGED
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
htmlPretty,
|
|
4
4
|
isValidTagName,
|
|
5
5
|
parseTagNames
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-WVRC46JG.js";
|
|
7
7
|
import {
|
|
8
8
|
copyGlob,
|
|
9
9
|
createViteServer,
|
|
@@ -22,186 +22,173 @@ import {
|
|
|
22
22
|
getVitePlugins
|
|
23
23
|
} from "./chunk-DTEQ2AIW.js";
|
|
24
24
|
|
|
25
|
-
// src/cli/commands/
|
|
25
|
+
// src/cli/commands/build.ts
|
|
26
26
|
import path3 from "node:path";
|
|
27
27
|
import { fileURLToPath } from "node:url";
|
|
28
|
-
import
|
|
28
|
+
import fsExtra from "fs-extra";
|
|
29
|
+
import glob2 from "tiny-glob";
|
|
30
|
+
import { build as viteBuild } from "vite";
|
|
29
31
|
|
|
30
|
-
// src/render/asset-map/
|
|
32
|
+
// src/render/asset-map/build-asset-map.ts
|
|
33
|
+
import fs from "node:fs";
|
|
31
34
|
import path from "node:path";
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
constructor(rootConfig, moduleGraph) {
|
|
35
|
+
var BuildAssetMap = class {
|
|
36
|
+
constructor(rootConfig) {
|
|
35
37
|
this.rootConfig = rootConfig;
|
|
36
|
-
this.
|
|
38
|
+
this.srcToAsset = /* @__PURE__ */ new Map();
|
|
37
39
|
}
|
|
38
40
|
async get(src) {
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
const [viteModule] = viteModules;
|
|
43
|
-
return new DevServerAsset(src, {
|
|
44
|
-
assetMap: this,
|
|
45
|
-
viteModule
|
|
46
|
-
});
|
|
41
|
+
const asset = this.srcToAsset.get(src);
|
|
42
|
+
if (asset) {
|
|
43
|
+
return asset;
|
|
47
44
|
}
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
getJsDeps: async () => [assetUrl]
|
|
55
|
-
};
|
|
45
|
+
const realSrc = realPathRelativeTo(this.rootConfig.rootDir, src);
|
|
46
|
+
if (realSrc !== src) {
|
|
47
|
+
const asset2 = this.srcToAsset.get(realSrc);
|
|
48
|
+
if (asset2) {
|
|
49
|
+
return asset2;
|
|
50
|
+
}
|
|
56
51
|
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
52
|
+
console.log(`could not find build asset: ${src}`);
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
add(asset) {
|
|
56
|
+
this.srcToAsset.set(asset.src, asset);
|
|
57
|
+
}
|
|
58
|
+
toJson() {
|
|
59
|
+
const result = {};
|
|
60
|
+
for (const src of this.srcToAsset.keys()) {
|
|
61
|
+
result[src] = this.srcToAsset.get(src).toJson();
|
|
62
|
+
}
|
|
63
|
+
return result;
|
|
64
|
+
}
|
|
65
|
+
static fromViteManifest(rootConfig, clientManifest, elementsGraph) {
|
|
66
|
+
const assetMap = new BuildAssetMap(rootConfig);
|
|
67
|
+
const elementFiles = /* @__PURE__ */ new Set();
|
|
68
|
+
Object.values(elementsGraph.sourceFiles).forEach((elementSource) => {
|
|
69
|
+
elementFiles.add(elementSource.relPath);
|
|
70
|
+
const realSrc = realPathRelativeTo(
|
|
71
|
+
rootConfig.rootDir,
|
|
72
|
+
elementSource.relPath
|
|
73
|
+
);
|
|
74
|
+
if (realSrc !== elementSource.filePath) {
|
|
75
|
+
elementFiles.add(realSrc);
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
Object.keys(clientManifest).forEach((manifestKey) => {
|
|
79
|
+
const src = manifestKey;
|
|
80
|
+
const manifestChunk = clientManifest[manifestKey];
|
|
81
|
+
const isElement = elementFiles.has(src);
|
|
82
|
+
const assetUrl = src.startsWith("routes/") && isJsFile(src) ? "" : `/${manifestChunk.file}`;
|
|
83
|
+
const assetData = {
|
|
61
84
|
src,
|
|
62
85
|
assetUrl,
|
|
63
|
-
|
|
64
|
-
|
|
86
|
+
importedModules: manifestChunk.imports || [],
|
|
87
|
+
importedCss: (manifestChunk.css || []).map((relPath) => `/${relPath}`),
|
|
88
|
+
isElement
|
|
65
89
|
};
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
return
|
|
90
|
+
assetMap.add(new BuildAsset(assetMap, assetData));
|
|
91
|
+
});
|
|
92
|
+
return assetMap;
|
|
69
93
|
}
|
|
70
|
-
|
|
71
|
-
|
|
94
|
+
static fromRootManifest(rootConfig, rootManifest) {
|
|
95
|
+
const assetMap = new BuildAssetMap(rootConfig);
|
|
96
|
+
Object.keys(rootManifest).forEach((moduleId) => {
|
|
97
|
+
const assetData = rootManifest[moduleId];
|
|
98
|
+
assetMap.add(new BuildAsset(assetMap, assetData));
|
|
99
|
+
});
|
|
100
|
+
return assetMap;
|
|
72
101
|
}
|
|
73
102
|
};
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
103
|
+
function realPathRelativeTo(rootDir, src) {
|
|
104
|
+
const fullPath = path.resolve(rootDir, src);
|
|
105
|
+
if (!fs.existsSync(fullPath)) {
|
|
106
|
+
return src;
|
|
107
|
+
}
|
|
108
|
+
const realpath = fs.realpathSync(path.resolve(rootDir, src));
|
|
109
|
+
return path.relative(rootDir, realpath);
|
|
110
|
+
}
|
|
111
|
+
var BuildAsset = class {
|
|
112
|
+
constructor(assetMap, assetData) {
|
|
113
|
+
this.assetMap = assetMap;
|
|
114
|
+
this.src = assetData.src;
|
|
115
|
+
this.assetUrl = assetData.assetUrl;
|
|
116
|
+
this.importedModules = assetData.importedModules;
|
|
117
|
+
this.importedCss = assetData.importedCss;
|
|
118
|
+
this.isElement = assetData.isElement;
|
|
81
119
|
}
|
|
82
120
|
async getCssDeps() {
|
|
83
121
|
const visited = /* @__PURE__ */ new Set();
|
|
84
122
|
const deps = /* @__PURE__ */ new Set();
|
|
85
|
-
this.collectCss(this, deps, visited);
|
|
123
|
+
await this.collectCss(this, deps, visited);
|
|
86
124
|
return Array.from(deps);
|
|
87
125
|
}
|
|
88
126
|
async getJsDeps() {
|
|
89
127
|
const visited = /* @__PURE__ */ new Set();
|
|
90
128
|
const deps = /* @__PURE__ */ new Set();
|
|
91
|
-
this.collectJs(this, deps, visited);
|
|
129
|
+
await this.collectJs(this, deps, visited);
|
|
92
130
|
return Array.from(deps);
|
|
93
131
|
}
|
|
94
|
-
|
|
95
|
-
return this.viteModule.importedModules;
|
|
96
|
-
}
|
|
97
|
-
collectJs(asset, urls, visited) {
|
|
132
|
+
async collectJs(asset, urls, visited) {
|
|
98
133
|
if (!asset) {
|
|
99
134
|
return;
|
|
100
135
|
}
|
|
101
|
-
if (!asset.
|
|
136
|
+
if (!asset.src) {
|
|
102
137
|
return;
|
|
103
138
|
}
|
|
104
|
-
if (visited.has(asset.
|
|
139
|
+
if (visited.has(asset.src)) {
|
|
105
140
|
return;
|
|
106
141
|
}
|
|
107
|
-
visited.add(asset.
|
|
108
|
-
|
|
109
|
-
if ([".js", ".jsx", ".ts", ".tsx"].includes(parts.ext) && asset.moduleId.includes("/elements/")) {
|
|
142
|
+
visited.add(asset.src);
|
|
143
|
+
if (asset.isElement) {
|
|
110
144
|
urls.add(asset.assetUrl);
|
|
111
145
|
}
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
const
|
|
115
|
-
const importedAsset = new DevServerAsset(src, {
|
|
116
|
-
assetMap: this.assetMap,
|
|
117
|
-
viteModule
|
|
118
|
-
});
|
|
146
|
+
await Promise.all(
|
|
147
|
+
asset.importedModules.map(async (src) => {
|
|
148
|
+
const importedAsset = await this.assetMap.get(src);
|
|
119
149
|
this.collectJs(importedAsset, urls, visited);
|
|
120
|
-
}
|
|
121
|
-
|
|
150
|
+
})
|
|
151
|
+
);
|
|
122
152
|
}
|
|
123
|
-
collectCss(asset, urls, visited) {
|
|
153
|
+
async collectCss(asset, urls, visited) {
|
|
124
154
|
if (!asset) {
|
|
125
155
|
return;
|
|
126
156
|
}
|
|
127
|
-
if (!asset.
|
|
157
|
+
if (!asset.src) {
|
|
128
158
|
return;
|
|
129
159
|
}
|
|
130
|
-
if (visited.has(asset.
|
|
160
|
+
if (visited.has(asset.src)) {
|
|
131
161
|
return;
|
|
132
162
|
}
|
|
133
|
-
visited.add(asset.
|
|
134
|
-
if (asset.
|
|
135
|
-
|
|
136
|
-
if (!parts.name.startsWith("_")) {
|
|
137
|
-
urls.add(asset.assetUrl);
|
|
138
|
-
}
|
|
163
|
+
visited.add(asset.src);
|
|
164
|
+
if (asset.importedCss) {
|
|
165
|
+
asset.importedCss.forEach((cssUrl) => urls.add(cssUrl));
|
|
139
166
|
}
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
const
|
|
143
|
-
const importedAsset = new DevServerAsset(src, {
|
|
144
|
-
assetMap: this.assetMap,
|
|
145
|
-
viteModule
|
|
146
|
-
});
|
|
167
|
+
await Promise.all(
|
|
168
|
+
asset.importedModules.map(async (moduleId) => {
|
|
169
|
+
const importedAsset = await this.assetMap.get(moduleId);
|
|
147
170
|
this.collectCss(importedAsset, urls, visited);
|
|
148
|
-
}
|
|
149
|
-
|
|
171
|
+
})
|
|
172
|
+
);
|
|
173
|
+
}
|
|
174
|
+
toJson() {
|
|
175
|
+
return {
|
|
176
|
+
src: this.src,
|
|
177
|
+
assetUrl: this.assetUrl,
|
|
178
|
+
importedModules: this.importedModules,
|
|
179
|
+
importedCss: this.importedCss,
|
|
180
|
+
isElement: this.isElement
|
|
181
|
+
};
|
|
150
182
|
}
|
|
151
183
|
};
|
|
152
184
|
|
|
153
|
-
// src/cli/commands/
|
|
154
|
-
import { dim } from "kleur/colors";
|
|
155
|
-
|
|
156
|
-
// src/core/middleware.ts
|
|
157
|
-
function rootProjectMiddleware(options) {
|
|
158
|
-
return (req, _, next) => {
|
|
159
|
-
req.rootConfig = options.rootConfig;
|
|
160
|
-
next();
|
|
161
|
-
};
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
// src/utils/ports.ts
|
|
165
|
-
import { createServer } from "node:net";
|
|
166
|
-
function isPortOpen(port) {
|
|
167
|
-
return new Promise((resolve, reject) => {
|
|
168
|
-
const server = createServer();
|
|
169
|
-
server.on("error", (err) => {
|
|
170
|
-
if (err.code === "EADDRINUSE") {
|
|
171
|
-
resolve(false);
|
|
172
|
-
return;
|
|
173
|
-
}
|
|
174
|
-
reject(err);
|
|
175
|
-
});
|
|
176
|
-
server.on("close", () => {
|
|
177
|
-
resolve(true);
|
|
178
|
-
});
|
|
179
|
-
server.listen(port, () => {
|
|
180
|
-
server.close((err) => {
|
|
181
|
-
if (err) {
|
|
182
|
-
console.log(`error closing server: ${err}`);
|
|
183
|
-
reject(err);
|
|
184
|
-
}
|
|
185
|
-
});
|
|
186
|
-
});
|
|
187
|
-
});
|
|
188
|
-
}
|
|
189
|
-
async function findOpenPort(min, max) {
|
|
190
|
-
let port = min;
|
|
191
|
-
while (port <= max) {
|
|
192
|
-
const isOpen = await isPortOpen(port);
|
|
193
|
-
if (isOpen) {
|
|
194
|
-
return port;
|
|
195
|
-
}
|
|
196
|
-
port += 1;
|
|
197
|
-
}
|
|
198
|
-
throw new Error(`no ports open between ${min} and ${max}`);
|
|
199
|
-
}
|
|
185
|
+
// src/cli/commands/build.ts
|
|
186
|
+
import { dim, cyan } from "kleur/colors";
|
|
200
187
|
|
|
201
188
|
// src/node/element-graph.ts
|
|
202
|
-
import
|
|
189
|
+
import fs2 from "node:fs";
|
|
203
190
|
import path2 from "node:path";
|
|
204
|
-
import { searchForWorkspaceRoot
|
|
191
|
+
import { searchForWorkspaceRoot } from "vite";
|
|
205
192
|
import glob from "tiny-glob";
|
|
206
193
|
var ElementGraph = class {
|
|
207
194
|
constructor(sourceFiles) {
|
|
@@ -229,7 +216,7 @@ var ElementGraph = class {
|
|
|
229
216
|
if (!srcFile) {
|
|
230
217
|
throw new Error(`could not find file path for tagName <${tagName}>`);
|
|
231
218
|
}
|
|
232
|
-
const src =
|
|
219
|
+
const src = fs2.readFileSync(srcFile.filePath, "utf-8");
|
|
233
220
|
const tagNames = parseTagNames(src);
|
|
234
221
|
const deps = /* @__PURE__ */ new Set();
|
|
235
222
|
for (const depTagName of tagNames) {
|
|
@@ -243,7 +230,7 @@ var ElementGraph = class {
|
|
|
243
230
|
async function getElements(rootConfig) {
|
|
244
231
|
var _a, _b;
|
|
245
232
|
const rootDir = rootConfig.rootDir;
|
|
246
|
-
const workspaceRoot =
|
|
233
|
+
const workspaceRoot = searchForWorkspaceRoot(rootDir);
|
|
247
234
|
const elementsDirs = [path2.join(rootDir, "elements")];
|
|
248
235
|
const elementsInclude = ((_a = rootConfig.elements) == null ? void 0 : _a.include) || [];
|
|
249
236
|
const excludePatterns = ((_b = rootConfig.elements) == null ? void 0 : _b.exclude) || [];
|
|
@@ -280,54 +267,36 @@ async function getElements(rootConfig) {
|
|
|
280
267
|
return graph;
|
|
281
268
|
}
|
|
282
269
|
|
|
283
|
-
// src/cli/commands/
|
|
284
|
-
import glob2 from "tiny-glob";
|
|
270
|
+
// src/cli/commands/build.ts
|
|
285
271
|
var __dirname = path3.dirname(fileURLToPath(import.meta.url));
|
|
286
|
-
async function
|
|
287
|
-
|
|
272
|
+
async function build(rootProjectDir, options) {
|
|
273
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
274
|
+
const mode = (options == null ? void 0 : options.mode) || "production";
|
|
275
|
+
process.env.NODE_ENV = mode;
|
|
288
276
|
const rootDir = path3.resolve(rootProjectDir || process.cwd());
|
|
289
|
-
const
|
|
290
|
-
const
|
|
277
|
+
const rootConfig = await loadRootConfig(rootDir, { command: "build" });
|
|
278
|
+
const distDir = path3.join(rootDir, "dist");
|
|
279
|
+
const ssrOnly = (options == null ? void 0 : options.ssrOnly) || false;
|
|
291
280
|
console.log();
|
|
292
281
|
console.log(`${dim("\u2503")} project: ${rootDir}`);
|
|
293
|
-
console.log(`${dim("\u2503")}
|
|
294
|
-
console.log(`${dim("\u2503")} mode:
|
|
282
|
+
console.log(`${dim("\u2503")} output: ${distDir}/html`);
|
|
283
|
+
console.log(`${dim("\u2503")} mode: ${mode}`);
|
|
295
284
|
console.log();
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
server.use(rootProjectMiddleware({ rootConfig }));
|
|
306
|
-
server.use(await viteServerMiddleware({ rootConfig, port }));
|
|
307
|
-
const plugins = rootConfig.plugins || [];
|
|
308
|
-
await configureServerPlugins(
|
|
309
|
-
server,
|
|
310
|
-
async () => {
|
|
311
|
-
var _a;
|
|
312
|
-
const userMiddlewares = ((_a = rootConfig.server) == null ? void 0 : _a.middlewares) || [];
|
|
313
|
-
for (const middleware of userMiddlewares) {
|
|
314
|
-
server.use(middleware);
|
|
285
|
+
await rmDir(distDir);
|
|
286
|
+
await makeDir(distDir);
|
|
287
|
+
const routeFiles = [];
|
|
288
|
+
if (await isDirectory(path3.join(rootDir, "routes"))) {
|
|
289
|
+
const pageFiles = await glob2("routes/**/*", { cwd: rootDir });
|
|
290
|
+
pageFiles.forEach((file) => {
|
|
291
|
+
const parts = path3.parse(file);
|
|
292
|
+
if (!parts.name.startsWith("_") && isJsFile(parts.base)) {
|
|
293
|
+
routeFiles.push(path3.resolve(rootDir, file));
|
|
315
294
|
}
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
server.use(rootDevServer500Middleware());
|
|
319
|
-
},
|
|
320
|
-
plugins,
|
|
321
|
-
{ type: "dev", rootConfig }
|
|
322
|
-
);
|
|
323
|
-
return server;
|
|
324
|
-
}
|
|
325
|
-
async function viteServerMiddleware(options) {
|
|
326
|
-
const rootConfig = options.rootConfig;
|
|
327
|
-
const rootDir = rootConfig.rootDir;
|
|
295
|
+
});
|
|
296
|
+
}
|
|
328
297
|
const elementGraph = await getElements(rootConfig);
|
|
329
298
|
const elements = Object.values(elementGraph.sourceFiles).map((sourceFile) => {
|
|
330
|
-
return sourceFile.
|
|
299
|
+
return sourceFile.filePath;
|
|
331
300
|
});
|
|
332
301
|
const bundleScripts = [];
|
|
333
302
|
if (await isDirectory(path3.join(rootDir, "bundles"))) {
|
|
@@ -335,272 +304,489 @@ async function viteServerMiddleware(options) {
|
|
|
335
304
|
bundleFiles.forEach((file) => {
|
|
336
305
|
const parts = path3.parse(file);
|
|
337
306
|
if (isJsFile(parts.base)) {
|
|
338
|
-
bundleScripts.push(file);
|
|
307
|
+
bundleScripts.push(path3.resolve(rootDir, file));
|
|
339
308
|
}
|
|
340
309
|
});
|
|
341
310
|
}
|
|
342
|
-
const
|
|
343
|
-
const
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
viteServer.middlewares(req, res, next);
|
|
360
|
-
} catch (e) {
|
|
361
|
-
next(e);
|
|
362
|
-
}
|
|
311
|
+
const rootPlugins = rootConfig.plugins || [];
|
|
312
|
+
const viteConfig = rootConfig.vite || {};
|
|
313
|
+
const vitePlugins = [
|
|
314
|
+
...viteConfig.plugins || [],
|
|
315
|
+
...getVitePlugins(rootPlugins)
|
|
316
|
+
];
|
|
317
|
+
const baseConfig = {
|
|
318
|
+
...viteConfig,
|
|
319
|
+
root: rootDir,
|
|
320
|
+
mode,
|
|
321
|
+
esbuild: {
|
|
322
|
+
...viteConfig.esbuild,
|
|
323
|
+
jsx: "automatic",
|
|
324
|
+
jsxImportSource: "preact",
|
|
325
|
+
treeShaking: true
|
|
326
|
+
},
|
|
327
|
+
plugins: vitePlugins
|
|
363
328
|
};
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
return async (req, res, next) => {
|
|
367
|
-
const renderer = req.renderer;
|
|
368
|
-
const viteServer = req.viteServer;
|
|
369
|
-
try {
|
|
370
|
-
await renderer.handle(req, res, next);
|
|
371
|
-
} catch (err) {
|
|
372
|
-
viteServer.ssrFixStacktrace(err);
|
|
373
|
-
next(err);
|
|
374
|
-
}
|
|
329
|
+
const ssrInput = {
|
|
330
|
+
render: path3.resolve(__dirname, "./render.js")
|
|
375
331
|
};
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
console.error(`\u2753 404 ${req.originalUrl}`);
|
|
380
|
-
if (req.renderer) {
|
|
381
|
-
const url = req.path;
|
|
382
|
-
const ext = path3.extname(url);
|
|
383
|
-
if (!ext) {
|
|
384
|
-
const renderer = req.renderer;
|
|
385
|
-
const data = await renderer.renderDevServer404(req);
|
|
386
|
-
const html = data.html || "";
|
|
387
|
-
res.status(404).set({ "Content-Type": "text/html" }).end(html);
|
|
388
|
-
return;
|
|
389
|
-
}
|
|
332
|
+
rootPlugins.forEach((plugin) => {
|
|
333
|
+
if (plugin.ssrInput) {
|
|
334
|
+
Object.assign(ssrInput, plugin.ssrInput());
|
|
390
335
|
}
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
const url = req.path;
|
|
400
|
-
const ext = path3.extname(url);
|
|
401
|
-
if (!ext) {
|
|
402
|
-
const renderer = req.renderer;
|
|
403
|
-
const data = await renderer.renderDevServer500(req, err);
|
|
404
|
-
const html = data.html || "";
|
|
405
|
-
res.status(500).set({ "Content-Type": "text/html" }).end(html);
|
|
406
|
-
return;
|
|
407
|
-
}
|
|
336
|
+
});
|
|
337
|
+
const noExternalConfig = (_a = viteConfig.ssr) == null ? void 0 : _a.noExternal;
|
|
338
|
+
const noExternal = [];
|
|
339
|
+
if (noExternalConfig) {
|
|
340
|
+
if (Array.isArray(noExternalConfig)) {
|
|
341
|
+
noExternal.push(...noExternalConfig);
|
|
342
|
+
} else {
|
|
343
|
+
noExternal.push(noExternalConfig);
|
|
408
344
|
}
|
|
409
|
-
next(err);
|
|
410
|
-
};
|
|
411
|
-
}
|
|
412
|
-
|
|
413
|
-
// src/cli/commands/build.ts
|
|
414
|
-
import path5 from "node:path";
|
|
415
|
-
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
416
|
-
import fsExtra from "fs-extra";
|
|
417
|
-
import glob3 from "tiny-glob";
|
|
418
|
-
import { build as viteBuild } from "vite";
|
|
419
|
-
|
|
420
|
-
// src/render/asset-map/build-asset-map.ts
|
|
421
|
-
import fs2 from "node:fs";
|
|
422
|
-
import path4 from "node:path";
|
|
423
|
-
var BuildAssetMap = class {
|
|
424
|
-
constructor(rootConfig) {
|
|
425
|
-
this.rootConfig = rootConfig;
|
|
426
|
-
this.srcToAsset = /* @__PURE__ */ new Map();
|
|
427
345
|
}
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
346
|
+
await viteBuild({
|
|
347
|
+
...baseConfig,
|
|
348
|
+
publicDir: false,
|
|
349
|
+
build: {
|
|
350
|
+
...viteConfig == null ? void 0 : viteConfig.build,
|
|
351
|
+
rollupOptions: {
|
|
352
|
+
...(_b = viteConfig == null ? void 0 : viteConfig.build) == null ? void 0 : _b.rollupOptions,
|
|
353
|
+
input: ssrInput,
|
|
354
|
+
output: {
|
|
355
|
+
format: "esm",
|
|
356
|
+
chunkFileNames: "chunks/[name].[hash].min.js",
|
|
357
|
+
assetFileNames: "assets/[name].[hash][extname]"
|
|
358
|
+
}
|
|
359
|
+
},
|
|
360
|
+
outDir: path3.join(distDir, "server"),
|
|
361
|
+
ssr: true,
|
|
362
|
+
ssrManifest: false,
|
|
363
|
+
cssCodeSplit: true,
|
|
364
|
+
target: "esnext",
|
|
365
|
+
minify: false,
|
|
366
|
+
modulePreload: { polyfill: false },
|
|
367
|
+
reportCompressedSize: false
|
|
368
|
+
},
|
|
369
|
+
ssr: {
|
|
370
|
+
...viteConfig.ssr,
|
|
371
|
+
target: "node",
|
|
372
|
+
noExternal: ["@blinkk/root", ...noExternal]
|
|
432
373
|
}
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
374
|
+
});
|
|
375
|
+
await viteBuild({
|
|
376
|
+
...baseConfig,
|
|
377
|
+
publicDir: false,
|
|
378
|
+
build: {
|
|
379
|
+
...viteConfig == null ? void 0 : viteConfig.build,
|
|
380
|
+
rollupOptions: {
|
|
381
|
+
...(_c = viteConfig == null ? void 0 : viteConfig.build) == null ? void 0 : _c.rollupOptions,
|
|
382
|
+
input: [...routeFiles],
|
|
383
|
+
output: {
|
|
384
|
+
format: "esm",
|
|
385
|
+
entryFileNames: "assets/[name].[hash].min.js",
|
|
386
|
+
chunkFileNames: "chunks/[name].[hash].min.js",
|
|
387
|
+
assetFileNames: "assets/[name].[hash][extname]",
|
|
388
|
+
...(_e = (_d = viteConfig == null ? void 0 : viteConfig.build) == null ? void 0 : _d.rollupOptions) == null ? void 0 : _e.output
|
|
389
|
+
}
|
|
390
|
+
},
|
|
391
|
+
outDir: path3.join(distDir, "routes"),
|
|
392
|
+
ssr: false,
|
|
393
|
+
ssrManifest: false,
|
|
394
|
+
manifest: true,
|
|
395
|
+
cssCodeSplit: true,
|
|
396
|
+
target: "esnext",
|
|
397
|
+
minify: true,
|
|
398
|
+
modulePreload: { polyfill: false },
|
|
399
|
+
reportCompressedSize: false
|
|
439
400
|
}
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
401
|
+
});
|
|
402
|
+
const clientInput = [...elements, ...bundleScripts];
|
|
403
|
+
if (clientInput.length > 0) {
|
|
404
|
+
await viteBuild({
|
|
405
|
+
...baseConfig,
|
|
406
|
+
publicDir: false,
|
|
407
|
+
build: {
|
|
408
|
+
...viteConfig == null ? void 0 : viteConfig.build,
|
|
409
|
+
rollupOptions: {
|
|
410
|
+
...(_f = viteConfig == null ? void 0 : viteConfig.build) == null ? void 0 : _f.rollupOptions,
|
|
411
|
+
input: [...elements, ...bundleScripts],
|
|
412
|
+
output: {
|
|
413
|
+
format: "esm",
|
|
414
|
+
entryFileNames: "assets/[name].[hash].min.js",
|
|
415
|
+
chunkFileNames: "chunks/[name].[hash].min.js",
|
|
416
|
+
assetFileNames: "assets/[name].[hash][extname]",
|
|
417
|
+
...(_h = (_g = viteConfig == null ? void 0 : viteConfig.build) == null ? void 0 : _g.rollupOptions) == null ? void 0 : _h.output
|
|
418
|
+
}
|
|
419
|
+
},
|
|
420
|
+
outDir: path3.join(distDir, "client"),
|
|
421
|
+
ssr: false,
|
|
422
|
+
ssrManifest: false,
|
|
423
|
+
manifest: true,
|
|
424
|
+
cssCodeSplit: true,
|
|
425
|
+
target: "esnext",
|
|
426
|
+
minify: true,
|
|
427
|
+
modulePreload: { polyfill: false },
|
|
428
|
+
reportCompressedSize: false
|
|
429
|
+
}
|
|
430
|
+
});
|
|
431
|
+
} else {
|
|
432
|
+
await writeFile(path3.join(distDir, "client/manifest.json"), "{}");
|
|
445
433
|
}
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
434
|
+
await copyGlob(
|
|
435
|
+
"*.css",
|
|
436
|
+
path3.join(distDir, "routes/assets"),
|
|
437
|
+
path3.join(distDir, "client/assets")
|
|
438
|
+
);
|
|
439
|
+
const routesManifest = await loadJson(
|
|
440
|
+
path3.join(distDir, "routes/manifest.json")
|
|
441
|
+
);
|
|
442
|
+
const clientManifest = await loadJson(
|
|
443
|
+
path3.join(distDir, "client/manifest.json")
|
|
444
|
+
);
|
|
445
|
+
function collectRouteCss(asset, cssDeps, visited) {
|
|
446
|
+
if (!asset || !asset.file || visited.has(asset.file)) {
|
|
447
|
+
return;
|
|
448
|
+
}
|
|
449
|
+
visited.add(asset.file);
|
|
450
|
+
if (asset.css) {
|
|
451
|
+
asset.css.forEach((dep) => cssDeps.add(dep));
|
|
452
|
+
}
|
|
453
|
+
if (asset.imports) {
|
|
454
|
+
asset.imports.forEach((manifestKey) => {
|
|
455
|
+
collectRouteCss(routesManifest[manifestKey], cssDeps, visited);
|
|
456
|
+
});
|
|
450
457
|
}
|
|
451
|
-
return result;
|
|
452
458
|
}
|
|
453
|
-
|
|
454
|
-
const
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
459
|
+
Object.keys(routesManifest).forEach((manifestKey) => {
|
|
460
|
+
const asset = routesManifest[manifestKey];
|
|
461
|
+
if (asset.isEntry) {
|
|
462
|
+
const visited = /* @__PURE__ */ new Set();
|
|
463
|
+
const cssDeps = /* @__PURE__ */ new Set();
|
|
464
|
+
collectRouteCss(asset, cssDeps, visited);
|
|
465
|
+
asset.css = Array.from(cssDeps);
|
|
466
|
+
asset.imports = [];
|
|
467
|
+
clientManifest[manifestKey] = asset;
|
|
468
|
+
} else if (asset.file.endsWith(".css")) {
|
|
469
|
+
clientManifest[manifestKey] = asset;
|
|
470
|
+
}
|
|
471
|
+
});
|
|
472
|
+
const assetMap = BuildAssetMap.fromViteManifest(
|
|
473
|
+
rootConfig,
|
|
474
|
+
clientManifest,
|
|
475
|
+
elementGraph
|
|
476
|
+
);
|
|
477
|
+
const rootManifest = assetMap.toJson();
|
|
478
|
+
await writeFile(
|
|
479
|
+
path3.join(distDir, "client/root-manifest.json"),
|
|
480
|
+
JSON.stringify(rootManifest, null, 2)
|
|
481
|
+
);
|
|
482
|
+
const buildDir = path3.join(distDir, "html");
|
|
483
|
+
const publicDir = path3.join(rootDir, "public");
|
|
484
|
+
if (fsExtra.existsSync(path3.join(rootDir, "public"))) {
|
|
485
|
+
fsExtra.copySync(publicDir, buildDir, { dereference: true });
|
|
486
|
+
} else {
|
|
487
|
+
await makeDir(buildDir);
|
|
488
|
+
}
|
|
489
|
+
await makeDir(path3.join(buildDir, "assets"));
|
|
490
|
+
await makeDir(path3.join(buildDir, "chunks"));
|
|
491
|
+
console.log("\njs/css output:");
|
|
492
|
+
await Promise.all(
|
|
493
|
+
Object.keys(rootManifest).map(async (src) => {
|
|
494
|
+
if (isRouteFile(src)) {
|
|
495
|
+
return;
|
|
464
496
|
}
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
const
|
|
470
|
-
const
|
|
471
|
-
const
|
|
497
|
+
const assetData = rootManifest[src];
|
|
498
|
+
if (!assetData.assetUrl) {
|
|
499
|
+
return;
|
|
500
|
+
}
|
|
501
|
+
const assetRelPath = assetData.assetUrl.slice(1);
|
|
502
|
+
const assetFrom = path3.join(distDir, "client", assetRelPath);
|
|
503
|
+
const assetTo = path3.join(buildDir, assetRelPath);
|
|
504
|
+
if (!await fileExists(assetFrom)) {
|
|
505
|
+
console.log(`${assetFrom} does not exist`);
|
|
506
|
+
return;
|
|
507
|
+
}
|
|
508
|
+
await fsExtra.copy(assetFrom, assetTo);
|
|
509
|
+
printFileOutput(fileSize(assetTo), "dist/html/", assetRelPath);
|
|
510
|
+
})
|
|
511
|
+
);
|
|
512
|
+
if (!ssrOnly) {
|
|
513
|
+
const render = await import(path3.join(distDir, "server/render.js"));
|
|
514
|
+
const renderer = new render.Renderer(rootConfig, { assetMap, elementGraph });
|
|
515
|
+
const sitemap = await renderer.getSitemap();
|
|
516
|
+
console.log("\nhtml output:");
|
|
517
|
+
await Promise.all(
|
|
518
|
+
Object.keys(sitemap).map(async (urlPath) => {
|
|
519
|
+
const { route, params } = sitemap[urlPath];
|
|
520
|
+
const data = await renderer.renderRoute(route, {
|
|
521
|
+
routeParams: params
|
|
522
|
+
});
|
|
523
|
+
if (data.notFound) {
|
|
524
|
+
return;
|
|
525
|
+
}
|
|
526
|
+
let outFilePath = path3.join(urlPath.slice(1), "index.html");
|
|
527
|
+
if (outFilePath.endsWith("404/index.html")) {
|
|
528
|
+
outFilePath = outFilePath.replace("404/index.html", "404.html");
|
|
529
|
+
}
|
|
530
|
+
const outPath = path3.join(buildDir, outFilePath);
|
|
531
|
+
let html = data.html || "";
|
|
532
|
+
if (rootConfig.prettyHtml !== false) {
|
|
533
|
+
html = await htmlPretty(html, rootConfig.prettyHtmlOptions);
|
|
534
|
+
}
|
|
535
|
+
if (rootConfig.minifyHtml !== false) {
|
|
536
|
+
html = await htmlMinify(html, rootConfig.minifyHtmlOptions);
|
|
537
|
+
}
|
|
538
|
+
await writeFile(outPath, html);
|
|
539
|
+
printFileOutput(fileSize(outPath), "dist/html/", outFilePath);
|
|
540
|
+
})
|
|
541
|
+
);
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
function isRouteFile(filepath) {
|
|
545
|
+
return filepath.startsWith("routes") && isJsFile(filepath);
|
|
546
|
+
}
|
|
547
|
+
function fileSize(filepath) {
|
|
548
|
+
const stats = fsExtra.statSync(filepath);
|
|
549
|
+
const bytes = stats.size;
|
|
550
|
+
const k = 1024;
|
|
551
|
+
if (bytes < k) {
|
|
552
|
+
return (bytes / k).toFixed(2) + " kB";
|
|
553
|
+
}
|
|
554
|
+
const units = ["B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
|
|
555
|
+
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
556
|
+
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + " " + units[i];
|
|
557
|
+
}
|
|
558
|
+
function printFileOutput(fileSize2, outputDir, outputFile) {
|
|
559
|
+
const indent = " ".repeat(2);
|
|
560
|
+
const paddedSize = fileSize2.padStart(9, " ");
|
|
561
|
+
console.log(
|
|
562
|
+
`${indent}${dim(paddedSize)} ${dim(outputDir)}${cyan(outputFile)}`
|
|
563
|
+
);
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
// src/cli/commands/dev.ts
|
|
567
|
+
import path5 from "node:path";
|
|
568
|
+
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
569
|
+
import { default as express } from "express";
|
|
570
|
+
|
|
571
|
+
// src/render/asset-map/dev-asset-map.ts
|
|
572
|
+
import path4 from "node:path";
|
|
573
|
+
import { searchForWorkspaceRoot as searchForWorkspaceRoot2 } from "vite";
|
|
574
|
+
var DevServerAssetMap = class {
|
|
575
|
+
constructor(rootConfig, moduleGraph) {
|
|
576
|
+
this.rootConfig = rootConfig;
|
|
577
|
+
this.moduleGraph = moduleGraph;
|
|
578
|
+
}
|
|
579
|
+
async get(src) {
|
|
580
|
+
const file = path4.resolve(this.rootConfig.rootDir, src);
|
|
581
|
+
const viteModules = this.moduleGraph.getModulesByFile(file);
|
|
582
|
+
if (viteModules && viteModules.size > 0) {
|
|
583
|
+
const [viteModule] = viteModules;
|
|
584
|
+
return new DevServerAsset(src, {
|
|
585
|
+
assetMap: this,
|
|
586
|
+
viteModule
|
|
587
|
+
});
|
|
588
|
+
}
|
|
589
|
+
if (file.startsWith(this.rootConfig.rootDir)) {
|
|
590
|
+
const assetUrl = file.slice(this.rootConfig.rootDir.length);
|
|
591
|
+
return {
|
|
472
592
|
src,
|
|
473
593
|
assetUrl,
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
isElement
|
|
594
|
+
getCssDeps: async () => [],
|
|
595
|
+
getJsDeps: async () => [assetUrl]
|
|
477
596
|
};
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
597
|
+
}
|
|
598
|
+
const workspaceRoot = searchForWorkspaceRoot2(this.rootConfig.rootDir);
|
|
599
|
+
if (await directoryContains(workspaceRoot, file)) {
|
|
600
|
+
const assetUrl = `/@fs/${file}`;
|
|
601
|
+
return {
|
|
602
|
+
src,
|
|
603
|
+
assetUrl,
|
|
604
|
+
getCssDeps: async () => [],
|
|
605
|
+
getJsDeps: async () => [assetUrl]
|
|
606
|
+
};
|
|
607
|
+
}
|
|
608
|
+
console.log(`could not find asset in asset map: ${src}`);
|
|
609
|
+
return null;
|
|
481
610
|
}
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
Object.keys(rootManifest).forEach((moduleId) => {
|
|
485
|
-
const assetData = rootManifest[moduleId];
|
|
486
|
-
assetMap.add(new BuildAsset(assetMap, assetData));
|
|
487
|
-
});
|
|
488
|
-
return assetMap;
|
|
611
|
+
filePathToSrc(file) {
|
|
612
|
+
return path4.relative(this.rootConfig.rootDir, file);
|
|
489
613
|
}
|
|
490
614
|
};
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
}
|
|
499
|
-
var BuildAsset = class {
|
|
500
|
-
constructor(assetMap, assetData) {
|
|
501
|
-
this.assetMap = assetMap;
|
|
502
|
-
this.src = assetData.src;
|
|
503
|
-
this.assetUrl = assetData.assetUrl;
|
|
504
|
-
this.importedModules = assetData.importedModules;
|
|
505
|
-
this.importedCss = assetData.importedCss;
|
|
506
|
-
this.isElement = assetData.isElement;
|
|
615
|
+
var DevServerAsset = class {
|
|
616
|
+
constructor(src, options) {
|
|
617
|
+
this.src = src;
|
|
618
|
+
this.assetMap = options.assetMap;
|
|
619
|
+
this.viteModule = options.viteModule;
|
|
620
|
+
this.moduleId = this.viteModule.id;
|
|
621
|
+
this.assetUrl = this.viteModule.url;
|
|
507
622
|
}
|
|
508
623
|
async getCssDeps() {
|
|
509
624
|
const visited = /* @__PURE__ */ new Set();
|
|
510
625
|
const deps = /* @__PURE__ */ new Set();
|
|
511
|
-
|
|
626
|
+
this.collectCss(this, deps, visited);
|
|
512
627
|
return Array.from(deps);
|
|
513
628
|
}
|
|
514
629
|
async getJsDeps() {
|
|
515
630
|
const visited = /* @__PURE__ */ new Set();
|
|
516
631
|
const deps = /* @__PURE__ */ new Set();
|
|
517
|
-
|
|
632
|
+
this.collectJs(this, deps, visited);
|
|
518
633
|
return Array.from(deps);
|
|
519
634
|
}
|
|
520
|
-
|
|
635
|
+
getImportedModules() {
|
|
636
|
+
return this.viteModule.importedModules;
|
|
637
|
+
}
|
|
638
|
+
collectJs(asset, urls, visited) {
|
|
521
639
|
if (!asset) {
|
|
522
640
|
return;
|
|
523
641
|
}
|
|
524
|
-
if (!asset.
|
|
642
|
+
if (!asset.moduleId) {
|
|
525
643
|
return;
|
|
526
644
|
}
|
|
527
|
-
if (visited.has(asset.
|
|
645
|
+
if (visited.has(asset.moduleId)) {
|
|
528
646
|
return;
|
|
529
647
|
}
|
|
530
|
-
visited.add(asset.
|
|
531
|
-
|
|
648
|
+
visited.add(asset.moduleId);
|
|
649
|
+
const parts = path4.parse(asset.assetUrl);
|
|
650
|
+
if ([".js", ".jsx", ".ts", ".tsx"].includes(parts.ext) && asset.moduleId.includes("/elements/")) {
|
|
532
651
|
urls.add(asset.assetUrl);
|
|
533
652
|
}
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
const
|
|
653
|
+
asset.getImportedModules().forEach((viteModule) => {
|
|
654
|
+
if (viteModule.file) {
|
|
655
|
+
const src = this.assetMap.filePathToSrc(viteModule.file);
|
|
656
|
+
const importedAsset = new DevServerAsset(src, {
|
|
657
|
+
assetMap: this.assetMap,
|
|
658
|
+
viteModule
|
|
659
|
+
});
|
|
537
660
|
this.collectJs(importedAsset, urls, visited);
|
|
538
|
-
}
|
|
539
|
-
);
|
|
661
|
+
}
|
|
662
|
+
});
|
|
540
663
|
}
|
|
541
|
-
|
|
664
|
+
collectCss(asset, urls, visited) {
|
|
542
665
|
if (!asset) {
|
|
543
666
|
return;
|
|
544
667
|
}
|
|
545
|
-
if (!asset.
|
|
668
|
+
if (!asset.assetUrl) {
|
|
546
669
|
return;
|
|
547
670
|
}
|
|
548
|
-
if (visited.has(asset.
|
|
671
|
+
if (visited.has(asset.assetUrl)) {
|
|
549
672
|
return;
|
|
550
673
|
}
|
|
551
|
-
visited.add(asset.
|
|
552
|
-
if (asset.
|
|
553
|
-
|
|
674
|
+
visited.add(asset.assetUrl);
|
|
675
|
+
if (asset.src.endsWith(".scss")) {
|
|
676
|
+
const parts = path4.parse(asset.src);
|
|
677
|
+
if (!parts.name.startsWith("_")) {
|
|
678
|
+
urls.add(asset.assetUrl);
|
|
679
|
+
}
|
|
554
680
|
}
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
const
|
|
681
|
+
asset.getImportedModules().forEach((viteModule) => {
|
|
682
|
+
if (viteModule.file) {
|
|
683
|
+
const src = this.assetMap.filePathToSrc(viteModule.file);
|
|
684
|
+
const importedAsset = new DevServerAsset(src, {
|
|
685
|
+
assetMap: this.assetMap,
|
|
686
|
+
viteModule
|
|
687
|
+
});
|
|
558
688
|
this.collectCss(importedAsset, urls, visited);
|
|
559
|
-
}
|
|
560
|
-
);
|
|
561
|
-
}
|
|
562
|
-
toJson() {
|
|
563
|
-
return {
|
|
564
|
-
src: this.src,
|
|
565
|
-
assetUrl: this.assetUrl,
|
|
566
|
-
importedModules: this.importedModules,
|
|
567
|
-
importedCss: this.importedCss,
|
|
568
|
-
isElement: this.isElement
|
|
569
|
-
};
|
|
689
|
+
}
|
|
690
|
+
});
|
|
570
691
|
}
|
|
571
692
|
};
|
|
572
693
|
|
|
573
|
-
// src/cli/commands/
|
|
574
|
-
import { dim as dim2
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
694
|
+
// src/cli/commands/dev.ts
|
|
695
|
+
import { dim as dim2 } from "kleur/colors";
|
|
696
|
+
|
|
697
|
+
// src/core/middleware.ts
|
|
698
|
+
function rootProjectMiddleware(options) {
|
|
699
|
+
return (req, _, next) => {
|
|
700
|
+
req.rootConfig = options.rootConfig;
|
|
701
|
+
next();
|
|
702
|
+
};
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
// src/utils/ports.ts
|
|
706
|
+
import { createServer } from "node:net";
|
|
707
|
+
function isPortOpen(port) {
|
|
708
|
+
return new Promise((resolve, reject) => {
|
|
709
|
+
const server = createServer();
|
|
710
|
+
server.on("error", (err) => {
|
|
711
|
+
if (err.code === "EADDRINUSE") {
|
|
712
|
+
resolve(false);
|
|
713
|
+
return;
|
|
714
|
+
}
|
|
715
|
+
reject(err);
|
|
716
|
+
});
|
|
717
|
+
server.on("close", () => {
|
|
718
|
+
resolve(true);
|
|
719
|
+
});
|
|
720
|
+
server.listen(port, () => {
|
|
721
|
+
server.close((err) => {
|
|
722
|
+
if (err) {
|
|
723
|
+
console.log(`error closing server: ${err}`);
|
|
724
|
+
reject(err);
|
|
725
|
+
}
|
|
726
|
+
});
|
|
727
|
+
});
|
|
728
|
+
});
|
|
729
|
+
}
|
|
730
|
+
async function findOpenPort(min, max) {
|
|
731
|
+
let port = min;
|
|
732
|
+
while (port <= max) {
|
|
733
|
+
const isOpen = await isPortOpen(port);
|
|
734
|
+
if (isOpen) {
|
|
735
|
+
return port;
|
|
736
|
+
}
|
|
737
|
+
port += 1;
|
|
738
|
+
}
|
|
739
|
+
throw new Error(`no ports open between ${min} and ${max}`);
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
// src/cli/commands/dev.ts
|
|
743
|
+
import glob3 from "tiny-glob";
|
|
744
|
+
var __dirname2 = path5.dirname(fileURLToPath2(import.meta.url));
|
|
745
|
+
async function dev(rootProjectDir) {
|
|
746
|
+
process.env.NODE_ENV = "development";
|
|
580
747
|
const rootDir = path5.resolve(rootProjectDir || process.cwd());
|
|
581
|
-
const
|
|
582
|
-
const
|
|
583
|
-
const ssrOnly = (options == null ? void 0 : options.ssrOnly) || false;
|
|
748
|
+
const defaultPort = parseInt(process.env.PORT || "4007");
|
|
749
|
+
const port = await findOpenPort(defaultPort, defaultPort + 10);
|
|
584
750
|
console.log();
|
|
585
751
|
console.log(`${dim2("\u2503")} project: ${rootDir}`);
|
|
586
|
-
console.log(`${dim2("\u2503")}
|
|
587
|
-
console.log(`${dim2("\u2503")} mode:
|
|
752
|
+
console.log(`${dim2("\u2503")} server: http://localhost:${port}`);
|
|
753
|
+
console.log(`${dim2("\u2503")} mode: development`);
|
|
588
754
|
console.log();
|
|
589
|
-
await
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
755
|
+
const server = await createDevServer({ rootDir, port });
|
|
756
|
+
server.listen(port);
|
|
757
|
+
}
|
|
758
|
+
async function createDevServer(options) {
|
|
759
|
+
const rootDir = path5.resolve((options == null ? void 0 : options.rootDir) || process.cwd());
|
|
760
|
+
const rootConfig = await loadRootConfig(rootDir, { command: "dev" });
|
|
761
|
+
const port = options == null ? void 0 : options.port;
|
|
762
|
+
const server = express();
|
|
763
|
+
server.disable("x-powered-by");
|
|
764
|
+
server.use(rootProjectMiddleware({ rootConfig }));
|
|
765
|
+
server.use(await viteServerMiddleware({ rootConfig, port }));
|
|
766
|
+
const plugins = rootConfig.plugins || [];
|
|
767
|
+
await configureServerPlugins(
|
|
768
|
+
server,
|
|
769
|
+
async () => {
|
|
770
|
+
var _a;
|
|
771
|
+
const userMiddlewares = ((_a = rootConfig.server) == null ? void 0 : _a.middlewares) || [];
|
|
772
|
+
for (const middleware of userMiddlewares) {
|
|
773
|
+
server.use(middleware);
|
|
598
774
|
}
|
|
599
|
-
|
|
600
|
-
|
|
775
|
+
server.use(rootDevServerMiddleware());
|
|
776
|
+
server.use(rootDevServer404Middleware());
|
|
777
|
+
server.use(rootDevServer500Middleware());
|
|
778
|
+
},
|
|
779
|
+
plugins,
|
|
780
|
+
{ type: "dev", rootConfig }
|
|
781
|
+
);
|
|
782
|
+
return server;
|
|
783
|
+
}
|
|
784
|
+
async function viteServerMiddleware(options) {
|
|
785
|
+
const rootConfig = options.rootConfig;
|
|
786
|
+
const rootDir = rootConfig.rootDir;
|
|
601
787
|
const elementGraph = await getElements(rootConfig);
|
|
602
788
|
const elements = Object.values(elementGraph.sourceFiles).map((sourceFile) => {
|
|
603
|
-
return sourceFile.
|
|
789
|
+
return sourceFile.relPath;
|
|
604
790
|
});
|
|
605
791
|
const bundleScripts = [];
|
|
606
792
|
if (await isDirectory(path5.join(rootDir, "bundles"))) {
|
|
@@ -608,263 +794,79 @@ async function build(rootProjectDir, options) {
|
|
|
608
794
|
bundleFiles.forEach((file) => {
|
|
609
795
|
const parts = path5.parse(file);
|
|
610
796
|
if (isJsFile(parts.base)) {
|
|
611
|
-
bundleScripts.push(
|
|
797
|
+
bundleScripts.push(file);
|
|
612
798
|
}
|
|
613
799
|
});
|
|
614
800
|
}
|
|
615
|
-
const
|
|
616
|
-
const
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
...getVitePlugins(rootPlugins)
|
|
620
|
-
];
|
|
621
|
-
const baseConfig = {
|
|
622
|
-
...viteConfig,
|
|
623
|
-
root: rootDir,
|
|
624
|
-
mode,
|
|
625
|
-
esbuild: {
|
|
626
|
-
...viteConfig.esbuild,
|
|
627
|
-
jsx: "automatic",
|
|
628
|
-
jsxImportSource: "preact",
|
|
629
|
-
treeShaking: true
|
|
630
|
-
},
|
|
631
|
-
plugins: vitePlugins
|
|
632
|
-
};
|
|
633
|
-
const ssrInput = {
|
|
634
|
-
render: path5.resolve(__dirname2, "./render.js")
|
|
635
|
-
};
|
|
636
|
-
rootPlugins.forEach((plugin) => {
|
|
637
|
-
if (plugin.ssrInput) {
|
|
638
|
-
Object.assign(ssrInput, plugin.ssrInput());
|
|
639
|
-
}
|
|
640
|
-
});
|
|
641
|
-
const noExternalConfig = (_a = viteConfig.ssr) == null ? void 0 : _a.noExternal;
|
|
642
|
-
const noExternal = [];
|
|
643
|
-
if (noExternalConfig) {
|
|
644
|
-
if (Array.isArray(noExternalConfig)) {
|
|
645
|
-
noExternal.push(...noExternalConfig);
|
|
646
|
-
} else {
|
|
647
|
-
noExternal.push(noExternalConfig);
|
|
648
|
-
}
|
|
649
|
-
}
|
|
650
|
-
await viteBuild({
|
|
651
|
-
...baseConfig,
|
|
652
|
-
publicDir: false,
|
|
653
|
-
build: {
|
|
654
|
-
...viteConfig == null ? void 0 : viteConfig.build,
|
|
655
|
-
rollupOptions: {
|
|
656
|
-
...(_b = viteConfig == null ? void 0 : viteConfig.build) == null ? void 0 : _b.rollupOptions,
|
|
657
|
-
input: ssrInput,
|
|
658
|
-
output: {
|
|
659
|
-
format: "esm",
|
|
660
|
-
chunkFileNames: "chunks/[name].[hash].min.js",
|
|
661
|
-
assetFileNames: "assets/[name].[hash][extname]"
|
|
662
|
-
}
|
|
663
|
-
},
|
|
664
|
-
outDir: path5.join(distDir, "server"),
|
|
665
|
-
ssr: true,
|
|
666
|
-
ssrManifest: false,
|
|
667
|
-
cssCodeSplit: true,
|
|
668
|
-
target: "esnext",
|
|
669
|
-
minify: false,
|
|
670
|
-
modulePreload: { polyfill: false },
|
|
671
|
-
reportCompressedSize: false
|
|
672
|
-
},
|
|
673
|
-
ssr: {
|
|
674
|
-
...viteConfig.ssr,
|
|
675
|
-
target: "node",
|
|
676
|
-
noExternal: ["@blinkk/root", ...noExternal]
|
|
677
|
-
}
|
|
678
|
-
});
|
|
679
|
-
await viteBuild({
|
|
680
|
-
...baseConfig,
|
|
681
|
-
publicDir: false,
|
|
682
|
-
build: {
|
|
683
|
-
...viteConfig == null ? void 0 : viteConfig.build,
|
|
684
|
-
rollupOptions: {
|
|
685
|
-
...(_c = viteConfig == null ? void 0 : viteConfig.build) == null ? void 0 : _c.rollupOptions,
|
|
686
|
-
input: [...routeFiles],
|
|
687
|
-
output: {
|
|
688
|
-
format: "esm",
|
|
689
|
-
entryFileNames: "assets/[name].[hash].min.js",
|
|
690
|
-
chunkFileNames: "chunks/[name].[hash].min.js",
|
|
691
|
-
assetFileNames: "assets/[name].[hash][extname]",
|
|
692
|
-
...(_e = (_d = viteConfig == null ? void 0 : viteConfig.build) == null ? void 0 : _d.rollupOptions) == null ? void 0 : _e.output
|
|
693
|
-
}
|
|
694
|
-
},
|
|
695
|
-
outDir: path5.join(distDir, "routes"),
|
|
696
|
-
ssr: false,
|
|
697
|
-
ssrManifest: false,
|
|
698
|
-
manifest: true,
|
|
699
|
-
cssCodeSplit: true,
|
|
700
|
-
target: "esnext",
|
|
701
|
-
minify: true,
|
|
702
|
-
modulePreload: { polyfill: false },
|
|
703
|
-
reportCompressedSize: false
|
|
704
|
-
}
|
|
801
|
+
const optimizeDeps = [...elements, ...bundleScripts];
|
|
802
|
+
const viteServer = await createViteServer(rootConfig, {
|
|
803
|
+
port: options.port,
|
|
804
|
+
optimizeDeps
|
|
705
805
|
});
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
...(_h = (_g = viteConfig == null ? void 0 : viteConfig.build) == null ? void 0 : _g.rollupOptions) == null ? void 0 : _h.output
|
|
722
|
-
}
|
|
723
|
-
},
|
|
724
|
-
outDir: path5.join(distDir, "client"),
|
|
725
|
-
ssr: false,
|
|
726
|
-
ssrManifest: false,
|
|
727
|
-
manifest: true,
|
|
728
|
-
cssCodeSplit: true,
|
|
729
|
-
target: "esnext",
|
|
730
|
-
minify: true,
|
|
731
|
-
modulePreload: { polyfill: false },
|
|
732
|
-
reportCompressedSize: false
|
|
733
|
-
}
|
|
734
|
-
});
|
|
735
|
-
} else {
|
|
736
|
-
await writeFile(path5.join(distDir, "client/manifest.json"), "{}");
|
|
737
|
-
}
|
|
738
|
-
await copyGlob(
|
|
739
|
-
"*.css",
|
|
740
|
-
path5.join(distDir, "routes/assets"),
|
|
741
|
-
path5.join(distDir, "client/assets")
|
|
742
|
-
);
|
|
743
|
-
const routesManifest = await loadJson(
|
|
744
|
-
path5.join(distDir, "routes/manifest.json")
|
|
745
|
-
);
|
|
746
|
-
const clientManifest = await loadJson(
|
|
747
|
-
path5.join(distDir, "client/manifest.json")
|
|
748
|
-
);
|
|
749
|
-
function collectRouteCss(asset, cssDeps, visited) {
|
|
750
|
-
if (!asset || !asset.file || visited.has(asset.file)) {
|
|
751
|
-
return;
|
|
752
|
-
}
|
|
753
|
-
visited.add(asset.file);
|
|
754
|
-
if (asset.css) {
|
|
755
|
-
asset.css.forEach((dep) => cssDeps.add(dep));
|
|
756
|
-
}
|
|
757
|
-
if (asset.imports) {
|
|
758
|
-
asset.imports.forEach((manifestKey) => {
|
|
759
|
-
collectRouteCss(routesManifest[manifestKey], cssDeps, visited);
|
|
760
|
-
});
|
|
806
|
+
return async (req, res, next) => {
|
|
807
|
+
try {
|
|
808
|
+
req.viteServer = viteServer;
|
|
809
|
+
const renderModulePath = path5.resolve(__dirname2, "./render.js");
|
|
810
|
+
const render = await viteServer.ssrLoadModule(
|
|
811
|
+
renderModulePath
|
|
812
|
+
);
|
|
813
|
+
const assetMap = new DevServerAssetMap(
|
|
814
|
+
rootConfig,
|
|
815
|
+
viteServer.moduleGraph
|
|
816
|
+
);
|
|
817
|
+
req.renderer = new render.Renderer(rootConfig, { assetMap, elementGraph });
|
|
818
|
+
viteServer.middlewares(req, res, next);
|
|
819
|
+
} catch (e) {
|
|
820
|
+
next(e);
|
|
761
821
|
}
|
|
762
|
-
}
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
clientManifest[manifestKey] = asset;
|
|
822
|
+
};
|
|
823
|
+
}
|
|
824
|
+
function rootDevServerMiddleware() {
|
|
825
|
+
return async (req, res, next) => {
|
|
826
|
+
const renderer = req.renderer;
|
|
827
|
+
const viteServer = req.viteServer;
|
|
828
|
+
try {
|
|
829
|
+
await renderer.handle(req, res, next);
|
|
830
|
+
} catch (err) {
|
|
831
|
+
viteServer.ssrFixStacktrace(err);
|
|
832
|
+
next(err);
|
|
774
833
|
}
|
|
775
|
-
}
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
if (fsExtra.existsSync(path5.join(rootDir, "public"))) {
|
|
789
|
-
fsExtra.copySync(publicDir, buildDir, { dereference: true });
|
|
790
|
-
} else {
|
|
791
|
-
await makeDir(buildDir);
|
|
792
|
-
}
|
|
793
|
-
await makeDir(path5.join(buildDir, "assets"));
|
|
794
|
-
await makeDir(path5.join(buildDir, "chunks"));
|
|
795
|
-
console.log("\njs/css output:");
|
|
796
|
-
await Promise.all(
|
|
797
|
-
Object.keys(rootManifest).map(async (src) => {
|
|
798
|
-
if (isRouteFile(src)) {
|
|
799
|
-
return;
|
|
800
|
-
}
|
|
801
|
-
const assetData = rootManifest[src];
|
|
802
|
-
if (!assetData.assetUrl) {
|
|
834
|
+
};
|
|
835
|
+
}
|
|
836
|
+
function rootDevServer404Middleware() {
|
|
837
|
+
return async (req, res) => {
|
|
838
|
+
console.error(`\u2753 404 ${req.originalUrl}`);
|
|
839
|
+
if (req.renderer) {
|
|
840
|
+
const url = req.path;
|
|
841
|
+
const ext = path5.extname(url);
|
|
842
|
+
if (!ext) {
|
|
843
|
+
const renderer = req.renderer;
|
|
844
|
+
const data = await renderer.renderDevServer404(req);
|
|
845
|
+
const html = data.html || "";
|
|
846
|
+
res.status(404).set({ "Content-Type": "text/html" }).end(html);
|
|
803
847
|
return;
|
|
804
848
|
}
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
849
|
+
}
|
|
850
|
+
res.status(404).set({ "Content-Type": "text/plain" }).end("404");
|
|
851
|
+
};
|
|
852
|
+
}
|
|
853
|
+
function rootDevServer500Middleware() {
|
|
854
|
+
return async (err, req, res, next) => {
|
|
855
|
+
console.error(`\u2757 500 ${req.originalUrl}`);
|
|
856
|
+
console.error(String(err.stack || err));
|
|
857
|
+
if (req.renderer) {
|
|
858
|
+
const url = req.path;
|
|
859
|
+
const ext = path5.extname(url);
|
|
860
|
+
if (!ext) {
|
|
861
|
+
const renderer = req.renderer;
|
|
862
|
+
const data = await renderer.renderDevServer500(req, err);
|
|
863
|
+
const html = data.html || "";
|
|
864
|
+
res.status(500).set({ "Content-Type": "text/html" }).end(html);
|
|
810
865
|
return;
|
|
811
866
|
}
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
);
|
|
816
|
-
if (!ssrOnly) {
|
|
817
|
-
const render = await import(path5.join(distDir, "server/render.js"));
|
|
818
|
-
const renderer = new render.Renderer(rootConfig, { assetMap, elementGraph });
|
|
819
|
-
const sitemap = await renderer.getSitemap();
|
|
820
|
-
console.log("\nhtml output:");
|
|
821
|
-
await Promise.all(
|
|
822
|
-
Object.keys(sitemap).map(async (urlPath) => {
|
|
823
|
-
const { route, params } = sitemap[urlPath];
|
|
824
|
-
const data = await renderer.renderRoute(route, {
|
|
825
|
-
routeParams: params
|
|
826
|
-
});
|
|
827
|
-
if (data.notFound) {
|
|
828
|
-
return;
|
|
829
|
-
}
|
|
830
|
-
let outFilePath = path5.join(urlPath.slice(1), "index.html");
|
|
831
|
-
if (outFilePath.endsWith("404/index.html")) {
|
|
832
|
-
outFilePath = outFilePath.replace("404/index.html", "404.html");
|
|
833
|
-
}
|
|
834
|
-
const outPath = path5.join(buildDir, outFilePath);
|
|
835
|
-
let html = data.html || "";
|
|
836
|
-
if (rootConfig.prettyHtml !== false) {
|
|
837
|
-
html = await htmlPretty(html, rootConfig.prettyHtmlOptions);
|
|
838
|
-
}
|
|
839
|
-
if (rootConfig.minifyHtml !== false) {
|
|
840
|
-
html = await htmlMinify(html, rootConfig.minifyHtmlOptions);
|
|
841
|
-
}
|
|
842
|
-
await writeFile(outPath, html);
|
|
843
|
-
printFileOutput(fileSize(outPath), "dist/html/", outFilePath);
|
|
844
|
-
})
|
|
845
|
-
);
|
|
846
|
-
}
|
|
847
|
-
}
|
|
848
|
-
function isRouteFile(filepath) {
|
|
849
|
-
return filepath.startsWith("routes") && isJsFile(filepath);
|
|
850
|
-
}
|
|
851
|
-
function fileSize(filepath) {
|
|
852
|
-
const stats = fsExtra.statSync(filepath);
|
|
853
|
-
const bytes = stats.size;
|
|
854
|
-
const k = 1024;
|
|
855
|
-
if (bytes < k) {
|
|
856
|
-
return (bytes / k).toFixed(2) + " kB";
|
|
857
|
-
}
|
|
858
|
-
const units = ["B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
|
|
859
|
-
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
860
|
-
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + " " + units[i];
|
|
861
|
-
}
|
|
862
|
-
function printFileOutput(fileSize2, outputDir, outputFile) {
|
|
863
|
-
const indent = " ".repeat(2);
|
|
864
|
-
const paddedSize = fileSize2.padStart(9, " ");
|
|
865
|
-
console.log(
|
|
866
|
-
`${indent}${dim2(paddedSize)} ${dim2(outputDir)}${cyan(outputFile)}`
|
|
867
|
-
);
|
|
867
|
+
}
|
|
868
|
+
next(err);
|
|
869
|
+
};
|
|
868
870
|
}
|
|
869
871
|
|
|
870
872
|
// src/cli/commands/preview.ts
|
|
@@ -876,7 +878,7 @@ import compression from "compression";
|
|
|
876
878
|
async function preview(rootProjectDir) {
|
|
877
879
|
process.env.NODE_ENV = "development";
|
|
878
880
|
const rootDir = path6.resolve(rootProjectDir || process.cwd());
|
|
879
|
-
const server = await
|
|
881
|
+
const server = await createPreviewServer({ rootDir });
|
|
880
882
|
const port = parseInt(process.env.PORT || "4007");
|
|
881
883
|
console.log();
|
|
882
884
|
console.log(`${dim3("\u2503")} project: ${rootDir}`);
|
|
@@ -885,7 +887,7 @@ async function preview(rootProjectDir) {
|
|
|
885
887
|
console.log();
|
|
886
888
|
server.listen(port);
|
|
887
889
|
}
|
|
888
|
-
async function
|
|
890
|
+
async function createPreviewServer(options) {
|
|
889
891
|
const rootDir = options.rootDir;
|
|
890
892
|
const rootConfig = await loadRootConfig(rootDir, { command: "preview" });
|
|
891
893
|
const distDir = path6.join(rootDir, "dist");
|
|
@@ -990,7 +992,7 @@ import compression2 from "compression";
|
|
|
990
992
|
async function start(rootProjectDir) {
|
|
991
993
|
process.env.NODE_ENV = "production";
|
|
992
994
|
const rootDir = path7.resolve(rootProjectDir || process.cwd());
|
|
993
|
-
const server = await
|
|
995
|
+
const server = await createProdServer({ rootDir });
|
|
994
996
|
const port = parseInt(process.env.PORT || "4007");
|
|
995
997
|
console.log();
|
|
996
998
|
console.log(`${dim4("\u2503")} project: ${rootDir}`);
|
|
@@ -999,7 +1001,7 @@ async function start(rootProjectDir) {
|
|
|
999
1001
|
console.log();
|
|
1000
1002
|
server.listen(port);
|
|
1001
1003
|
}
|
|
1002
|
-
async function
|
|
1004
|
+
async function createProdServer(options) {
|
|
1003
1005
|
const rootDir = options.rootDir;
|
|
1004
1006
|
const rootConfig = await loadRootConfig(rootDir, { command: "start" });
|
|
1005
1007
|
const distDir = path7.join(rootDir, "dist");
|
|
@@ -1100,6 +1102,9 @@ function rootProdServer500Middleware() {
|
|
|
1100
1102
|
}
|
|
1101
1103
|
export {
|
|
1102
1104
|
build,
|
|
1105
|
+
createDevServer,
|
|
1106
|
+
createPreviewServer,
|
|
1107
|
+
createProdServer,
|
|
1103
1108
|
dev,
|
|
1104
1109
|
preview,
|
|
1105
1110
|
start
|