@nasti-toolchain/nasti 2.5.0 → 2.5.2
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/README.md +34 -2
- package/dist/build-CENae4VM.js +748 -0
- package/dist/build-CENae4VM.js.map +1 -0
- package/dist/build-vjh6h7PB.cjs +786 -0
- package/dist/build-vjh6h7PB.cjs.map +1 -0
- package/dist/cli.cjs +166 -7608
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.d.cts +1 -2
- package/dist/cli.d.ts +1 -2
- package/dist/cli.js +166 -7606
- package/dist/cli.js.map +1 -1
- package/dist/client/hmr.cjs +0 -19
- package/dist/client/hmr.d.cts +14 -12
- package/dist/client/hmr.d.cts.map +1 -0
- package/dist/client/hmr.d.ts +14 -12
- package/dist/client/hmr.d.ts.map +1 -0
- package/dist/client/hmr.js +1 -1
- package/dist/dev-engine-DJL9sfv5.cjs +473 -0
- package/dist/dev-engine-DJL9sfv5.cjs.map +1 -0
- package/dist/dev-engine-DapuTPIz.js +469 -0
- package/dist/dev-engine-DapuTPIz.js.map +1 -0
- package/dist/electron-Bj8H-BJ6.js +278 -0
- package/dist/electron-Bj8H-BJ6.js.map +1 -0
- package/dist/electron-D0PSXz-a.cjs +316 -0
- package/dist/electron-D0PSXz-a.cjs.map +1 -0
- package/dist/electron-dev-BzI2IFnR.cjs +272 -0
- package/dist/electron-dev-BzI2IFnR.cjs.map +1 -0
- package/dist/electron-dev-CM15gsFp.js +251 -0
- package/dist/electron-dev-CM15gsFp.js.map +1 -0
- package/dist/env-GY7K1zPK.js +833 -0
- package/dist/env-GY7K1zPK.js.map +1 -0
- package/dist/env-lOj3yw8v.cjs +924 -0
- package/dist/env-lOj3yw8v.cjs.map +1 -0
- package/dist/environment-B2jCrhY2.js +1361 -0
- package/dist/environment-B2jCrhY2.js.map +1 -0
- package/dist/environment-CjmvoHIG.cjs +1443 -0
- package/dist/environment-CjmvoHIG.cjs.map +1 -0
- package/dist/index.cjs +453 -7976
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +872 -817
- package/dist/index.d.cts.map +1 -0
- package/dist/index.d.ts +872 -817
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +418 -7939
- package/dist/index.js.map +1 -1
- package/dist/logger-BVZwdqqT.js +116 -0
- package/dist/logger-BVZwdqqT.js.map +1 -0
- package/dist/logger-M7AuVVTV.cjs +171 -0
- package/dist/logger-M7AuVVTV.cjs.map +1 -0
- package/dist/runnable-environment-BjoOvdDa.js +1345 -0
- package/dist/runnable-environment-BjoOvdDa.js.map +1 -0
- package/dist/runnable-environment-ByA3DHQ6.cjs +1351 -0
- package/dist/runnable-environment-ByA3DHQ6.cjs.map +1 -0
- package/dist/server-Bqgl25z0.js +1871 -0
- package/dist/server-Bqgl25z0.js.map +1 -0
- package/dist/server-BynlMdFc.cjs +1895 -0
- package/dist/server-BynlMdFc.cjs.map +1 -0
- package/package.json +20 -10
- package/dist/client/hmr.cjs.map +0 -1
- package/dist/client/hmr.js.map +0 -1
|
@@ -0,0 +1,748 @@
|
|
|
1
|
+
import { a as __exportAll } from "./logger-BVZwdqqT.js";
|
|
2
|
+
import { a as matchesReactFilter, c as transformReactCode, f as resolveConfig, h as resolveMinifyOption, i as ssrDefineOverrides, n as loadEnv, o as shouldTransform, p as getPluginApi, s as transformCode, t as buildEnvDefine } from "./env-GY7K1zPK.js";
|
|
3
|
+
import { c as processHtml, d as createCssEngine, f as getCssMetadata, l as readHtmlFile, o as resolvePluginList, p as createDebugger, s as htmlPlugin, t as NastiEnvironment } from "./environment-B2jCrhY2.js";
|
|
4
|
+
import { builtinModules } from "node:module";
|
|
5
|
+
import path from "node:path";
|
|
6
|
+
import fs from "node:fs";
|
|
7
|
+
import pc from "picocolors";
|
|
8
|
+
import { rolldown } from "rolldown";
|
|
9
|
+
import { gzipSync } from "node:zlib";
|
|
10
|
+
//#region src/plugins/react.ts
|
|
11
|
+
const REACT_FILE_RE = /\.[jt]sx(?:[?#].*)?$/;
|
|
12
|
+
function reactPlugin(config, environment) {
|
|
13
|
+
return {
|
|
14
|
+
name: "nasti:oxc-transform",
|
|
15
|
+
async transform(code, id) {
|
|
16
|
+
const result = await transformReactCode(id, code, {
|
|
17
|
+
react: config.react,
|
|
18
|
+
consumer: environment.consumer,
|
|
19
|
+
development: config.mode === "development",
|
|
20
|
+
sourcemap: !!environment.options.build.sourcemap,
|
|
21
|
+
target: environment.options.build.target,
|
|
22
|
+
onWarning: (message) => config.logger.warn(`[nasti:react] ${message}`)
|
|
23
|
+
});
|
|
24
|
+
if (!result) return null;
|
|
25
|
+
return {
|
|
26
|
+
code: result.code,
|
|
27
|
+
map: result.map ? JSON.parse(result.map) : void 0
|
|
28
|
+
};
|
|
29
|
+
},
|
|
30
|
+
handleHotUpdate(ctx) {
|
|
31
|
+
for (const mod of ctx.modules) if (REACT_FILE_RE.test(mod.url) && matchesReactFilter(mod.url, config.react.include, config.react.exclude)) mod.isSelfAccepting = true;
|
|
32
|
+
return ctx.modules;
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
//#endregion
|
|
37
|
+
//#region src/build/reporter.ts
|
|
38
|
+
const debug$1 = createDebugger("nasti:reporter");
|
|
39
|
+
/**
|
|
40
|
+
* 尝试创建原生体积报告插件(Rust 实现,gzip 并行计算)。
|
|
41
|
+
* 返回 null 表示当前 rolldown 版本不提供该实验导出,调用方应改用
|
|
42
|
+
* {@link reportBuildOutput} 的 JS 表格。
|
|
43
|
+
*/
|
|
44
|
+
async function tryNativeReporterPlugin(config, logger) {
|
|
45
|
+
try {
|
|
46
|
+
const { viteReporterPlugin } = await import("rolldown/experimental");
|
|
47
|
+
if (typeof viteReporterPlugin !== "function") return null;
|
|
48
|
+
return viteReporterPlugin({
|
|
49
|
+
root: config.root,
|
|
50
|
+
isTty: process.stdout.isTTY ?? false,
|
|
51
|
+
isLib: false,
|
|
52
|
+
assetsDir: config.build.assetsDir,
|
|
53
|
+
chunkLimit: config.build.chunkSizeWarningLimit,
|
|
54
|
+
warnLargeChunks: false,
|
|
55
|
+
reportCompressedSize: config.build.reportCompressedSize,
|
|
56
|
+
logInfo: (msg) => logger.info(msg)
|
|
57
|
+
});
|
|
58
|
+
} catch (err) {
|
|
59
|
+
debug$1?.(`native viteReporterPlugin unavailable, falling back to JS table: ${err}`);
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
const numberFormatter = new Intl.NumberFormat("en", {
|
|
64
|
+
maximumFractionDigits: 2,
|
|
65
|
+
minimumFractionDigits: 2
|
|
66
|
+
});
|
|
67
|
+
function displaySize(bytes) {
|
|
68
|
+
return `${numberFormatter.format(bytes / 1e3)} kB`;
|
|
69
|
+
}
|
|
70
|
+
function byteLength(content) {
|
|
71
|
+
if (content == null) return 0;
|
|
72
|
+
return typeof content === "string" ? Buffer.byteLength(content) : content.byteLength;
|
|
73
|
+
}
|
|
74
|
+
/** JS fallback:打印 Vite 形态的产物体积表(gzip 可经 reportCompressedSize 关闭) */
|
|
75
|
+
function reportBuildOutput(output, config, logger) {
|
|
76
|
+
const entries = [];
|
|
77
|
+
const compressed = config.build.reportCompressedSize;
|
|
78
|
+
for (const file of output) {
|
|
79
|
+
const content = file.type === "chunk" ? file.code : file.source;
|
|
80
|
+
const size = byteLength(content);
|
|
81
|
+
let gzip = null;
|
|
82
|
+
if (compressed && content != null) gzip = gzipSync(typeof content === "string" ? Buffer.from(content) : content).byteLength;
|
|
83
|
+
const ext = path.extname(file.fileName);
|
|
84
|
+
const group = file.type === "chunk" ? "js" : ext === ".css" ? "css" : "assets";
|
|
85
|
+
entries.push({
|
|
86
|
+
name: file.fileName,
|
|
87
|
+
size,
|
|
88
|
+
gzip,
|
|
89
|
+
group
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
const groupOrder = {
|
|
93
|
+
assets: 0,
|
|
94
|
+
css: 1,
|
|
95
|
+
js: 2
|
|
96
|
+
};
|
|
97
|
+
entries.sort((a, b) => groupOrder[a.group] - groupOrder[b.group] || a.size - b.size);
|
|
98
|
+
const outDirPrefix = `${config.build.outDir.replace(/\/$/, "")}/`;
|
|
99
|
+
const maxNameLen = Math.max(...entries.map((e) => (outDirPrefix + e.name).length), 0);
|
|
100
|
+
const maxSizeLen = Math.max(...entries.map((e) => displaySize(e.size).length), 0);
|
|
101
|
+
const groupColor = {
|
|
102
|
+
assets: pc.green,
|
|
103
|
+
css: pc.magenta,
|
|
104
|
+
js: pc.cyan
|
|
105
|
+
};
|
|
106
|
+
for (const e of entries) {
|
|
107
|
+
const color = groupColor[e.group];
|
|
108
|
+
const namePart = pc.dim(outDirPrefix) + color(e.name.padEnd(maxNameLen - outDirPrefix.length));
|
|
109
|
+
const sizePart = pc.dim(pc.bold(displaySize(e.size).padStart(maxSizeLen)));
|
|
110
|
+
const gzipPart = e.gzip != null ? pc.dim(` │ gzip: ${displaySize(e.gzip)}`) : "";
|
|
111
|
+
logger.info(`${namePart} ${sizePart}${gzipPart}`);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
/** 大 chunk 警告(独立于表格渲染路径,始终经 logger.warn 输出) */
|
|
115
|
+
function warnLargeChunks(output, config, logger) {
|
|
116
|
+
const limit = config.build.chunkSizeWarningLimit;
|
|
117
|
+
if (output.filter((f) => f.type === "chunk" && byteLength(f.code) / 1e3 > limit).length === 0) return;
|
|
118
|
+
logger.warn(pc.yellow(`\n(!) Some chunks are larger than ${limit} kB after minification. Consider:\n- Using dynamic import() to code-split the application\n- Configuring build.rolldownOptions.output.advancedChunks to isolate large dependencies\n- Adjusting build.chunkSizeWarningLimit to silence this warning`));
|
|
119
|
+
}
|
|
120
|
+
//#endregion
|
|
121
|
+
//#region src/core/build-app-context.ts
|
|
122
|
+
function createBuildAppContext(config, results) {
|
|
123
|
+
const output = [];
|
|
124
|
+
const emitted = /* @__PURE__ */ new Set();
|
|
125
|
+
const outDir = path.resolve(config.root, config.build.outDir);
|
|
126
|
+
let environmentArtifacts;
|
|
127
|
+
return {
|
|
128
|
+
config,
|
|
129
|
+
results,
|
|
130
|
+
get output() {
|
|
131
|
+
return Object.freeze([...output]);
|
|
132
|
+
},
|
|
133
|
+
getResult(environmentName) {
|
|
134
|
+
return results[environmentName];
|
|
135
|
+
},
|
|
136
|
+
getArtifact(environmentName, fileName) {
|
|
137
|
+
const normalized = normalizeEnvironmentFileName(fileName);
|
|
138
|
+
return results[environmentName]?.output.find((artifact) => normalizeEnvironmentFileName(artifact.fileName) === normalized);
|
|
139
|
+
},
|
|
140
|
+
getEntry(environmentName, entryName) {
|
|
141
|
+
const result = results[environmentName];
|
|
142
|
+
const fileName = result?.entries?.[entryName];
|
|
143
|
+
if (!fileName) return void 0;
|
|
144
|
+
return result.output.find((artifact) => normalizeEnvironmentFileName(artifact.fileName) === normalizeEnvironmentFileName(fileName));
|
|
145
|
+
},
|
|
146
|
+
getManifest(environmentName) {
|
|
147
|
+
return results[environmentName]?.manifest;
|
|
148
|
+
},
|
|
149
|
+
getChunk(environmentName, fileName) {
|
|
150
|
+
const normalized = normalizeEnvironmentFileName(fileName);
|
|
151
|
+
return results[environmentName]?.chunks?.[normalized];
|
|
152
|
+
},
|
|
153
|
+
getCss(environmentName) {
|
|
154
|
+
return results[environmentName]?.css;
|
|
155
|
+
},
|
|
156
|
+
getSourceMap(environmentName, fileName) {
|
|
157
|
+
const normalized = normalizeEnvironmentFileName(fileName);
|
|
158
|
+
return results[environmentName]?.sourceMaps?.[normalized];
|
|
159
|
+
},
|
|
160
|
+
resolvePublicPath(environmentName, fileName) {
|
|
161
|
+
const result = results[environmentName];
|
|
162
|
+
if (!result) return void 0;
|
|
163
|
+
const normalized = normalizeEnvironmentFileName(fileName);
|
|
164
|
+
return joinPublicPath(result.publicPath ?? config.base, normalized);
|
|
165
|
+
},
|
|
166
|
+
emitFile(file) {
|
|
167
|
+
const fileName = normalizeAppFileName(file.fileName);
|
|
168
|
+
const collisionKey = artifactCollisionKey(fileName);
|
|
169
|
+
if (emitted.has(collisionKey)) throw new Error(`[nasti] app artifact already emitted: ${fileName}`);
|
|
170
|
+
environmentArtifacts ??= collectEnvironmentArtifacts(config, results, outDir);
|
|
171
|
+
if (environmentArtifacts.has(collisionKey)) throw new Error(`[nasti] app artifact conflicts with environment output: ${fileName}`);
|
|
172
|
+
const target = path.resolve(outDir, ...fileName.split("/"));
|
|
173
|
+
const relative = path.relative(outDir, target);
|
|
174
|
+
if (relative.startsWith("..") || path.isAbsolute(relative)) throw new Error(`[nasti] app artifact must stay inside build.outDir: ${file.fileName}`);
|
|
175
|
+
assertNoSymlinkComponents(outDir, fileName);
|
|
176
|
+
fs.mkdirSync(path.dirname(target), { recursive: true });
|
|
177
|
+
fs.writeFileSync(target, file.source);
|
|
178
|
+
const artifact = {
|
|
179
|
+
...file,
|
|
180
|
+
fileName,
|
|
181
|
+
type: "asset"
|
|
182
|
+
};
|
|
183
|
+
emitted.add(collisionKey);
|
|
184
|
+
output.push(artifact);
|
|
185
|
+
return fileName;
|
|
186
|
+
}
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
function joinPublicPath(base, fileName) {
|
|
190
|
+
return `${base.endsWith("/") ? base : `${base}/`}${fileName.replace(/^\//, "")}`;
|
|
191
|
+
}
|
|
192
|
+
function normalizeEnvironmentFileName(fileName) {
|
|
193
|
+
return path.posix.normalize(fileName.replace(/\\/g, "/").replace(/^\.\//, ""));
|
|
194
|
+
}
|
|
195
|
+
function isInvalidEnvironmentFileName(fileName) {
|
|
196
|
+
return !fileName || fileName === "." || fileName === ".." || fileName.startsWith("../") || path.posix.isAbsolute(fileName) || /^[A-Za-z]:\//.test(fileName);
|
|
197
|
+
}
|
|
198
|
+
function normalizeAppFileName(fileName) {
|
|
199
|
+
const normalized = normalizeEnvironmentFileName(fileName);
|
|
200
|
+
if (isInvalidEnvironmentFileName(normalized)) throw new Error(`[nasti] invalid app artifact fileName: ${fileName}`);
|
|
201
|
+
return normalized;
|
|
202
|
+
}
|
|
203
|
+
function artifactCollisionKey(fileName) {
|
|
204
|
+
return normalizeEnvironmentFileName(fileName).toLowerCase();
|
|
205
|
+
}
|
|
206
|
+
function collectEnvironmentArtifacts(config, results, appOutDir) {
|
|
207
|
+
const occupied = /* @__PURE__ */ new Set();
|
|
208
|
+
for (const [environmentName, result] of Object.entries(results)) {
|
|
209
|
+
const environment = config.environments[environmentName];
|
|
210
|
+
if (!environment) continue;
|
|
211
|
+
const environmentOutDir = path.resolve(config.root, environment.build.outDir);
|
|
212
|
+
for (const artifact of result.output) {
|
|
213
|
+
const artifactPath = path.resolve(environmentOutDir, ...normalizeEnvironmentFileName(artifact.fileName).split("/"));
|
|
214
|
+
const relative = path.relative(appOutDir, artifactPath);
|
|
215
|
+
if (!relative.startsWith("..") && !path.isAbsolute(relative)) occupied.add(artifactCollisionKey(relative));
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
return occupied;
|
|
219
|
+
}
|
|
220
|
+
function assertNoSymlinkComponents(outDir, fileName) {
|
|
221
|
+
let current = outDir;
|
|
222
|
+
for (const segment of fileName.split("/")) {
|
|
223
|
+
current = path.join(current, segment);
|
|
224
|
+
let stats;
|
|
225
|
+
try {
|
|
226
|
+
stats = fs.lstatSync(current);
|
|
227
|
+
} catch (error) {
|
|
228
|
+
if (error.code === "ENOENT") continue;
|
|
229
|
+
throw error;
|
|
230
|
+
}
|
|
231
|
+
if (stats.isSymbolicLink()) throw new Error(`[nasti] app artifact path cannot traverse a symlink: ${fileName}`);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
function inferEnvironmentEntries(output) {
|
|
235
|
+
const entries = {};
|
|
236
|
+
for (const artifact of output) {
|
|
237
|
+
if (artifact.type !== "chunk" || !artifact.isEntry || !artifact.name) continue;
|
|
238
|
+
entries[artifact.name] = normalizeEnvironmentFileName(artifact.fileName);
|
|
239
|
+
}
|
|
240
|
+
return Object.keys(entries).length > 0 ? entries : void 0;
|
|
241
|
+
}
|
|
242
|
+
//#endregion
|
|
243
|
+
//#region src/build/index.ts
|
|
244
|
+
var build_exports = /* @__PURE__ */ __exportAll({
|
|
245
|
+
build: () => build,
|
|
246
|
+
getRolldownOptions: () => getRolldownOptions,
|
|
247
|
+
replaceEntryScript: () => replaceEntryScript,
|
|
248
|
+
resolveClientEntries: () => resolveClientEntries,
|
|
249
|
+
toRolldownPlugins: () => toRolldownPlugins
|
|
250
|
+
});
|
|
251
|
+
const debug = createDebugger("nasti:build");
|
|
252
|
+
const NODE_BUILTINS = /* @__PURE__ */ new Set([...builtinModules, ...builtinModules.map((m) => `node:${m}`)]);
|
|
253
|
+
/**
|
|
254
|
+
* 把单个环境的 rolldown input/output 选项收敛到一处(Phase 3 DevEngine 复用)。
|
|
255
|
+
* - input:user rolldownOptions 透传 + per-env platform/resolve/external/define
|
|
256
|
+
* - output:默认命名 + user output 覆盖 + dir 由 Nasti 强制
|
|
257
|
+
*/
|
|
258
|
+
function getRolldownOptions(environment, entryPoints, rolldownPlugins) {
|
|
259
|
+
const config = environment.config;
|
|
260
|
+
const envOptions = environment.options;
|
|
261
|
+
const isServer = environment.consumer === "server";
|
|
262
|
+
const outDir = path.resolve(config.root, envOptions.build.outDir);
|
|
263
|
+
const assetsDir = envOptions.build.assetsDir;
|
|
264
|
+
const { output: userOutput, transform: userTransform, resolve: userResolve, ...restInputOptions } = envOptions.build.rolldownOptions;
|
|
265
|
+
const vueDefine = config.framework === "vue" ? {
|
|
266
|
+
__VUE_OPTIONS_API__: "true",
|
|
267
|
+
__VUE_PROD_DEVTOOLS__: "false",
|
|
268
|
+
__VUE_PROD_HYDRATION_MISMATCH_DETAILS__: "false"
|
|
269
|
+
} : {};
|
|
270
|
+
const env = loadEnv(config.mode, config.root, config.envPrefix);
|
|
271
|
+
const envDefine = buildEnvDefine(env, config.mode, ssrDefineOverrides(environment.consumer));
|
|
272
|
+
const mergedDefine = {
|
|
273
|
+
...vueDefine,
|
|
274
|
+
...userTransform?.define ?? {},
|
|
275
|
+
...envDefine
|
|
276
|
+
};
|
|
277
|
+
return {
|
|
278
|
+
inputOptions: {
|
|
279
|
+
...restInputOptions,
|
|
280
|
+
input: entryPoints,
|
|
281
|
+
transform: {
|
|
282
|
+
...userTransform,
|
|
283
|
+
target: userTransform?.target ?? envOptions.build.target,
|
|
284
|
+
define: mergedDefine
|
|
285
|
+
},
|
|
286
|
+
plugins: rolldownPlugins,
|
|
287
|
+
resolve: {
|
|
288
|
+
...userResolve ?? {},
|
|
289
|
+
conditionNames: envOptions.resolve.conditions,
|
|
290
|
+
mainFields: envOptions.resolve.mainFields
|
|
291
|
+
},
|
|
292
|
+
...isServer ? {
|
|
293
|
+
platform: restInputOptions.platform ?? "node",
|
|
294
|
+
external: restInputOptions.external ?? ((id) => {
|
|
295
|
+
if (NODE_BUILTINS.has(id)) return true;
|
|
296
|
+
return !id.startsWith(".") && !path.isAbsolute(id) && !id.startsWith("\0") && !id.startsWith("virtual:");
|
|
297
|
+
})
|
|
298
|
+
} : {}
|
|
299
|
+
},
|
|
300
|
+
outputOptions: isServer ? {
|
|
301
|
+
format: "esm",
|
|
302
|
+
sourcemap: envOptions.build.sourcemap,
|
|
303
|
+
minify: resolveMinifyOption(envOptions.build.minify),
|
|
304
|
+
entryFileNames: "[name].js",
|
|
305
|
+
chunkFileNames: "chunks/[name]-[hash].js",
|
|
306
|
+
assetFileNames: `${assetsDir}/[name].[hash][extname]`,
|
|
307
|
+
...userOutput,
|
|
308
|
+
dir: outDir
|
|
309
|
+
} : {
|
|
310
|
+
format: "esm",
|
|
311
|
+
sourcemap: envOptions.build.sourcemap,
|
|
312
|
+
minify: resolveMinifyOption(envOptions.build.minify),
|
|
313
|
+
entryFileNames: `${assetsDir}/[name].[hash].js`,
|
|
314
|
+
chunkFileNames: `${assetsDir}/[name].[hash].js`,
|
|
315
|
+
assetFileNames: `${assetsDir}/[name].[hash][extname]`,
|
|
316
|
+
...userOutput,
|
|
317
|
+
dir: outDir
|
|
318
|
+
},
|
|
319
|
+
outDir
|
|
320
|
+
};
|
|
321
|
+
}
|
|
322
|
+
/**
|
|
323
|
+
* Nasti 插件 → Rolldown 插件转发表。包装器保留 Rolldown 的真实插件上下文,
|
|
324
|
+
* 同时注入当前 Nasti environment,供同为 client consumer 的 BG/MT 管线区分彼此。
|
|
325
|
+
*/
|
|
326
|
+
function toRolldownPlugins(plugins, environment) {
|
|
327
|
+
const wrap = (hook) => {
|
|
328
|
+
if (!hook) return hook;
|
|
329
|
+
return function(...args) {
|
|
330
|
+
return hook.apply(attachEnvironment(this, environment), args);
|
|
331
|
+
};
|
|
332
|
+
};
|
|
333
|
+
return plugins.map((p) => ({
|
|
334
|
+
name: p.name,
|
|
335
|
+
resolveId: wrap(p.resolveId),
|
|
336
|
+
load: wrap(p.load),
|
|
337
|
+
transform: wrap(p.transform),
|
|
338
|
+
buildStart: wrap(p.buildStart),
|
|
339
|
+
buildEnd: wrap(p.buildEnd),
|
|
340
|
+
closeBundle: wrap(p.closeBundle),
|
|
341
|
+
renderChunk: wrap(p.renderChunk),
|
|
342
|
+
augmentChunkHash: wrap(p.augmentChunkHash),
|
|
343
|
+
generateBundle: wrap(p.generateBundle)
|
|
344
|
+
}));
|
|
345
|
+
}
|
|
346
|
+
function attachEnvironment(context, environment) {
|
|
347
|
+
if (context?.environment === environment) return context;
|
|
348
|
+
try {
|
|
349
|
+
Object.defineProperty(context, "environment", {
|
|
350
|
+
configurable: true,
|
|
351
|
+
enumerable: false,
|
|
352
|
+
writable: false,
|
|
353
|
+
value: environment
|
|
354
|
+
});
|
|
355
|
+
return context;
|
|
356
|
+
} catch {
|
|
357
|
+
return new Proxy(context, {
|
|
358
|
+
get(target, property) {
|
|
359
|
+
if (property === "environment") return environment;
|
|
360
|
+
const value = Reflect.get(target, property, target);
|
|
361
|
+
return typeof value === "function" ? value.bind(target) : value;
|
|
362
|
+
},
|
|
363
|
+
set(target, property, value) {
|
|
364
|
+
return Reflect.set(target, property, value, target);
|
|
365
|
+
}
|
|
366
|
+
});
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
function finalizeEnvironmentResult(environment, result) {
|
|
370
|
+
const metadata = environment.getBuildMetadata();
|
|
371
|
+
const entries = {
|
|
372
|
+
...inferEnvironmentEntries(result.output),
|
|
373
|
+
...metadata.entries,
|
|
374
|
+
...result.entries
|
|
375
|
+
};
|
|
376
|
+
const normalizedEntries = Object.fromEntries(Object.entries(entries).map(([name, fileName]) => {
|
|
377
|
+
const normalized = normalizeEnvironmentFileName(fileName);
|
|
378
|
+
if (isInvalidEnvironmentFileName(normalized)) throw new Error(`[nasti] environment "${environment.name}" returned invalid entry "${name}": ${fileName}`);
|
|
379
|
+
return [name, normalized];
|
|
380
|
+
}));
|
|
381
|
+
const inferredMetadata = inferOutputMetadata(environment, result.output);
|
|
382
|
+
return {
|
|
383
|
+
publicPath: environment.config.base,
|
|
384
|
+
...inferredMetadata,
|
|
385
|
+
...metadata,
|
|
386
|
+
...result,
|
|
387
|
+
output: result.output,
|
|
388
|
+
chunks: {
|
|
389
|
+
...inferredMetadata.chunks,
|
|
390
|
+
...metadata.chunks,
|
|
391
|
+
...result.chunks
|
|
392
|
+
},
|
|
393
|
+
assets: {
|
|
394
|
+
...inferredMetadata.assets,
|
|
395
|
+
...metadata.assets,
|
|
396
|
+
...result.assets
|
|
397
|
+
},
|
|
398
|
+
sourceMaps: {
|
|
399
|
+
...inferredMetadata.sourceMaps,
|
|
400
|
+
...metadata.sourceMaps,
|
|
401
|
+
...result.sourceMaps
|
|
402
|
+
},
|
|
403
|
+
...Object.keys(normalizedEntries).length > 0 ? { entries: normalizedEntries } : {}
|
|
404
|
+
};
|
|
405
|
+
}
|
|
406
|
+
function inferOutputMetadata(environment, output) {
|
|
407
|
+
const chunks = {};
|
|
408
|
+
const assets = {};
|
|
409
|
+
const sourceMaps = {};
|
|
410
|
+
const cssChunks = environment.getBuildMetadata().css?.chunks ?? {};
|
|
411
|
+
const assetModules = environment.getAssetModules();
|
|
412
|
+
const publicPath = environment.config.base;
|
|
413
|
+
for (const artifact of output) {
|
|
414
|
+
const fileName = normalizeEnvironmentFileName(artifact.fileName);
|
|
415
|
+
if (artifact.map != null) sourceMaps[fileName] = artifact.map;
|
|
416
|
+
if (artifact.type === "chunk") {
|
|
417
|
+
const moduleIds = [...artifact.moduleIds ?? []];
|
|
418
|
+
chunks[fileName] = {
|
|
419
|
+
fileName,
|
|
420
|
+
name: artifact.name ?? fileName,
|
|
421
|
+
isEntry: !!artifact.isEntry,
|
|
422
|
+
isDynamicEntry: !!artifact.isDynamicEntry,
|
|
423
|
+
imports: [...artifact.imports ?? []],
|
|
424
|
+
dynamicImports: [...artifact.dynamicImports ?? []],
|
|
425
|
+
moduleIds,
|
|
426
|
+
css: [...cssChunks[fileName]?.cssFileNames ?? []],
|
|
427
|
+
assets: [...new Set(moduleIds.map((id) => assetModules[id]).filter((asset) => !!asset))]
|
|
428
|
+
};
|
|
429
|
+
} else if (artifact.type === "asset") assets[fileName] = {
|
|
430
|
+
fileName,
|
|
431
|
+
names: [...artifact.names ?? (artifact.name ? [artifact.name] : [])],
|
|
432
|
+
publicPath: joinPublicPath(publicPath, fileName)
|
|
433
|
+
};
|
|
434
|
+
}
|
|
435
|
+
return {
|
|
436
|
+
chunks,
|
|
437
|
+
assets,
|
|
438
|
+
sourceMaps
|
|
439
|
+
};
|
|
440
|
+
}
|
|
441
|
+
function prepareBuildOutputDirectories(config, buildableNames) {
|
|
442
|
+
const directories = /* @__PURE__ */ new Set();
|
|
443
|
+
const protectedPaths = /* @__PURE__ */ new Set();
|
|
444
|
+
if (!buildableNames.includes("client") && config.build.emptyOutDir) directories.add(path.resolve(config.root, config.build.outDir));
|
|
445
|
+
for (const name of buildableNames) {
|
|
446
|
+
const environment = config.environments[name];
|
|
447
|
+
const outDir = path.resolve(config.root, environment.build.outDir);
|
|
448
|
+
if (!environment.build.emptyOutDir) {
|
|
449
|
+
protectedPaths.add(outDir);
|
|
450
|
+
continue;
|
|
451
|
+
}
|
|
452
|
+
if (!environment.driver) directories.add(outDir);
|
|
453
|
+
}
|
|
454
|
+
const containsPath = (parent, child) => {
|
|
455
|
+
const relative = path.relative(parent, child);
|
|
456
|
+
return relative === "" || !relative.startsWith("..") && !path.isAbsolute(relative);
|
|
457
|
+
};
|
|
458
|
+
const roots = [...directories].filter((directory) => ![...protectedPaths].some((protectedPath) => containsPath(directory, protectedPath))).sort((a, b) => a.length - b.length).filter((directory, index, all) => !all.slice(0, index).some((parent) => containsPath(parent, directory)));
|
|
459
|
+
for (const directory of roots) if (fs.existsSync(directory)) fs.rmSync(directory, {
|
|
460
|
+
recursive: true,
|
|
461
|
+
force: true
|
|
462
|
+
});
|
|
463
|
+
}
|
|
464
|
+
function assertDriverBuildResult(environment, result) {
|
|
465
|
+
const output = result != null && typeof result === "object" ? result.output : void 0;
|
|
466
|
+
if (!(Array.isArray(output) && output.every((artifact) => artifact != null && typeof artifact === "object" && typeof artifact.fileName === "string" && typeof artifact.type === "string"))) throw new Error(`[nasti] environment "${environment.name}" driver "${environment.driver?.name}" returned an invalid build result; expected { output: EnvironmentBuildOutput[] }`);
|
|
467
|
+
}
|
|
468
|
+
/** 从 index.html 提取 client 入口(含常见路径回退) */
|
|
469
|
+
function resolveClientEntries(config, html) {
|
|
470
|
+
const configuredEntries = config.environments.client?.entry ?? [];
|
|
471
|
+
if (configuredEntries.length > 0) return configuredEntries;
|
|
472
|
+
const entryPoints = [];
|
|
473
|
+
const htmlFile = config.environments.client?.html;
|
|
474
|
+
const htmlDir = htmlFile ? path.dirname(htmlFile) : config.root;
|
|
475
|
+
if (html) {
|
|
476
|
+
const scriptMatches = html.matchAll(/<script[^>]+src=["']([^"']+)["'][^>]*>/gi);
|
|
477
|
+
for (const match of scriptMatches) {
|
|
478
|
+
const src = match[1];
|
|
479
|
+
if (src && !src.startsWith("http")) {
|
|
480
|
+
const cleanSrc = src.split(/[?#]/, 1)[0];
|
|
481
|
+
entryPoints.push(cleanSrc.startsWith("/") ? path.resolve(config.root, cleanSrc.replace(/^\//, "")) : path.resolve(htmlDir, cleanSrc));
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
if (entryPoints.length === 0) for (const entry of [
|
|
486
|
+
"src/main.ts",
|
|
487
|
+
"src/main.tsx",
|
|
488
|
+
"src/main.js",
|
|
489
|
+
"src/index.ts",
|
|
490
|
+
"src/index.tsx",
|
|
491
|
+
"src/index.js"
|
|
492
|
+
]) {
|
|
493
|
+
const fullPath = path.resolve(config.root, entry);
|
|
494
|
+
if (fs.existsSync(fullPath)) {
|
|
495
|
+
entryPoints.push(fullPath);
|
|
496
|
+
break;
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
return entryPoints;
|
|
500
|
+
}
|
|
501
|
+
/** 单个环境的 oxc 转译插件(TS/JSX,consumer 无关) */
|
|
502
|
+
function createOxcTransformPlugin(config, environment) {
|
|
503
|
+
if (config.framework === "react") return reactPlugin(config, environment);
|
|
504
|
+
return {
|
|
505
|
+
name: "nasti:oxc-transform",
|
|
506
|
+
transform(code, id) {
|
|
507
|
+
if (!shouldTransform(id)) return null;
|
|
508
|
+
const result = transformCode(id, code, {
|
|
509
|
+
sourcemap: !!environment.options.build.sourcemap,
|
|
510
|
+
target: environment.options.build.target,
|
|
511
|
+
jsxRuntime: "automatic",
|
|
512
|
+
jsxImportSource: config.framework === "vue" ? "vue" : "react"
|
|
513
|
+
});
|
|
514
|
+
return {
|
|
515
|
+
code: result.code,
|
|
516
|
+
map: result.map ? JSON.parse(result.map) : void 0
|
|
517
|
+
};
|
|
518
|
+
}
|
|
519
|
+
};
|
|
520
|
+
}
|
|
521
|
+
async function build(inlineConfig = {}) {
|
|
522
|
+
const config = await resolveConfig(inlineConfig, "build");
|
|
523
|
+
const logger = config.logger;
|
|
524
|
+
const startTime = performance.now();
|
|
525
|
+
logger.info(pc.cyan(`\nnasti v2.5.2 `) + pc.green(`building for ${config.mode}...`));
|
|
526
|
+
debug?.(`root: ${config.root}`);
|
|
527
|
+
const buildableNames = Object.keys(config.environments).filter((name) => {
|
|
528
|
+
const environment = config.environments[name];
|
|
529
|
+
if (!environment.buildEnabled) return false;
|
|
530
|
+
return name === "client" || environment.entry.length > 0 || !!environment.driver;
|
|
531
|
+
});
|
|
532
|
+
buildableNames.sort((a, b) => a === "client" ? -1 : b === "client" ? 1 : 0);
|
|
533
|
+
prepareBuildOutputDirectories(config, buildableNames);
|
|
534
|
+
const environments = {};
|
|
535
|
+
const environmentResults = {};
|
|
536
|
+
const initializedEnvironments = [];
|
|
537
|
+
const buildAppContext = createBuildAppContext(config, environmentResults);
|
|
538
|
+
let clientOutput = [];
|
|
539
|
+
let buildFailed = false;
|
|
540
|
+
try {
|
|
541
|
+
for (const name of buildableNames) {
|
|
542
|
+
const built = name === "client" ? await buildClientEnvironment(config) : await buildServerEnvironment(config, name);
|
|
543
|
+
initializedEnvironments.push(built.environment);
|
|
544
|
+
environments[name] = built.result.output;
|
|
545
|
+
environmentResults[name] = built.result;
|
|
546
|
+
if (name === "client") clientOutput = built.result.output;
|
|
547
|
+
if (buildableNames.length > 1) debug?.(`environment "${name}" built (${built.result.output.length} files)`);
|
|
548
|
+
}
|
|
549
|
+
const pluginApi = getPluginApi(config);
|
|
550
|
+
for (const plugin of config.plugins) await plugin.afterBuildApp?.(environmentResults, pluginApi, buildAppContext);
|
|
551
|
+
} catch (error) {
|
|
552
|
+
buildFailed = true;
|
|
553
|
+
throw error;
|
|
554
|
+
} finally {
|
|
555
|
+
let closeFailed = false;
|
|
556
|
+
let firstCloseError;
|
|
557
|
+
for (const environment of [...initializedEnvironments].reverse()) try {
|
|
558
|
+
await environment.close();
|
|
559
|
+
} catch (error) {
|
|
560
|
+
if (!closeFailed) {
|
|
561
|
+
closeFailed = true;
|
|
562
|
+
firstCloseError = error;
|
|
563
|
+
}
|
|
564
|
+
const closeError = error instanceof Error ? error : new Error(String(error));
|
|
565
|
+
logger.error(`[nasti] failed to close environment "${environment.name}"`, { error: closeError });
|
|
566
|
+
}
|
|
567
|
+
if (closeFailed && !buildFailed) throw firstCloseError;
|
|
568
|
+
}
|
|
569
|
+
const elapsed = ((performance.now() - startTime) / 1e3).toFixed(2);
|
|
570
|
+
const allOutput = [...Object.values(environments).flat(), ...buildAppContext.output];
|
|
571
|
+
const totalSize = allOutput.reduce((sum, chunk) => {
|
|
572
|
+
const content = chunk.type === "chunk" ? chunk.code : chunk.source;
|
|
573
|
+
if (content == null) return sum;
|
|
574
|
+
return sum + (typeof content === "string" ? Buffer.byteLength(content) : content.byteLength);
|
|
575
|
+
}, 0);
|
|
576
|
+
const fileCount = allOutput.length;
|
|
577
|
+
const envSuffix = buildableNames.length > 1 ? ` (${buildableNames.join(" + ")})` : "";
|
|
578
|
+
logger.info(pc.green(`✓ built in ${elapsed}s`) + pc.dim(envSuffix));
|
|
579
|
+
logger.info(pc.dim(` ${fileCount} files, ${displaySize(totalSize)} total → ${config.build.outDir}/`));
|
|
580
|
+
return {
|
|
581
|
+
output: clientOutput,
|
|
582
|
+
environments,
|
|
583
|
+
environmentResults,
|
|
584
|
+
appOutput: [...buildAppContext.output]
|
|
585
|
+
};
|
|
586
|
+
}
|
|
587
|
+
/** client 环境构建:HTML 入口 + CSS 抽取 + 体积表 + index.html 改写 */
|
|
588
|
+
async function buildClientEnvironment(config) {
|
|
589
|
+
const logger = config.logger;
|
|
590
|
+
const outDir = path.resolve(config.root, config.build.outDir);
|
|
591
|
+
const cssEngine = createCssEngine();
|
|
592
|
+
const pluginList = resolvePluginList(config, config.plugins, {
|
|
593
|
+
cssEngine,
|
|
594
|
+
environmentName: "client"
|
|
595
|
+
});
|
|
596
|
+
const clientEnv = new NastiEnvironment("client", config, {
|
|
597
|
+
mode: "build",
|
|
598
|
+
plugins: pluginList,
|
|
599
|
+
pluginApi: getPluginApi(config)
|
|
600
|
+
});
|
|
601
|
+
await clientEnv.init();
|
|
602
|
+
try {
|
|
603
|
+
if (clientEnv.driver) {
|
|
604
|
+
if (!clientEnv.driver.build) throw new Error(`[nasti] environment "client" driver "${clientEnv.driver.name}" does not implement build()`);
|
|
605
|
+
const result = await clientEnv.driver.build(clientEnv.getDriverContext());
|
|
606
|
+
assertDriverBuildResult(clientEnv, result);
|
|
607
|
+
return {
|
|
608
|
+
environment: clientEnv,
|
|
609
|
+
result: finalizeEnvironmentResult(clientEnv, result)
|
|
610
|
+
};
|
|
611
|
+
}
|
|
612
|
+
fs.mkdirSync(outDir, { recursive: true });
|
|
613
|
+
const htmlFile = config.environments.client.html ?? path.resolve(config.root, "index.html");
|
|
614
|
+
const html = await readHtmlFile(config.root, htmlFile);
|
|
615
|
+
const entryPoints = resolveClientEntries(config, html);
|
|
616
|
+
if (entryPoints.length === 0) throw new Error("No entry point found. Add a <script> tag to index.html or create src/main.ts");
|
|
617
|
+
const allPlugins = clientEnv.plugins;
|
|
618
|
+
const nativeReporter = config.logLevel === "silent" ? null : await tryNativeReporterPlugin(config, logger);
|
|
619
|
+
const { inputOptions, outputOptions } = getRolldownOptions(clientEnv, entryPoints, [
|
|
620
|
+
createOxcTransformPlugin(config, clientEnv),
|
|
621
|
+
...toRolldownPlugins(allPlugins, clientEnv),
|
|
622
|
+
...nativeReporter ? [nativeReporter] : []
|
|
623
|
+
]);
|
|
624
|
+
const bundle = await rolldown(inputOptions);
|
|
625
|
+
const { output } = await bundle.write(outputOptions);
|
|
626
|
+
await bundle.close();
|
|
627
|
+
clientEnv.setBuildMetadata({ css: getCssMetadata(cssEngine) });
|
|
628
|
+
if (html) {
|
|
629
|
+
let processedHtml = html;
|
|
630
|
+
const htmlPlugins = [...allPlugins.filter((p) => p.transformIndexHtml), htmlPlugin(config)];
|
|
631
|
+
for (const p of htmlPlugins) {
|
|
632
|
+
const result = await p.transformIndexHtml(processedHtml);
|
|
633
|
+
if (typeof result === "string") processedHtml = result;
|
|
634
|
+
else if (result && "html" in result) processedHtml = processHtml(result.html, result.tags);
|
|
635
|
+
else if (Array.isArray(result)) processedHtml = processHtml(processedHtml, result);
|
|
636
|
+
}
|
|
637
|
+
if (clientEnv.options.build.css.inject !== false) processedHtml = injectCssLinks(processedHtml, cssEngine, config);
|
|
638
|
+
for (const chunk of output) if (chunk.type === "chunk" && chunk.isEntry && chunk.facadeModuleId) processedHtml = replaceEntryScript(processedHtml, chunk.facadeModuleId, chunk.fileName, config, htmlFile, config.base);
|
|
639
|
+
fs.writeFileSync(path.resolve(outDir, "index.html"), processedHtml);
|
|
640
|
+
}
|
|
641
|
+
if (!nativeReporter && config.logLevel !== "silent") reportBuildOutput(output, config, logger);
|
|
642
|
+
warnLargeChunks(output, config, logger);
|
|
643
|
+
return {
|
|
644
|
+
environment: clientEnv,
|
|
645
|
+
result: finalizeEnvironmentResult(clientEnv, { output })
|
|
646
|
+
};
|
|
647
|
+
} catch (error) {
|
|
648
|
+
try {
|
|
649
|
+
await clientEnv.close();
|
|
650
|
+
} catch (closeError) {
|
|
651
|
+
const normalized = closeError instanceof Error ? closeError : new Error(String(closeError));
|
|
652
|
+
logger.error("[nasti] failed to close client environment after build failure", { error: normalized });
|
|
653
|
+
}
|
|
654
|
+
throw error;
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
/** 非 client 环境构建(SSR / worker / main / preload …):entry 显式声明 */
|
|
658
|
+
async function buildServerEnvironment(config, name) {
|
|
659
|
+
const envOptions = config.environments[name];
|
|
660
|
+
const logger = config.logger;
|
|
661
|
+
const cssEngine = envOptions.consumer === "client" ? createCssEngine() : void 0;
|
|
662
|
+
const pluginList = resolvePluginList(config, config.plugins, {
|
|
663
|
+
consumer: envOptions.consumer,
|
|
664
|
+
environmentName: name,
|
|
665
|
+
cssEngine
|
|
666
|
+
});
|
|
667
|
+
const environment = new NastiEnvironment(name, config, {
|
|
668
|
+
mode: "build",
|
|
669
|
+
plugins: pluginList,
|
|
670
|
+
pluginApi: getPluginApi(config)
|
|
671
|
+
});
|
|
672
|
+
await environment.init();
|
|
673
|
+
if (environment.driver) {
|
|
674
|
+
if (!environment.driver.build) {
|
|
675
|
+
await environment.close();
|
|
676
|
+
throw new Error(`[nasti] environment "${name}" driver "${environment.driver.name}" does not implement build()`);
|
|
677
|
+
}
|
|
678
|
+
try {
|
|
679
|
+
const result = await environment.driver.build(environment.getDriverContext());
|
|
680
|
+
assertDriverBuildResult(environment, result);
|
|
681
|
+
return {
|
|
682
|
+
environment,
|
|
683
|
+
result: finalizeEnvironmentResult(environment, result)
|
|
684
|
+
};
|
|
685
|
+
} catch (error) {
|
|
686
|
+
await environment.close();
|
|
687
|
+
throw error;
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
for (const entry of envOptions.entry) if (!fs.existsSync(entry)) {
|
|
691
|
+
await environment.close();
|
|
692
|
+
throw new Error(`[nasti] environment "${name}" entry not found: ${entry}`);
|
|
693
|
+
}
|
|
694
|
+
const rolldownPlugins = [createOxcTransformPlugin(config, environment), ...toRolldownPlugins(environment.plugins, environment)];
|
|
695
|
+
const { inputOptions, outputOptions, outDir } = getRolldownOptions(environment, envOptions.entry, rolldownPlugins);
|
|
696
|
+
fs.mkdirSync(outDir, { recursive: true });
|
|
697
|
+
const bundle = await rolldown(inputOptions);
|
|
698
|
+
const { output } = await bundle.write(outputOptions);
|
|
699
|
+
await bundle.close();
|
|
700
|
+
if (cssEngine) environment.setBuildMetadata({ css: getCssMetadata(cssEngine) });
|
|
701
|
+
logger.info(pc.dim(` [${name}] `) + output.map((o) => path.join(envOptions.build.outDir, o.fileName)).join(pc.dim(", ")));
|
|
702
|
+
return {
|
|
703
|
+
environment,
|
|
704
|
+
result: finalizeEnvironmentResult(environment, { output })
|
|
705
|
+
};
|
|
706
|
+
}
|
|
707
|
+
/** 注入抽取出的 CSS link 标签(entry css 或单文件模式) */
|
|
708
|
+
function injectCssLinks(html, cssEngine, config) {
|
|
709
|
+
const cssLinkTags = [];
|
|
710
|
+
if (cssEngine.singleFileName) cssLinkTags.push({
|
|
711
|
+
tag: "link",
|
|
712
|
+
attrs: {
|
|
713
|
+
rel: "stylesheet",
|
|
714
|
+
href: config.base + cssEngine.singleFileName
|
|
715
|
+
},
|
|
716
|
+
injectTo: "head"
|
|
717
|
+
});
|
|
718
|
+
else for (const files of cssEngine.entryCss.values()) for (const file of files) cssLinkTags.push({
|
|
719
|
+
tag: "link",
|
|
720
|
+
attrs: {
|
|
721
|
+
rel: "stylesheet",
|
|
722
|
+
href: config.base + file
|
|
723
|
+
},
|
|
724
|
+
injectTo: "head"
|
|
725
|
+
});
|
|
726
|
+
return cssLinkTags.length > 0 ? processHtml(html, cssLinkTags) : html;
|
|
727
|
+
}
|
|
728
|
+
function escapeRegExp(string) {
|
|
729
|
+
return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
730
|
+
}
|
|
731
|
+
function replaceEntryScript(html, facadeModuleId, fileName, config, htmlFile, urlPrefix) {
|
|
732
|
+
const rootRelative = path.relative(config.root, facadeModuleId).split(path.sep).join("/");
|
|
733
|
+
const resolvedHtmlFile = path.resolve(config.root, htmlFile);
|
|
734
|
+
const htmlRelative = path.relative(path.dirname(resolvedHtmlFile), facadeModuleId).split(path.sep).join("/");
|
|
735
|
+
const candidates = /* @__PURE__ */ new Set([
|
|
736
|
+
rootRelative,
|
|
737
|
+
`/${rootRelative}`,
|
|
738
|
+
htmlRelative,
|
|
739
|
+
`./${htmlRelative}`
|
|
740
|
+
]);
|
|
741
|
+
let processed = html;
|
|
742
|
+
for (const candidate of candidates) processed = processed.replace(new RegExp(`(src=["'])${escapeRegExp(candidate)}([?#][^"']*)?(["'])`, "g"), `$1${urlPrefix}${fileName}$3`);
|
|
743
|
+
return processed;
|
|
744
|
+
}
|
|
745
|
+
//#endregion
|
|
746
|
+
export { resolveClientEntries as a, replaceEntryScript as i, build_exports as n, toRolldownPlugins as o, getRolldownOptions as r, build as t };
|
|
747
|
+
|
|
748
|
+
//# sourceMappingURL=build-CENae4VM.js.map
|