@nasti-toolchain/nasti 2.3.1 → 2.4.0
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 +64 -1
- package/bin/nasti.js +0 -0
- package/client/hmr.ts +4 -3
- package/dist/cli.cjs +957 -269
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +951 -264
- package/dist/cli.js.map +1 -1
- package/dist/client/hmr.cjs.map +1 -1
- package/dist/client/hmr.d.cts +4 -3
- package/dist/client/hmr.d.ts +4 -3
- package/dist/index.cjs +1054 -366
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +64 -8
- package/dist/index.d.ts +64 -8
- package/dist/index.js +1048 -361
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -10,10 +10,10 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
|
|
|
10
10
|
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
11
11
|
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
12
12
|
});
|
|
13
|
-
var __glob = (map) => (
|
|
14
|
-
var fn = map[
|
|
13
|
+
var __glob = (map) => (path18) => {
|
|
14
|
+
var fn = map[path18];
|
|
15
15
|
if (fn) return fn();
|
|
16
|
-
throw new Error("Module not found in bundle: " +
|
|
16
|
+
throw new Error("Module not found in bundle: " + path18);
|
|
17
17
|
};
|
|
18
18
|
var __esm = (fn, res) => function __init() {
|
|
19
19
|
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
@@ -484,6 +484,7 @@ async function resolveConfig(inlineConfig = {}, command) {
|
|
|
484
484
|
if (envOptions.build) Object.assign(resolved.build, envOptions.build);
|
|
485
485
|
resolved.environments.client = {
|
|
486
486
|
consumer,
|
|
487
|
+
buildEnabled: envOptions.buildEnabled ?? true,
|
|
487
488
|
entry: normalizeEnvironmentEntries(envOptions.entry, root),
|
|
488
489
|
html: path.resolve(
|
|
489
490
|
root,
|
|
@@ -498,6 +499,7 @@ async function resolveConfig(inlineConfig = {}, command) {
|
|
|
498
499
|
}
|
|
499
500
|
resolved.environments[name] = {
|
|
500
501
|
consumer,
|
|
502
|
+
buildEnabled: envOptions.buildEnabled ?? true,
|
|
501
503
|
entry: normalizeEnvironmentEntries(envOptions.entry, root),
|
|
502
504
|
html: envOptions.consumer === "client" && envOptions.html ? path.resolve(root, envOptions.html) : void 0,
|
|
503
505
|
driver: envOptions.driver,
|
|
@@ -787,17 +789,35 @@ var init_plugin_container = __esm({
|
|
|
787
789
|
}
|
|
788
790
|
});
|
|
789
791
|
|
|
792
|
+
// src/core/url.ts
|
|
793
|
+
function removeTimestampQuery(url) {
|
|
794
|
+
const hashIndex = url.indexOf("#");
|
|
795
|
+
const hash = hashIndex >= 0 ? url.slice(hashIndex) : "";
|
|
796
|
+
const withoutHash = hashIndex >= 0 ? url.slice(0, hashIndex) : url;
|
|
797
|
+
const queryIndex = withoutHash.indexOf("?");
|
|
798
|
+
if (queryIndex < 0) return url;
|
|
799
|
+
const pathname = withoutHash.slice(0, queryIndex);
|
|
800
|
+
const query = withoutHash.slice(queryIndex + 1).split("&").filter((part) => !/^t=\d+$/.test(part)).join("&");
|
|
801
|
+
return pathname + (query ? `?${query}` : "") + hash;
|
|
802
|
+
}
|
|
803
|
+
var init_url = __esm({
|
|
804
|
+
"src/core/url.ts"() {
|
|
805
|
+
"use strict";
|
|
806
|
+
}
|
|
807
|
+
});
|
|
808
|
+
|
|
790
809
|
// src/core/module-graph.ts
|
|
791
810
|
var ModuleGraph;
|
|
792
811
|
var init_module_graph = __esm({
|
|
793
812
|
"src/core/module-graph.ts"() {
|
|
794
813
|
"use strict";
|
|
814
|
+
init_url();
|
|
795
815
|
ModuleGraph = class {
|
|
796
816
|
urlToModuleMap = /* @__PURE__ */ new Map();
|
|
797
817
|
idToModuleMap = /* @__PURE__ */ new Map();
|
|
798
818
|
fileToModulesMap = /* @__PURE__ */ new Map();
|
|
799
819
|
getModuleByUrl(url) {
|
|
800
|
-
return this.urlToModuleMap.get(url);
|
|
820
|
+
return this.urlToModuleMap.get(removeTimestampQuery(url));
|
|
801
821
|
}
|
|
802
822
|
getModuleById(id) {
|
|
803
823
|
return this.idToModuleMap.get(id);
|
|
@@ -806,10 +826,11 @@ var init_module_graph = __esm({
|
|
|
806
826
|
return this.fileToModulesMap.get(file);
|
|
807
827
|
}
|
|
808
828
|
async ensureEntryFromUrl(url) {
|
|
809
|
-
|
|
829
|
+
const normalizedUrl = removeTimestampQuery(url);
|
|
830
|
+
let mod = this.urlToModuleMap.get(normalizedUrl);
|
|
810
831
|
if (mod) return mod;
|
|
811
|
-
mod = this.createModule(
|
|
812
|
-
this.urlToModuleMap.set(
|
|
832
|
+
mod = this.createModule(normalizedUrl);
|
|
833
|
+
this.urlToModuleMap.set(normalizedUrl, mod);
|
|
813
834
|
return mod;
|
|
814
835
|
}
|
|
815
836
|
createModule(url, id) {
|
|
@@ -823,6 +844,7 @@ var init_module_graph = __esm({
|
|
|
823
844
|
acceptedHmrDeps: /* @__PURE__ */ new Set(),
|
|
824
845
|
transformResult: null,
|
|
825
846
|
lastHMRTimestamp: 0,
|
|
847
|
+
invalidationVersion: 0,
|
|
826
848
|
isSelfAccepting: false
|
|
827
849
|
};
|
|
828
850
|
this.idToModuleMap.set(mod.id, mod);
|
|
@@ -865,10 +887,64 @@ var init_module_graph = __esm({
|
|
|
865
887
|
}
|
|
866
888
|
}
|
|
867
889
|
}
|
|
890
|
+
/**
|
|
891
|
+
* 用一次转换得到的信息原子更新 import 与 HMR accept 关系。
|
|
892
|
+
* 依赖节点会在真正被浏览器请求前预先创建,这样入口模块先转换时也能建立完整图。
|
|
893
|
+
*/
|
|
894
|
+
async updateModuleInfo(mod, importedUrls, acceptedUrls, isSelfAccepting, expectedInvalidationVersion) {
|
|
895
|
+
const importedModules = await Promise.all(
|
|
896
|
+
[...importedUrls].map((url) => this.ensureEntryFromUrl(url))
|
|
897
|
+
);
|
|
898
|
+
const acceptedModules = await Promise.all(
|
|
899
|
+
[...acceptedUrls].map((url) => this.ensureEntryFromUrl(url))
|
|
900
|
+
);
|
|
901
|
+
if (expectedInvalidationVersion !== void 0 && mod.invalidationVersion !== expectedInvalidationVersion) {
|
|
902
|
+
return null;
|
|
903
|
+
}
|
|
904
|
+
const previousImports = new Set(mod.importedModules);
|
|
905
|
+
for (const imported of previousImports) {
|
|
906
|
+
imported.importers.delete(mod);
|
|
907
|
+
}
|
|
908
|
+
mod.importedModules.clear();
|
|
909
|
+
mod.acceptedHmrDeps.clear();
|
|
910
|
+
for (const imported of importedModules) {
|
|
911
|
+
mod.importedModules.add(imported);
|
|
912
|
+
imported.importers.add(mod);
|
|
913
|
+
}
|
|
914
|
+
for (const accepted of acceptedModules) {
|
|
915
|
+
mod.acceptedHmrDeps.add(accepted);
|
|
916
|
+
}
|
|
917
|
+
mod.isSelfAccepting = isSelfAccepting;
|
|
918
|
+
const pruned = /* @__PURE__ */ new Set();
|
|
919
|
+
for (const imported of previousImports) {
|
|
920
|
+
if (!mod.importedModules.has(imported) && imported.importers.size === 0) {
|
|
921
|
+
pruned.add(imported);
|
|
922
|
+
}
|
|
923
|
+
}
|
|
924
|
+
return pruned;
|
|
925
|
+
}
|
|
868
926
|
/** 使模块的转换缓存失效 */
|
|
869
|
-
invalidateModule(mod) {
|
|
927
|
+
invalidateModule(mod, timestamp = Date.now()) {
|
|
870
928
|
mod.transformResult = null;
|
|
871
|
-
mod.lastHMRTimestamp =
|
|
929
|
+
mod.lastHMRTimestamp = timestamp;
|
|
930
|
+
mod.invalidationVersion++;
|
|
931
|
+
}
|
|
932
|
+
/**
|
|
933
|
+
* 仅失效到 HMR 边界:显式接受依赖的模块本身不会重执行;自接受模块需要失效,
|
|
934
|
+
* 但不再继续影响其 importer。这样既能传播依赖时间戳,也不会隐式重复副作用。
|
|
935
|
+
*/
|
|
936
|
+
invalidateModuleAndImporters(mod, timestamp = Date.now(), seen = /* @__PURE__ */ new Set()) {
|
|
937
|
+
if (seen.has(mod)) return;
|
|
938
|
+
seen.add(mod);
|
|
939
|
+
this.invalidateModule(mod, timestamp);
|
|
940
|
+
for (const importer of mod.importers) {
|
|
941
|
+
if (importer.acceptedHmrDeps.has(mod)) continue;
|
|
942
|
+
if (importer.isSelfAccepting) {
|
|
943
|
+
this.invalidateModule(importer, timestamp);
|
|
944
|
+
continue;
|
|
945
|
+
}
|
|
946
|
+
this.invalidateModuleAndImporters(importer, timestamp, seen);
|
|
947
|
+
}
|
|
872
948
|
}
|
|
873
949
|
/** 使所有模块缓存失效 */
|
|
874
950
|
invalidateAll() {
|
|
@@ -879,34 +955,32 @@ var init_module_graph = __esm({
|
|
|
879
955
|
/** 获取 HMR 传播边界 - 从变更模块向上遍历找到接受更新的边界 */
|
|
880
956
|
getHmrBoundaries(mod) {
|
|
881
957
|
const boundaries = [];
|
|
882
|
-
const
|
|
883
|
-
const
|
|
884
|
-
if (
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
boundaries.push({ boundary
|
|
888
|
-
return true;
|
|
958
|
+
const traversed = /* @__PURE__ */ new Set();
|
|
959
|
+
const addBoundary = (boundary, acceptedVia) => {
|
|
960
|
+
if (!boundaries.some(
|
|
961
|
+
(item) => item.boundary === boundary && item.acceptedVia === acceptedVia
|
|
962
|
+
)) {
|
|
963
|
+
boundaries.push({ boundary, acceptedVia });
|
|
889
964
|
}
|
|
890
|
-
|
|
891
|
-
|
|
965
|
+
};
|
|
966
|
+
const propagate = (node) => {
|
|
967
|
+
if (traversed.has(node)) return true;
|
|
968
|
+
traversed.add(node);
|
|
969
|
+
if (node.isSelfAccepting) {
|
|
970
|
+
addBoundary(node, node);
|
|
892
971
|
return true;
|
|
893
972
|
}
|
|
894
973
|
if (node.importers.size === 0) return false;
|
|
895
974
|
for (const importer of node.importers) {
|
|
896
|
-
if (
|
|
975
|
+
if (importer.acceptedHmrDeps.has(node)) {
|
|
976
|
+
addBoundary(importer, node);
|
|
977
|
+
continue;
|
|
978
|
+
}
|
|
979
|
+
if (!propagate(importer)) return false;
|
|
897
980
|
}
|
|
898
981
|
return true;
|
|
899
982
|
};
|
|
900
|
-
|
|
901
|
-
boundaries.push({ boundary: mod, acceptedVia: mod });
|
|
902
|
-
return boundaries;
|
|
903
|
-
}
|
|
904
|
-
for (const importer of mod.importers) {
|
|
905
|
-
if (!propagate(importer, mod)) {
|
|
906
|
-
return [];
|
|
907
|
-
}
|
|
908
|
-
}
|
|
909
|
-
return boundaries;
|
|
983
|
+
return propagate(mod) ? boundaries : [];
|
|
910
984
|
}
|
|
911
985
|
};
|
|
912
986
|
}
|
|
@@ -1045,6 +1119,7 @@ var init_environment = __esm({
|
|
|
1045
1119
|
moduleGraph;
|
|
1046
1120
|
candidatePlugins;
|
|
1047
1121
|
pluginApi;
|
|
1122
|
+
buildMetadata = {};
|
|
1048
1123
|
initialized = false;
|
|
1049
1124
|
constructor(name, config, init = {}) {
|
|
1050
1125
|
const options = config.environments[name];
|
|
@@ -1101,6 +1176,22 @@ var init_environment = __esm({
|
|
|
1101
1176
|
logger: this.config.logger
|
|
1102
1177
|
};
|
|
1103
1178
|
}
|
|
1179
|
+
setBuildMetadata(metadata) {
|
|
1180
|
+
const { entries: currentEntries, ...currentMetadata } = this.buildMetadata;
|
|
1181
|
+
const { entries, ...nextMetadata } = metadata;
|
|
1182
|
+
this.buildMetadata = {
|
|
1183
|
+
...currentMetadata,
|
|
1184
|
+
...nextMetadata,
|
|
1185
|
+
...currentEntries || entries ? { entries: { ...currentEntries, ...entries } } : {}
|
|
1186
|
+
};
|
|
1187
|
+
}
|
|
1188
|
+
getBuildMetadata() {
|
|
1189
|
+
const { entries, ...metadata } = this.buildMetadata;
|
|
1190
|
+
return {
|
|
1191
|
+
...metadata,
|
|
1192
|
+
...entries ? { entries: { ...entries } } : {}
|
|
1193
|
+
};
|
|
1194
|
+
}
|
|
1104
1195
|
async close() {
|
|
1105
1196
|
try {
|
|
1106
1197
|
await this.driver?.close?.(this.getDriverContext());
|
|
@@ -1354,8 +1445,10 @@ import fs4 from "fs";
|
|
|
1354
1445
|
import { createRequire } from "module";
|
|
1355
1446
|
import { fileURLToPath, pathToFileURL as pathToFileURL2 } from "url";
|
|
1356
1447
|
import pc3 from "picocolors";
|
|
1357
|
-
function getReactRefreshRuntimeEsm() {
|
|
1358
|
-
if (__refreshRuntimeCache)
|
|
1448
|
+
function getReactRefreshRuntimeEsm(includeBoundaryHelpers = false) {
|
|
1449
|
+
if (__refreshRuntimeCache) {
|
|
1450
|
+
return includeBoundaryHelpers ? __refreshRuntimeCache + REACT_REFRESH_BOUNDARY_HELPERS : __refreshRuntimeCache;
|
|
1451
|
+
}
|
|
1359
1452
|
let cjsPath;
|
|
1360
1453
|
try {
|
|
1361
1454
|
const pkgPath = __require2.resolve("react-refresh/package.json");
|
|
@@ -1390,7 +1483,7 @@ export const findAffectedHostInstances = __rt.findAffectedHostInstances;
|
|
|
1390
1483
|
export const collectCustomHooksForSignature = __rt.collectCustomHooksForSignature;
|
|
1391
1484
|
export default __rt;
|
|
1392
1485
|
`;
|
|
1393
|
-
return __refreshRuntimeCache;
|
|
1486
|
+
return includeBoundaryHelpers ? __refreshRuntimeCache + REACT_REFRESH_BOUNDARY_HELPERS : __refreshRuntimeCache;
|
|
1394
1487
|
}
|
|
1395
1488
|
function buildReactRefreshWrapper(moduleUrl, transformedCode) {
|
|
1396
1489
|
const urlLit = JSON.stringify(moduleUrl);
|
|
@@ -1416,22 +1509,40 @@ window.$RefreshReg$ = prevRefreshReg;
|
|
|
1416
1509
|
window.$RefreshSig$ = prevRefreshSig;
|
|
1417
1510
|
|
|
1418
1511
|
if (__nasti_hot__) {
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1512
|
+
let __nasti_current_exports__;
|
|
1513
|
+
__nasti_hot__.accept((nextExports) => {
|
|
1514
|
+
if (!nextExports) return;
|
|
1515
|
+
if (!__nasti_current_exports__) {
|
|
1516
|
+
__nasti_hot__.invalidate('Could not Fast Refresh (previous exports unavailable)');
|
|
1517
|
+
return;
|
|
1518
|
+
}
|
|
1519
|
+
const invalidateMessage = RefreshRuntime.validateRefreshBoundaryAndEnqueueUpdate(
|
|
1520
|
+
${urlLit},
|
|
1521
|
+
__nasti_current_exports__,
|
|
1522
|
+
nextExports,
|
|
1523
|
+
);
|
|
1524
|
+
if (invalidateMessage) __nasti_hot__.invalidate(invalidateMessage);
|
|
1525
|
+
});
|
|
1526
|
+
RefreshRuntime.__hmr_import(import.meta.url).then((currentExports) => {
|
|
1527
|
+
__nasti_current_exports__ = currentExports;
|
|
1528
|
+
RefreshRuntime.registerExportsForReactRefresh(${urlLit}, currentExports);
|
|
1424
1529
|
});
|
|
1425
1530
|
}
|
|
1426
1531
|
`;
|
|
1427
1532
|
}
|
|
1428
1533
|
function injectImportMetaHot(code, moduleUrl) {
|
|
1429
|
-
|
|
1534
|
+
const hotRE = /\bimport\.meta\.hot\b/g;
|
|
1535
|
+
const matches = [...maskStringsAndComments(code).matchAll(hotRE)];
|
|
1536
|
+
if (matches.length === 0) return code;
|
|
1537
|
+
for (const match of matches.reverse()) {
|
|
1538
|
+
const start = match.index;
|
|
1539
|
+
code = code.slice(0, start) + "__nasti_hot__" + code.slice(start + match[0].length);
|
|
1540
|
+
}
|
|
1430
1541
|
const urlLit = JSON.stringify(moduleUrl);
|
|
1431
1542
|
const header = `import { createHotContext as __nasti_createHotContext__ } from "/@nasti/client";
|
|
1432
1543
|
const __nasti_hot__ = __nasti_createHotContext__(${urlLit});
|
|
1433
1544
|
`;
|
|
1434
|
-
return header + code
|
|
1545
|
+
return header + code;
|
|
1435
1546
|
}
|
|
1436
1547
|
function transformMiddleware(ctx) {
|
|
1437
1548
|
ctx.envDefine = buildEnvDefine(
|
|
@@ -1507,13 +1618,14 @@ function transformMiddleware(ctx) {
|
|
|
1507
1618
|
}
|
|
1508
1619
|
async function transformRequest(url, ctx) {
|
|
1509
1620
|
const { config, pluginContainer, moduleGraph } = ctx;
|
|
1621
|
+
url = removeTimestampQuery(url);
|
|
1510
1622
|
const cleanReqUrl = url.split("?")[0];
|
|
1511
1623
|
const cached2 = moduleGraph.getModuleByUrl(url);
|
|
1512
1624
|
if (cached2?.transformResult) {
|
|
1513
1625
|
return cached2.transformResult;
|
|
1514
1626
|
}
|
|
1515
1627
|
if (cleanReqUrl === "/@react-refresh") {
|
|
1516
|
-
return { code: getReactRefreshRuntimeEsm() };
|
|
1628
|
+
return { code: getReactRefreshRuntimeEsm(true) };
|
|
1517
1629
|
}
|
|
1518
1630
|
if (cleanReqUrl.startsWith("/@modules/") && url.includes("?")) {
|
|
1519
1631
|
const idParam = new URLSearchParams(url.slice(url.indexOf("?") + 1)).get("id");
|
|
@@ -1549,6 +1661,8 @@ async function transformRequest(url, ctx) {
|
|
|
1549
1661
|
}
|
|
1550
1662
|
const rawQuery = url.includes("?") ? url.slice(url.indexOf("?") + 1) : "";
|
|
1551
1663
|
if (rawQuery && !/^t=\d+$/.test(rawQuery)) {
|
|
1664
|
+
const mod2 = await moduleGraph.ensureEntryFromUrl(url);
|
|
1665
|
+
const transformVersion2 = mod2.invalidationVersion;
|
|
1552
1666
|
const loaded = await pluginContainer.load(url);
|
|
1553
1667
|
if (loaded != null) {
|
|
1554
1668
|
let code2 = typeof loaded === "string" ? loaded : loaded.code;
|
|
@@ -1556,16 +1670,28 @@ async function transformRequest(url, ctx) {
|
|
|
1556
1670
|
if (transformed != null) {
|
|
1557
1671
|
code2 = typeof transformed === "string" ? transformed : transformed.code;
|
|
1558
1672
|
}
|
|
1559
|
-
const
|
|
1560
|
-
moduleGraph.registerModule(mod2,
|
|
1561
|
-
|
|
1673
|
+
const parentFile = resolveUrlToFile(cleanReqUrl, config.root) ?? cleanReqUrl;
|
|
1674
|
+
moduleGraph.registerModule(mod2, parentFile);
|
|
1675
|
+
const hotInfo2 = rewriteHotAcceptDeps(code2, config, parentFile);
|
|
1676
|
+
code2 = injectImportMetaHot(hotInfo2.code, url);
|
|
1562
1677
|
code2 = replaceEnvInCode(code2, ctx.envDefine ?? buildEnvDefine(
|
|
1563
1678
|
loadEnv(config.mode, config.root, config.envPrefix),
|
|
1564
1679
|
config.mode
|
|
1565
1680
|
));
|
|
1566
|
-
|
|
1681
|
+
const importedUrls2 = /* @__PURE__ */ new Set();
|
|
1682
|
+
code2 = rewriteImports(code2, config, parentFile, importedUrls2, moduleGraph);
|
|
1683
|
+
const pruned2 = await moduleGraph.updateModuleInfo(
|
|
1684
|
+
mod2,
|
|
1685
|
+
importedUrls2,
|
|
1686
|
+
hotInfo2.acceptedUrls,
|
|
1687
|
+
hotInfo2.isSelfAccepting,
|
|
1688
|
+
transformVersion2
|
|
1689
|
+
);
|
|
1567
1690
|
const transformResult2 = { code: code2 };
|
|
1568
|
-
|
|
1691
|
+
if (pruned2) {
|
|
1692
|
+
if (pruned2.size > 0) ctx.onPrune?.([...pruned2].map((item) => item.url));
|
|
1693
|
+
mod2.transformResult = transformResult2;
|
|
1694
|
+
}
|
|
1569
1695
|
return transformResult2;
|
|
1570
1696
|
}
|
|
1571
1697
|
}
|
|
@@ -1573,6 +1699,7 @@ async function transformRequest(url, ctx) {
|
|
|
1573
1699
|
if (!filePath || !fs4.existsSync(filePath)) return null;
|
|
1574
1700
|
const mod = await moduleGraph.ensureEntryFromUrl(url);
|
|
1575
1701
|
moduleGraph.registerModule(mod, filePath);
|
|
1702
|
+
const transformVersion = mod.invalidationVersion;
|
|
1576
1703
|
if (cleanReqUrl.startsWith("/@modules/")) {
|
|
1577
1704
|
const code2 = await bundlePackageAsEsm(filePath, config.root);
|
|
1578
1705
|
const transformResult2 = { code: code2 };
|
|
@@ -1599,9 +1726,10 @@ async function transformRequest(url, ctx) {
|
|
|
1599
1726
|
if (useRefresh) {
|
|
1600
1727
|
code = buildReactRefreshWrapper(stableUrl, code);
|
|
1601
1728
|
wrappedWithRefresh = true;
|
|
1602
|
-
mod.isSelfAccepting = true;
|
|
1603
1729
|
}
|
|
1604
1730
|
}
|
|
1731
|
+
const hotInfo = rewriteHotAcceptDeps(code, config, filePath);
|
|
1732
|
+
code = hotInfo.code;
|
|
1605
1733
|
if (!wrappedWithRefresh) {
|
|
1606
1734
|
code = injectImportMetaHot(code, stableUrl);
|
|
1607
1735
|
}
|
|
@@ -1610,9 +1738,20 @@ async function transformRequest(url, ctx) {
|
|
|
1610
1738
|
config.mode
|
|
1611
1739
|
);
|
|
1612
1740
|
code = replaceEnvInCode(code, envDefine);
|
|
1613
|
-
|
|
1741
|
+
const importedUrls = /* @__PURE__ */ new Set();
|
|
1742
|
+
code = rewriteImports(code, config, filePath, importedUrls, moduleGraph);
|
|
1743
|
+
const pruned = await moduleGraph.updateModuleInfo(
|
|
1744
|
+
mod,
|
|
1745
|
+
importedUrls,
|
|
1746
|
+
hotInfo.acceptedUrls,
|
|
1747
|
+
wrappedWithRefresh || hotInfo.isSelfAccepting,
|
|
1748
|
+
transformVersion
|
|
1749
|
+
);
|
|
1614
1750
|
const transformResult = { code };
|
|
1615
|
-
|
|
1751
|
+
if (pruned) {
|
|
1752
|
+
if (pruned.size > 0) ctx.onPrune?.([...pruned].map((item) => item.url));
|
|
1753
|
+
mod.transformResult = transformResult;
|
|
1754
|
+
}
|
|
1616
1755
|
return transformResult;
|
|
1617
1756
|
}
|
|
1618
1757
|
async function loadVirtualModule(spec, ctx) {
|
|
@@ -1817,49 +1956,202 @@ async function injectCjsNamedExports(code, entryFile) {
|
|
|
1817
1956
|
return code;
|
|
1818
1957
|
}
|
|
1819
1958
|
}
|
|
1820
|
-
function rewriteImports(code, config, filePath) {
|
|
1959
|
+
function rewriteImports(code, config, filePath, importedUrls, moduleGraph) {
|
|
1960
|
+
const resolveSpec = createModuleSpecifierResolver(config, filePath);
|
|
1961
|
+
const transformSpec = (spec) => {
|
|
1962
|
+
const resolved = removeTimestampQuery(resolveSpec(spec));
|
|
1963
|
+
importedUrls?.add(resolved);
|
|
1964
|
+
const timestamp = moduleGraph?.getModuleByUrl(resolved)?.lastHMRTimestamp ?? 0;
|
|
1965
|
+
return timestamp > 0 ? appendTimestampQuery(resolved, timestamp) : resolved;
|
|
1966
|
+
};
|
|
1967
|
+
return code.replace(
|
|
1968
|
+
/\bfrom\s+(['"])([^'"]+)\1/g,
|
|
1969
|
+
(_m, q, s) => `from ${q}${transformSpec(s)}${q}`
|
|
1970
|
+
).replace(
|
|
1971
|
+
/\bimport\s+(['"])([^'"]+)\1/g,
|
|
1972
|
+
(_m, q, s) => `import ${q}${transformSpec(s)}${q}`
|
|
1973
|
+
).replace(
|
|
1974
|
+
/\bimport\s*\(\s*(['"])([^'"]+)\1\s*\)/g,
|
|
1975
|
+
(_m, q, s) => `import(${q}${transformSpec(s)}${q})`
|
|
1976
|
+
);
|
|
1977
|
+
}
|
|
1978
|
+
function createModuleSpecifierResolver(config, filePath) {
|
|
1821
1979
|
const root = config.root;
|
|
1822
1980
|
const fileDir = path4.dirname(filePath);
|
|
1823
1981
|
const aliasEntries = Object.entries(config.resolve.alias).sort(
|
|
1824
1982
|
([a], [b]) => b.length - a.length
|
|
1825
1983
|
);
|
|
1826
1984
|
const toRootUrl = (abs) => "/" + path4.relative(root, abs).replace(/\\/g, "/");
|
|
1827
|
-
|
|
1828
|
-
const suffixMatch =
|
|
1985
|
+
return (specifier) => {
|
|
1986
|
+
const suffixMatch = specifier.match(/[?#].*$/);
|
|
1829
1987
|
const suffix = suffixMatch ? suffixMatch[0] : "";
|
|
1830
|
-
const baseSpec = suffix ?
|
|
1988
|
+
const baseSpec = suffix ? specifier.slice(0, -suffix.length) : specifier;
|
|
1831
1989
|
for (const [key, value] of aliasEntries) {
|
|
1832
1990
|
if (baseSpec === key || baseSpec.startsWith(key + "/")) {
|
|
1833
1991
|
const aliasBase = resolveAliasTarget(value, root);
|
|
1834
1992
|
const sub = baseSpec.slice(key.length).replace(/^\//, "");
|
|
1835
1993
|
const target = sub ? path4.join(aliasBase, sub) : aliasBase;
|
|
1836
1994
|
const resolved = tryResolveDiskPath(target);
|
|
1837
|
-
return resolved && isUnderRoot(resolved, root) ? toRootUrl(resolved) + suffix :
|
|
1995
|
+
return resolved && isUnderRoot(resolved, root) ? toRootUrl(resolved) + suffix : specifier;
|
|
1838
1996
|
}
|
|
1839
1997
|
}
|
|
1840
1998
|
if (baseSpec.startsWith("./") || baseSpec.startsWith("../")) {
|
|
1841
|
-
const
|
|
1842
|
-
|
|
1843
|
-
return resolved && isUnderRoot(resolved, root) ? toRootUrl(resolved) + suffix : spec;
|
|
1999
|
+
const resolved = tryResolveDiskPath(path4.resolve(fileDir, baseSpec));
|
|
2000
|
+
return resolved && isUnderRoot(resolved, root) ? toRootUrl(resolved) + suffix : specifier;
|
|
1844
2001
|
}
|
|
1845
2002
|
if (baseSpec.startsWith("/") && !baseSpec.startsWith("/@")) {
|
|
1846
|
-
const
|
|
1847
|
-
|
|
1848
|
-
return resolved && isUnderRoot(resolved, root) ? toRootUrl(resolved) + suffix : spec;
|
|
2003
|
+
const resolved = tryResolveDiskPath(path4.join(root, baseSpec.replace(/^\//, "")));
|
|
2004
|
+
return resolved && isUnderRoot(resolved, root) ? toRootUrl(resolved) + suffix : specifier;
|
|
1849
2005
|
}
|
|
1850
|
-
if (baseSpec.startsWith("/")) return
|
|
1851
|
-
return `/@modules/${
|
|
2006
|
+
if (baseSpec.startsWith("/")) return specifier;
|
|
2007
|
+
return `/@modules/${specifier}`;
|
|
1852
2008
|
};
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
)
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
)
|
|
2009
|
+
}
|
|
2010
|
+
function rewriteHotAcceptDeps(code, config, filePath) {
|
|
2011
|
+
const acceptedUrls = /* @__PURE__ */ new Set();
|
|
2012
|
+
const edits = [];
|
|
2013
|
+
const resolveSpec = createModuleSpecifierResolver(config, filePath);
|
|
2014
|
+
const acceptRE = /(?:\bimport\.meta\.hot|\b__nasti_hot__)(?:(?:\?\.)|\.)accept\s*\(/g;
|
|
2015
|
+
const searchableCode = maskStringsAndComments(code);
|
|
2016
|
+
let isSelfAccepting = false;
|
|
2017
|
+
let match;
|
|
2018
|
+
while (match = acceptRE.exec(searchableCode)) {
|
|
2019
|
+
let cursor = match.index + match[0].length;
|
|
2020
|
+
const skipTrivia = () => {
|
|
2021
|
+
while (cursor < code.length) {
|
|
2022
|
+
if (/\s/.test(code[cursor])) {
|
|
2023
|
+
cursor++;
|
|
2024
|
+
continue;
|
|
2025
|
+
}
|
|
2026
|
+
if (code[cursor] === "/" && code[cursor + 1] === "/") {
|
|
2027
|
+
cursor += 2;
|
|
2028
|
+
while (cursor < code.length && code[cursor] !== "\n") cursor++;
|
|
2029
|
+
continue;
|
|
2030
|
+
}
|
|
2031
|
+
if (code[cursor] === "/" && code[cursor + 1] === "*") {
|
|
2032
|
+
cursor += 2;
|
|
2033
|
+
while (cursor < code.length && !(code[cursor] === "*" && code[cursor + 1] === "/")) cursor++;
|
|
2034
|
+
cursor += 2;
|
|
2035
|
+
continue;
|
|
2036
|
+
}
|
|
2037
|
+
break;
|
|
2038
|
+
}
|
|
2039
|
+
};
|
|
2040
|
+
skipTrivia();
|
|
2041
|
+
const first = code[cursor];
|
|
2042
|
+
if (!first || first === ")" || first !== "[" && first !== "'" && first !== '"' && first !== "`") {
|
|
2043
|
+
isSelfAccepting = true;
|
|
2044
|
+
continue;
|
|
2045
|
+
}
|
|
2046
|
+
const readLiteral = () => {
|
|
2047
|
+
const quote = code[cursor];
|
|
2048
|
+
if (quote !== "'" && quote !== '"' && quote !== "`") return;
|
|
2049
|
+
const start = cursor;
|
|
2050
|
+
cursor++;
|
|
2051
|
+
let raw = "";
|
|
2052
|
+
while (cursor < code.length) {
|
|
2053
|
+
const char = code[cursor];
|
|
2054
|
+
if (char === "\\") {
|
|
2055
|
+
raw += code[cursor + 1] ?? "";
|
|
2056
|
+
cursor += 2;
|
|
2057
|
+
continue;
|
|
2058
|
+
}
|
|
2059
|
+
if (char === quote) {
|
|
2060
|
+
cursor++;
|
|
2061
|
+
const resolved = removeTimestampQuery(resolveSpec(raw));
|
|
2062
|
+
acceptedUrls.add(resolved);
|
|
2063
|
+
edits.push({ start, end: cursor, value: JSON.stringify(resolved) });
|
|
2064
|
+
return;
|
|
2065
|
+
}
|
|
2066
|
+
if (quote === "`" && char === "$" && code[cursor + 1] === "{") return;
|
|
2067
|
+
raw += char;
|
|
2068
|
+
cursor++;
|
|
2069
|
+
}
|
|
2070
|
+
};
|
|
2071
|
+
if (first === "[") {
|
|
2072
|
+
cursor++;
|
|
2073
|
+
while (cursor < code.length) {
|
|
2074
|
+
skipTrivia();
|
|
2075
|
+
if (code[cursor] === ",") {
|
|
2076
|
+
cursor++;
|
|
2077
|
+
skipTrivia();
|
|
2078
|
+
}
|
|
2079
|
+
if (code[cursor] === "]") break;
|
|
2080
|
+
const before = cursor;
|
|
2081
|
+
readLiteral();
|
|
2082
|
+
if (cursor === before) break;
|
|
2083
|
+
}
|
|
2084
|
+
} else {
|
|
2085
|
+
readLiteral();
|
|
2086
|
+
}
|
|
2087
|
+
}
|
|
2088
|
+
for (const edit of edits.sort((a, b) => b.start - a.start)) {
|
|
2089
|
+
code = code.slice(0, edit.start) + edit.value + code.slice(edit.end);
|
|
2090
|
+
}
|
|
2091
|
+
return { code, acceptedUrls, isSelfAccepting };
|
|
2092
|
+
}
|
|
2093
|
+
function maskStringsAndComments(code) {
|
|
2094
|
+
const masked = code.split("");
|
|
2095
|
+
let state = "code";
|
|
2096
|
+
const isRegexStart = (index2) => {
|
|
2097
|
+
let previous = index2 - 1;
|
|
2098
|
+
while (previous >= 0 && /\s/.test(code[previous])) previous--;
|
|
2099
|
+
return previous < 0 || "=(:,!&|?{};[]+-*%^~<>".includes(code[previous]);
|
|
2100
|
+
};
|
|
2101
|
+
for (let i = 0; i < code.length; i++) {
|
|
2102
|
+
const char = code[i];
|
|
2103
|
+
const next = code[i + 1];
|
|
2104
|
+
if (state === "code") {
|
|
2105
|
+
if (char === "'") state = "single";
|
|
2106
|
+
else if (char === '"') state = "double";
|
|
2107
|
+
else if (char === "`") state = "template";
|
|
2108
|
+
else if (char === "/" && next === "/") state = "line-comment";
|
|
2109
|
+
else if (char === "/" && next === "*") state = "block-comment";
|
|
2110
|
+
else if (char === "/" && isRegexStart(i)) state = "regex";
|
|
2111
|
+
else continue;
|
|
2112
|
+
masked[i] = " ";
|
|
2113
|
+
continue;
|
|
2114
|
+
}
|
|
2115
|
+
if (state === "line-comment") {
|
|
2116
|
+
if (char === "\n") {
|
|
2117
|
+
state = "code";
|
|
2118
|
+
} else {
|
|
2119
|
+
masked[i] = " ";
|
|
2120
|
+
}
|
|
2121
|
+
continue;
|
|
2122
|
+
}
|
|
2123
|
+
if (state === "block-comment") {
|
|
2124
|
+
masked[i] = char === "\n" ? "\n" : " ";
|
|
2125
|
+
if (char === "*" && next === "/") {
|
|
2126
|
+
masked[i + 1] = " ";
|
|
2127
|
+
i++;
|
|
2128
|
+
state = "code";
|
|
2129
|
+
}
|
|
2130
|
+
continue;
|
|
2131
|
+
}
|
|
2132
|
+
if (state === "regex" || state === "regex-class") {
|
|
2133
|
+
masked[i] = char === "\n" ? "\n" : " ";
|
|
2134
|
+
if (char === "\\") {
|
|
2135
|
+
if (i + 1 < code.length) masked[++i] = " ";
|
|
2136
|
+
} else if (state === "regex" && char === "[") {
|
|
2137
|
+
state = "regex-class";
|
|
2138
|
+
} else if (state === "regex-class" && char === "]") {
|
|
2139
|
+
state = "regex";
|
|
2140
|
+
} else if (state === "regex" && char === "/") {
|
|
2141
|
+
state = "code";
|
|
2142
|
+
}
|
|
2143
|
+
continue;
|
|
2144
|
+
}
|
|
2145
|
+
masked[i] = char === "\n" ? "\n" : " ";
|
|
2146
|
+
if (char === "\\") {
|
|
2147
|
+
if (i + 1 < code.length) masked[++i] = " ";
|
|
2148
|
+
continue;
|
|
2149
|
+
}
|
|
2150
|
+
if (state === "single" && char === "'" || state === "double" && char === '"' || state === "template" && char === "`") {
|
|
2151
|
+
state = "code";
|
|
2152
|
+
}
|
|
2153
|
+
}
|
|
2154
|
+
return masked.join("");
|
|
1863
2155
|
}
|
|
1864
2156
|
function resolveAliasTarget(value, root) {
|
|
1865
2157
|
if (path4.isAbsolute(value) && fs4.existsSync(value)) return value;
|
|
@@ -1884,6 +2176,12 @@ function isUnderRoot(abs, root) {
|
|
|
1884
2176
|
const rel = path4.relative(root, abs);
|
|
1885
2177
|
return !!rel && !rel.startsWith("..") && !path4.isAbsolute(rel);
|
|
1886
2178
|
}
|
|
2179
|
+
function appendTimestampQuery(url, timestamp) {
|
|
2180
|
+
const hashIndex = url.indexOf("#");
|
|
2181
|
+
const hash = hashIndex >= 0 ? url.slice(hashIndex) : "";
|
|
2182
|
+
const withoutHash = hashIndex >= 0 ? url.slice(0, hashIndex) : url;
|
|
2183
|
+
return `${withoutHash}${withoutHash.includes("?") ? "&" : "?"}t=${timestamp}${hash}`;
|
|
2184
|
+
}
|
|
1887
2185
|
function externalSpecToModuleUrl(spec, baseDir, root) {
|
|
1888
2186
|
const resolved = resolveNodeModule(baseDir, spec);
|
|
1889
2187
|
if (!resolved) return `/@modules/${spec}`;
|
|
@@ -2027,30 +2325,29 @@ function isModuleRequest(url) {
|
|
|
2027
2325
|
function getHmrClientCode() {
|
|
2028
2326
|
return `
|
|
2029
2327
|
// Nasti HMR Client
|
|
2030
|
-
const
|
|
2328
|
+
const socketProtocol = location.protocol === 'https:' ? 'wss' : 'ws';
|
|
2329
|
+
const socket = new WebSocket(socketProtocol + '://' + location.host, 'nasti-hmr');
|
|
2031
2330
|
const hotModulesMap = new Map();
|
|
2032
2331
|
const disposeMap = new Map();
|
|
2033
2332
|
const pruneMap = new Map();
|
|
2333
|
+
const dataMap = new Map();
|
|
2334
|
+
let updateQueue = [];
|
|
2335
|
+
let pendingUpdateQueue = false;
|
|
2034
2336
|
|
|
2035
2337
|
socket.addEventListener('message', async ({ data }) => {
|
|
2036
2338
|
const payload = JSON.parse(data);
|
|
2037
2339
|
switch (payload.type) {
|
|
2038
2340
|
case 'connected':
|
|
2039
|
-
console.
|
|
2341
|
+
console.debug('[nasti] connected.');
|
|
2040
2342
|
clearErrorOverlay();
|
|
2041
2343
|
break;
|
|
2042
2344
|
case 'update':
|
|
2043
2345
|
try {
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
} else if (update.type === 'css-update') {
|
|
2048
|
-
return updateCss(update.path);
|
|
2049
|
-
}
|
|
2050
|
-
}));
|
|
2346
|
+
// CSS \u5728 unbundled \u6A21\u5F0F\u4E0B\u4E5F\u662F\u4F1A\u6CE8\u5165 <style> \u7684 JS \u6A21\u5757\uFF0C\u548C\u666E\u901A JS
|
|
2347
|
+
// \u4E00\u6837\u91CD\u65B0 import \u624D\u80FD\u6267\u884C dispose/accept \u5E76\u4FDD\u6301\u9875\u9762\u72B6\u6001\u3002
|
|
2348
|
+
await Promise.all(payload.updates.map(queueUpdate));
|
|
2051
2349
|
clearErrorOverlay();
|
|
2052
|
-
console.
|
|
2053
|
-
location.reload();
|
|
2350
|
+
console.debug('[nasti] HMR update complete.');
|
|
2054
2351
|
} catch (err) {
|
|
2055
2352
|
console.error('[nasti] HMR update failed:', err);
|
|
2056
2353
|
showErrorOverlay(err);
|
|
@@ -2061,10 +2358,17 @@ socket.addEventListener('message', async ({ data }) => {
|
|
|
2061
2358
|
location.reload();
|
|
2062
2359
|
break;
|
|
2063
2360
|
case 'prune':
|
|
2064
|
-
payload.paths.
|
|
2065
|
-
const
|
|
2066
|
-
|
|
2067
|
-
|
|
2361
|
+
await Promise.all(payload.paths.map(async (path) => {
|
|
2362
|
+
const data = dataMap.get(path);
|
|
2363
|
+
const dispose = disposeMap.get(path);
|
|
2364
|
+
const prune = pruneMap.get(path);
|
|
2365
|
+
if (dispose) await dispose(data);
|
|
2366
|
+
if (prune) await prune(data);
|
|
2367
|
+
hotModulesMap.delete(path);
|
|
2368
|
+
disposeMap.delete(path);
|
|
2369
|
+
pruneMap.delete(path);
|
|
2370
|
+
dataMap.delete(path);
|
|
2371
|
+
}));
|
|
2068
2372
|
break;
|
|
2069
2373
|
case 'error':
|
|
2070
2374
|
console.error('[nasti] error:', payload.err.message);
|
|
@@ -2073,33 +2377,64 @@ socket.addEventListener('message', async ({ data }) => {
|
|
|
2073
2377
|
}
|
|
2074
2378
|
});
|
|
2075
2379
|
|
|
2076
|
-
// \
|
|
2380
|
+
// \u670D\u52A1\u91CD\u542F\u540E\u65E7\u6A21\u5757\u56FE\u5DF2\u5931\u6548\uFF0C\u91CD\u8FDE\u65F6\u6574\u9875\u5237\u65B0\u662F\u5FC5\u8981\u515C\u5E95\uFF1B\u6B63\u5E38 update \u4E0D\u518D\u5237\u65B0\u3002
|
|
2077
2381
|
let reconnectTimer = 0;
|
|
2078
2382
|
socket.addEventListener('close', () => {
|
|
2079
2383
|
clearTimeout(reconnectTimer);
|
|
2080
2384
|
reconnectTimer = setTimeout(() => location.reload(), 1000);
|
|
2081
2385
|
});
|
|
2082
2386
|
|
|
2387
|
+
/**
|
|
2388
|
+
* \u540C\u4E00\u6279\u66F4\u65B0\u5148\u5168\u90E8\u62C9\u53D6\uFF0C\u518D\u6309\u670D\u52A1\u7AEF\u6D88\u606F\u987A\u5E8F\u6267\u884C accept \u56DE\u8C03\uFF0C\u907F\u514D HTTP \u5F80\u8FD4\u901F\u5EA6
|
|
2389
|
+
* \u6539\u53D8\u6A21\u5757\u5E94\u7528\u987A\u5E8F\u3002\u8FD9\u4E0E Vite HMRClient \u7684 fetch/apply \u4E24\u9636\u6BB5\u4E00\u81F4\u3002
|
|
2390
|
+
*/
|
|
2391
|
+
async function queueUpdate(update) {
|
|
2392
|
+
updateQueue.push(fetchUpdate(update));
|
|
2393
|
+
if (pendingUpdateQueue) return;
|
|
2394
|
+
|
|
2395
|
+
pendingUpdateQueue = true;
|
|
2396
|
+
await Promise.resolve();
|
|
2397
|
+
pendingUpdateQueue = false;
|
|
2398
|
+
const loading = updateQueue;
|
|
2399
|
+
updateQueue = [];
|
|
2400
|
+
const applyUpdates = await Promise.all(loading);
|
|
2401
|
+
for (const apply of applyUpdates) {
|
|
2402
|
+
if (apply) apply();
|
|
2403
|
+
}
|
|
2404
|
+
}
|
|
2405
|
+
|
|
2083
2406
|
async function fetchUpdate(update) {
|
|
2084
2407
|
const mod = hotModulesMap.get(update.path);
|
|
2085
|
-
// \
|
|
2086
|
-
|
|
2087
|
-
if (dispose) dispose();
|
|
2408
|
+
// \u5C1A\u672A\u5728\u5F53\u524D\u9875\u9762\u52A0\u8F7D\u7684\u52A8\u6001\u6A21\u5757\u4E0D\u9700\u8981\u66F4\u65B0\u3002
|
|
2409
|
+
if (!mod) return;
|
|
2088
2410
|
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2411
|
+
// \u5FC5\u987B\u5728\u91CD\u65B0 import \u524D\u786E\u5B9A\u65E7\u56DE\u8C03\uFF1B\u65B0\u6A21\u5757\u6267\u884C createHotContext \u65F6\u4F1A\u6E05\u7A7A\u5E76\u6CE8\u518C\u65B0\u56DE\u8C03\u3002
|
|
2412
|
+
const qualifiedCallbacks = mod.callbacks.filter(({ deps }) =>
|
|
2413
|
+
deps.includes(update.acceptedPath)
|
|
2414
|
+
);
|
|
2415
|
+
const isSelfUpdate = update.path === update.acceptedPath;
|
|
2416
|
+
if (!isSelfUpdate && qualifiedCallbacks.length === 0) return;
|
|
2417
|
+
|
|
2418
|
+
const dispose = disposeMap.get(update.acceptedPath);
|
|
2419
|
+
if (dispose) await dispose(dataMap.get(update.acceptedPath));
|
|
2420
|
+
const newMod = await import(appendTimestampQuery(update.acceptedPath, update.timestamp));
|
|
2421
|
+
|
|
2422
|
+
return () => {
|
|
2423
|
+
for (const { deps, fn } of qualifiedCallbacks) {
|
|
2424
|
+
fn(deps.map((dep) => dep === update.acceptedPath ? newMod : undefined));
|
|
2425
|
+
}
|
|
2426
|
+
const detail = isSelfUpdate
|
|
2427
|
+
? update.path
|
|
2428
|
+
: update.acceptedPath + ' via ' + update.path;
|
|
2429
|
+
console.debug('[nasti] hot updated:', detail);
|
|
2430
|
+
};
|
|
2094
2431
|
}
|
|
2095
2432
|
|
|
2096
|
-
function
|
|
2097
|
-
const
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
.then(css => { el.textContent = css; });
|
|
2102
|
-
}
|
|
2433
|
+
function appendTimestampQuery(url, timestamp) {
|
|
2434
|
+
const hashIndex = url.indexOf('#');
|
|
2435
|
+
const hash = hashIndex >= 0 ? url.slice(hashIndex) : '';
|
|
2436
|
+
const withoutHash = hashIndex >= 0 ? url.slice(0, hashIndex) : url;
|
|
2437
|
+
return withoutHash + (withoutHash.includes('?') ? '&' : '?') + 't=' + timestamp + hash;
|
|
2103
2438
|
}
|
|
2104
2439
|
|
|
2105
2440
|
function clearErrorOverlay() {
|
|
@@ -2127,23 +2462,30 @@ function showErrorOverlay(err) {
|
|
|
2127
2462
|
document.body.appendChild(overlay);
|
|
2128
2463
|
}
|
|
2129
2464
|
|
|
2130
|
-
/**
|
|
2131
|
-
* \u751F\u6210 import.meta.hot \u7684 hot context\u3002
|
|
2132
|
-
* \u5173\u952E\u7EA6\u675F\uFF1A\u540C\u4E00 ownerPath \u7684 accept \u56DE\u8C03\u5FC5\u987B\u66FF\u6362\uFF08\u4E0D\u662F append\uFF09\u3002
|
|
2133
|
-
* \u6BCF\u6B21\u6A21\u5757\u91CD\u65B0 import \u90FD\u4F1A\u8C03\u7528 createHotContext\uFF0C\u65E7\u56DE\u8C03\u4F1A\u88AB fetchUpdate \u8C03\u7528\u540E\u7ACB\u5373\u88AB\u65B0 import
|
|
2134
|
-
* \u91CC\u7684 accept \u66FF\u6362\u3002\u4E0D\u66FF\u6362\u7684\u8BDD\u6BCF\u7F16\u8F91\u4E00\u6B21\u5C31\u591A\u4E00\u4E2A\u56DE\u8C03\uFF0C\u8D8A\u8DD1\u8D8A\u6162\u3002
|
|
2135
|
-
*/
|
|
2136
2465
|
export function createHotContext(ownerPath) {
|
|
2466
|
+
if (!dataMap.has(ownerPath)) dataMap.set(ownerPath, {});
|
|
2467
|
+
|
|
2468
|
+
// \u6A21\u5757\u91CD\u65B0\u6267\u884C\u65F6\u4E22\u5F03\u65E7 accept \u56DE\u8C03\uFF0C\u4F46\u4FDD\u7559\u540C\u4E00\u4E2A hot.data \u5BF9\u8C61\u3002
|
|
2469
|
+
const existing = hotModulesMap.get(ownerPath);
|
|
2470
|
+
if (existing) existing.callbacks = [];
|
|
2471
|
+
|
|
2472
|
+
const acceptDeps = (deps, callback = () => {}) => {
|
|
2473
|
+
const mod = hotModulesMap.get(ownerPath) || { id: ownerPath, callbacks: [] };
|
|
2474
|
+
mod.callbacks.push({ deps, fn: callback });
|
|
2475
|
+
hotModulesMap.set(ownerPath, mod);
|
|
2476
|
+
};
|
|
2477
|
+
|
|
2137
2478
|
return {
|
|
2138
2479
|
accept(deps, callback) {
|
|
2139
|
-
// \u81EA\u63A5\u53D7: hot.accept() \u6216 hot.accept(callback)
|
|
2140
2480
|
if (typeof deps === 'function' || deps === undefined) {
|
|
2141
|
-
|
|
2142
|
-
|
|
2481
|
+
acceptDeps([ownerPath], ([mod]) => deps?.(mod));
|
|
2482
|
+
} else if (typeof deps === 'string') {
|
|
2483
|
+
acceptDeps([deps], ([mod]) => callback?.(mod));
|
|
2484
|
+
} else if (Array.isArray(deps)) {
|
|
2485
|
+
acceptDeps(deps, callback);
|
|
2486
|
+
} else {
|
|
2487
|
+
throw new Error('invalid hot.accept() usage');
|
|
2143
2488
|
}
|
|
2144
|
-
// \u4F9D\u8D56\u63A5\u53D7: hot.accept(deps, callback)\uFF0C\u591A\u6B21\u8C03\u7528\u8FFD\u52A0
|
|
2145
|
-
const existing = hotModulesMap.get(ownerPath)?.callbacks ?? [];
|
|
2146
|
-
hotModulesMap.set(ownerPath, { callbacks: [...existing, callback] });
|
|
2147
2489
|
},
|
|
2148
2490
|
prune(callback) {
|
|
2149
2491
|
pruneMap.set(ownerPath, callback);
|
|
@@ -2154,21 +2496,85 @@ export function createHotContext(ownerPath) {
|
|
|
2154
2496
|
invalidate() {
|
|
2155
2497
|
location.reload();
|
|
2156
2498
|
},
|
|
2157
|
-
data:
|
|
2499
|
+
data: dataMap.get(ownerPath),
|
|
2158
2500
|
};
|
|
2159
2501
|
}
|
|
2160
2502
|
`;
|
|
2161
2503
|
}
|
|
2162
|
-
var __dirname_esm, __require2, __refreshRuntimeCache, REACT_REFRESH_GLOBAL_PREAMBLE, esmBundleCache, VALID_IDENT, RESOLVE_EXTENSIONS, ESM_CONDITIONS;
|
|
2504
|
+
var __dirname_esm, __require2, __refreshRuntimeCache, REACT_REFRESH_BOUNDARY_HELPERS, REACT_REFRESH_GLOBAL_PREAMBLE, esmBundleCache, VALID_IDENT, RESOLVE_EXTENSIONS, ESM_CONDITIONS;
|
|
2163
2505
|
var init_middleware = __esm({
|
|
2164
2506
|
"src/server/middleware.ts"() {
|
|
2165
2507
|
"use strict";
|
|
2166
2508
|
init_transformer();
|
|
2167
2509
|
init_html();
|
|
2168
2510
|
init_env();
|
|
2511
|
+
init_url();
|
|
2169
2512
|
__dirname_esm = path4.dirname(fileURLToPath(import.meta.url));
|
|
2170
2513
|
__require2 = createRequire(import.meta.url);
|
|
2171
2514
|
__refreshRuntimeCache = null;
|
|
2515
|
+
REACT_REFRESH_BOUNDARY_HELPERS = `
|
|
2516
|
+
function __nastiIsPlainObject(obj) {
|
|
2517
|
+
return Object.prototype.toString.call(obj) === '[object Object]' &&
|
|
2518
|
+
(obj.constructor === Object || obj.constructor === undefined);
|
|
2519
|
+
}
|
|
2520
|
+
function __nastiIsCompoundComponent(type) {
|
|
2521
|
+
if (!__nastiIsPlainObject(type)) return false;
|
|
2522
|
+
for (const key in type) {
|
|
2523
|
+
if (!isLikelyComponentType(type[key])) return false;
|
|
2524
|
+
}
|
|
2525
|
+
return true;
|
|
2526
|
+
}
|
|
2527
|
+
export function registerExportsForReactRefresh(filename, moduleExports) {
|
|
2528
|
+
for (const key in moduleExports) {
|
|
2529
|
+
if (key === '__esModule') continue;
|
|
2530
|
+
const value = moduleExports[key];
|
|
2531
|
+
if (isLikelyComponentType(value)) {
|
|
2532
|
+
register(value, filename + ' export ' + key);
|
|
2533
|
+
} else if (__nastiIsCompoundComponent(value)) {
|
|
2534
|
+
for (const subKey in value) {
|
|
2535
|
+
register(value[subKey], filename + ' export ' + key + '-' + subKey);
|
|
2536
|
+
}
|
|
2537
|
+
}
|
|
2538
|
+
}
|
|
2539
|
+
}
|
|
2540
|
+
let __nastiRefreshTimer;
|
|
2541
|
+
function __nastiEnqueueRefresh() {
|
|
2542
|
+
clearTimeout(__nastiRefreshTimer);
|
|
2543
|
+
__nastiRefreshTimer = setTimeout(() => performReactRefresh(), 16);
|
|
2544
|
+
}
|
|
2545
|
+
function __nastiCheckExports(ignored, exports, predicate) {
|
|
2546
|
+
for (const key in exports) {
|
|
2547
|
+
if (ignored.includes(key)) continue;
|
|
2548
|
+
if (!predicate(key, exports[key])) return key;
|
|
2549
|
+
}
|
|
2550
|
+
return true;
|
|
2551
|
+
}
|
|
2552
|
+
export function validateRefreshBoundaryAndEnqueueUpdate(id, prevExports, nextExports) {
|
|
2553
|
+
const ignored = window.__getReactRefreshIgnoredExports?.({ id }) ?? [];
|
|
2554
|
+
if (__nastiCheckExports(ignored, prevExports, (key) => key in nextExports) !== true) {
|
|
2555
|
+
return 'Could not Fast Refresh (export removed)';
|
|
2556
|
+
}
|
|
2557
|
+
if (__nastiCheckExports(ignored, nextExports, (key) => key in prevExports) !== true) {
|
|
2558
|
+
return 'Could not Fast Refresh (new export)';
|
|
2559
|
+
}
|
|
2560
|
+
let hasExports = false;
|
|
2561
|
+
const compatible = __nastiCheckExports(ignored, nextExports, (key, value) => {
|
|
2562
|
+
hasExports = true;
|
|
2563
|
+
return isLikelyComponentType(value) ||
|
|
2564
|
+
__nastiIsCompoundComponent(value) ||
|
|
2565
|
+
prevExports[key] === value;
|
|
2566
|
+
});
|
|
2567
|
+
if (!hasExports) {
|
|
2568
|
+
return 'Could not Fast Refresh (no exports)';
|
|
2569
|
+
}
|
|
2570
|
+
if (compatible === true) {
|
|
2571
|
+
__nastiEnqueueRefresh();
|
|
2572
|
+
return;
|
|
2573
|
+
}
|
|
2574
|
+
return 'Could not Fast Refresh ("' + compatible + '" export is incompatible)';
|
|
2575
|
+
}
|
|
2576
|
+
export const __hmr_import = (module) => import(module);
|
|
2577
|
+
`;
|
|
2172
2578
|
REACT_REFRESH_GLOBAL_PREAMBLE = `
|
|
2173
2579
|
import RefreshRuntime from "/@react-refresh";
|
|
2174
2580
|
RefreshRuntime.injectIntoGlobalHook(window);
|
|
@@ -2198,8 +2604,10 @@ async function handleFileChange(file, server) {
|
|
|
2198
2604
|
}
|
|
2199
2605
|
const updates = [];
|
|
2200
2606
|
const timestamp = Date.now();
|
|
2607
|
+
const graph = moduleGraph;
|
|
2608
|
+
const invalidatedModules = /* @__PURE__ */ new Set();
|
|
2201
2609
|
for (const mod of mods) {
|
|
2202
|
-
|
|
2610
|
+
graph.invalidateModuleAndImporters(mod, timestamp, invalidatedModules);
|
|
2203
2611
|
const ctx = {
|
|
2204
2612
|
file,
|
|
2205
2613
|
timestamp,
|
|
@@ -2217,19 +2625,25 @@ async function handleFileChange(file, server) {
|
|
|
2217
2625
|
}
|
|
2218
2626
|
}
|
|
2219
2627
|
for (const affected of affectedModules) {
|
|
2220
|
-
|
|
2628
|
+
graph.invalidateModuleAndImporters(affected, timestamp, invalidatedModules);
|
|
2629
|
+
const boundaries = graph.getHmrBoundaries(affected);
|
|
2221
2630
|
if (boundaries.length === 0) {
|
|
2222
2631
|
logger.info(pc4.green("page reload ") + pc4.dim(shortFile), { timestamp: true });
|
|
2223
2632
|
ws.send({ type: "full-reload", path: relativePath });
|
|
2224
2633
|
return;
|
|
2225
2634
|
}
|
|
2226
|
-
for (const { boundary } of boundaries) {
|
|
2227
|
-
|
|
2635
|
+
for (const { boundary, acceptedVia } of boundaries) {
|
|
2636
|
+
const update = {
|
|
2228
2637
|
type: boundary.type === "css" ? "css-update" : "js-update",
|
|
2229
2638
|
path: boundary.url,
|
|
2230
|
-
acceptedPath:
|
|
2639
|
+
acceptedPath: acceptedVia.url,
|
|
2231
2640
|
timestamp
|
|
2232
|
-
}
|
|
2641
|
+
};
|
|
2642
|
+
if (!updates.some(
|
|
2643
|
+
(existing) => existing.type === update.type && existing.path === update.path && existing.acceptedPath === update.acceptedPath
|
|
2644
|
+
)) {
|
|
2645
|
+
updates.push(update);
|
|
2646
|
+
}
|
|
2233
2647
|
}
|
|
2234
2648
|
}
|
|
2235
2649
|
}
|
|
@@ -2299,6 +2713,7 @@ function resolvePlugin(config) {
|
|
|
2299
2713
|
}
|
|
2300
2714
|
if (!source.startsWith("/") && !source.startsWith(".")) {
|
|
2301
2715
|
if (vueRuntimeEntry && source === "vue") return vueRuntimeEntry;
|
|
2716
|
+
if (config.command === "build") return null;
|
|
2302
2717
|
try {
|
|
2303
2718
|
const resolved = require2.resolve(source, {
|
|
2304
2719
|
paths: [importer ? path6.dirname(importer) : config.root]
|
|
@@ -2387,27 +2802,27 @@ var require_process = __commonJS({
|
|
|
2387
2802
|
var require_filesystem = __commonJS({
|
|
2388
2803
|
"node_modules/detect-libc/lib/filesystem.js"(exports, module) {
|
|
2389
2804
|
"use strict";
|
|
2390
|
-
var
|
|
2805
|
+
var fs13 = __require("fs");
|
|
2391
2806
|
var LDD_PATH = "/usr/bin/ldd";
|
|
2392
2807
|
var SELF_PATH = "/proc/self/exe";
|
|
2393
2808
|
var MAX_LENGTH = 2048;
|
|
2394
|
-
var readFileSync = (
|
|
2395
|
-
const fd =
|
|
2809
|
+
var readFileSync = (path18) => {
|
|
2810
|
+
const fd = fs13.openSync(path18, "r");
|
|
2396
2811
|
const buffer = Buffer.alloc(MAX_LENGTH);
|
|
2397
|
-
const bytesRead =
|
|
2398
|
-
|
|
2812
|
+
const bytesRead = fs13.readSync(fd, buffer, 0, MAX_LENGTH, 0);
|
|
2813
|
+
fs13.close(fd, () => {
|
|
2399
2814
|
});
|
|
2400
2815
|
return buffer.subarray(0, bytesRead);
|
|
2401
2816
|
};
|
|
2402
|
-
var readFile = (
|
|
2403
|
-
|
|
2817
|
+
var readFile = (path18) => new Promise((resolve, reject) => {
|
|
2818
|
+
fs13.open(path18, "r", (err, fd) => {
|
|
2404
2819
|
if (err) {
|
|
2405
2820
|
reject(err);
|
|
2406
2821
|
} else {
|
|
2407
2822
|
const buffer = Buffer.alloc(MAX_LENGTH);
|
|
2408
|
-
|
|
2823
|
+
fs13.read(fd, buffer, 0, MAX_LENGTH, 0, (_, bytesRead) => {
|
|
2409
2824
|
resolve(buffer.subarray(0, bytesRead));
|
|
2410
|
-
|
|
2825
|
+
fs13.close(fd, () => {
|
|
2411
2826
|
});
|
|
2412
2827
|
});
|
|
2413
2828
|
}
|
|
@@ -2519,11 +2934,11 @@ var require_detect_libc = __commonJS({
|
|
|
2519
2934
|
}
|
|
2520
2935
|
return null;
|
|
2521
2936
|
};
|
|
2522
|
-
var familyFromInterpreterPath = (
|
|
2523
|
-
if (
|
|
2524
|
-
if (
|
|
2937
|
+
var familyFromInterpreterPath = (path18) => {
|
|
2938
|
+
if (path18) {
|
|
2939
|
+
if (path18.includes("/ld-musl-")) {
|
|
2525
2940
|
return MUSL;
|
|
2526
|
-
} else if (
|
|
2941
|
+
} else if (path18.includes("/ld-linux-")) {
|
|
2527
2942
|
return GLIBC;
|
|
2528
2943
|
}
|
|
2529
2944
|
}
|
|
@@ -2570,8 +2985,8 @@ var require_detect_libc = __commonJS({
|
|
|
2570
2985
|
cachedFamilyInterpreter = null;
|
|
2571
2986
|
try {
|
|
2572
2987
|
const selfContent = await readFile(SELF_PATH);
|
|
2573
|
-
const
|
|
2574
|
-
cachedFamilyInterpreter = familyFromInterpreterPath(
|
|
2988
|
+
const path18 = interpreterPath(selfContent);
|
|
2989
|
+
cachedFamilyInterpreter = familyFromInterpreterPath(path18);
|
|
2575
2990
|
} catch (e) {
|
|
2576
2991
|
}
|
|
2577
2992
|
return cachedFamilyInterpreter;
|
|
@@ -2583,8 +2998,8 @@ var require_detect_libc = __commonJS({
|
|
|
2583
2998
|
cachedFamilyInterpreter = null;
|
|
2584
2999
|
try {
|
|
2585
3000
|
const selfContent = readFileSync(SELF_PATH);
|
|
2586
|
-
const
|
|
2587
|
-
cachedFamilyInterpreter = familyFromInterpreterPath(
|
|
3001
|
+
const path18 = interpreterPath(selfContent);
|
|
3002
|
+
cachedFamilyInterpreter = familyFromInterpreterPath(path18);
|
|
2588
3003
|
} catch (e) {
|
|
2589
3004
|
}
|
|
2590
3005
|
return cachedFamilyInterpreter;
|
|
@@ -3610,8 +4025,8 @@ function vuePlugin(config) {
|
|
|
3610
4025
|
let descriptor = descriptorCache.get(filePath);
|
|
3611
4026
|
if (!descriptor) {
|
|
3612
4027
|
try {
|
|
3613
|
-
const
|
|
3614
|
-
const source =
|
|
4028
|
+
const fs13 = await import("fs");
|
|
4029
|
+
const source = fs13.readFileSync(filePath, "utf-8");
|
|
3615
4030
|
const parsed = sfc.parse(source, { filename: filePath });
|
|
3616
4031
|
if (parsed.errors.length) return null;
|
|
3617
4032
|
descriptor = parsed.descriptor;
|
|
@@ -3749,16 +4164,27 @@ var init_vue = __esm({
|
|
|
3749
4164
|
// src/plugins/builtins.ts
|
|
3750
4165
|
function resolvePluginList(config, userPlugins, opts = {}) {
|
|
3751
4166
|
const isServe = config.command === "serve";
|
|
4167
|
+
let environmentOptions;
|
|
4168
|
+
if (opts.environmentName) {
|
|
4169
|
+
environmentOptions = config.environments[opts.environmentName];
|
|
4170
|
+
if (!environmentOptions) {
|
|
4171
|
+
throw new Error(
|
|
4172
|
+
`[nasti] unknown environment "${opts.environmentName}" \u2014 declare it in config.environments`
|
|
4173
|
+
);
|
|
4174
|
+
}
|
|
4175
|
+
}
|
|
4176
|
+
const pluginConfig = environmentOptions ? { ...config, resolve: environmentOptions.resolve, build: environmentOptions.build } : config;
|
|
4177
|
+
const consumer = opts.consumer ?? environmentOptions?.consumer;
|
|
3752
4178
|
return [
|
|
3753
4179
|
// vuePlugin 排最前(enforce: 'pre' 语义):.vue 先编译成 JS 再走后续管道
|
|
3754
|
-
...config.framework === "vue" ? [vuePlugin(
|
|
3755
|
-
resolvePlugin(
|
|
3756
|
-
cssPlugin(
|
|
3757
|
-
assetsPlugin(
|
|
3758
|
-
...isServe ? [htmlPlugin(
|
|
4180
|
+
...config.framework === "vue" ? [vuePlugin(pluginConfig)] : [],
|
|
4181
|
+
resolvePlugin(pluginConfig),
|
|
4182
|
+
cssPlugin(pluginConfig, opts.cssEngine, consumer),
|
|
4183
|
+
assetsPlugin(pluginConfig),
|
|
4184
|
+
...isServe ? [htmlPlugin(pluginConfig)] : [],
|
|
3759
4185
|
...userPlugins,
|
|
3760
4186
|
// cssPostPlugin 最后(enforce: 'post' 语义):renderChunk 聚合抽取
|
|
3761
|
-
...!isServe && opts.cssEngine ? [cssPostPlugin(
|
|
4187
|
+
...!isServe && opts.cssEngine ? [cssPostPlugin(pluginConfig, opts.cssEngine)] : []
|
|
3762
4188
|
];
|
|
3763
4189
|
}
|
|
3764
4190
|
var init_builtins = __esm({
|
|
@@ -4082,6 +4508,134 @@ var init_reporter = __esm({
|
|
|
4082
4508
|
}
|
|
4083
4509
|
});
|
|
4084
4510
|
|
|
4511
|
+
// src/core/build-app-context.ts
|
|
4512
|
+
import fs9 from "fs";
|
|
4513
|
+
import path12 from "path";
|
|
4514
|
+
function createBuildAppContext(config, results) {
|
|
4515
|
+
const output = [];
|
|
4516
|
+
const emitted = /* @__PURE__ */ new Set();
|
|
4517
|
+
const outDir = path12.resolve(config.root, config.build.outDir);
|
|
4518
|
+
let environmentArtifacts;
|
|
4519
|
+
return {
|
|
4520
|
+
config,
|
|
4521
|
+
results,
|
|
4522
|
+
get output() {
|
|
4523
|
+
return Object.freeze([...output]);
|
|
4524
|
+
},
|
|
4525
|
+
getResult(environmentName) {
|
|
4526
|
+
return results[environmentName];
|
|
4527
|
+
},
|
|
4528
|
+
getArtifact(environmentName, fileName) {
|
|
4529
|
+
const normalized = normalizeEnvironmentFileName(fileName);
|
|
4530
|
+
return results[environmentName]?.output.find(
|
|
4531
|
+
(artifact) => normalizeEnvironmentFileName(artifact.fileName) === normalized
|
|
4532
|
+
);
|
|
4533
|
+
},
|
|
4534
|
+
getEntry(environmentName, entryName) {
|
|
4535
|
+
const result = results[environmentName];
|
|
4536
|
+
const fileName = result?.entries?.[entryName];
|
|
4537
|
+
if (!fileName) return void 0;
|
|
4538
|
+
return result.output.find(
|
|
4539
|
+
(artifact) => normalizeEnvironmentFileName(artifact.fileName) === normalizeEnvironmentFileName(fileName)
|
|
4540
|
+
);
|
|
4541
|
+
},
|
|
4542
|
+
getManifest(environmentName) {
|
|
4543
|
+
return results[environmentName]?.manifest;
|
|
4544
|
+
},
|
|
4545
|
+
emitFile(file) {
|
|
4546
|
+
const fileName = normalizeAppFileName(file.fileName);
|
|
4547
|
+
const collisionKey = artifactCollisionKey(fileName);
|
|
4548
|
+
if (emitted.has(collisionKey)) {
|
|
4549
|
+
throw new Error(`[nasti] app artifact already emitted: ${fileName}`);
|
|
4550
|
+
}
|
|
4551
|
+
environmentArtifacts ??= collectEnvironmentArtifacts(config, results, outDir);
|
|
4552
|
+
if (environmentArtifacts.has(collisionKey)) {
|
|
4553
|
+
throw new Error(`[nasti] app artifact conflicts with environment output: ${fileName}`);
|
|
4554
|
+
}
|
|
4555
|
+
const target = path12.resolve(outDir, ...fileName.split("/"));
|
|
4556
|
+
const relative = path12.relative(outDir, target);
|
|
4557
|
+
if (relative.startsWith("..") || path12.isAbsolute(relative)) {
|
|
4558
|
+
throw new Error(`[nasti] app artifact must stay inside build.outDir: ${file.fileName}`);
|
|
4559
|
+
}
|
|
4560
|
+
assertNoSymlinkComponents(outDir, fileName);
|
|
4561
|
+
fs9.mkdirSync(path12.dirname(target), { recursive: true });
|
|
4562
|
+
fs9.writeFileSync(target, file.source);
|
|
4563
|
+
const artifact = {
|
|
4564
|
+
...file,
|
|
4565
|
+
fileName,
|
|
4566
|
+
type: "asset"
|
|
4567
|
+
};
|
|
4568
|
+
emitted.add(collisionKey);
|
|
4569
|
+
output.push(artifact);
|
|
4570
|
+
return fileName;
|
|
4571
|
+
}
|
|
4572
|
+
};
|
|
4573
|
+
}
|
|
4574
|
+
function normalizeEnvironmentFileName(fileName) {
|
|
4575
|
+
return path12.posix.normalize(fileName.replace(/\\/g, "/").replace(/^\.\//, ""));
|
|
4576
|
+
}
|
|
4577
|
+
function isInvalidEnvironmentFileName(fileName) {
|
|
4578
|
+
return !fileName || fileName === "." || fileName === ".." || fileName.startsWith("../") || path12.posix.isAbsolute(fileName) || /^[A-Za-z]:\//.test(fileName);
|
|
4579
|
+
}
|
|
4580
|
+
function normalizeAppFileName(fileName) {
|
|
4581
|
+
const normalized = normalizeEnvironmentFileName(fileName);
|
|
4582
|
+
if (isInvalidEnvironmentFileName(normalized)) {
|
|
4583
|
+
throw new Error(`[nasti] invalid app artifact fileName: ${fileName}`);
|
|
4584
|
+
}
|
|
4585
|
+
return normalized;
|
|
4586
|
+
}
|
|
4587
|
+
function artifactCollisionKey(fileName) {
|
|
4588
|
+
return normalizeEnvironmentFileName(fileName).toLowerCase();
|
|
4589
|
+
}
|
|
4590
|
+
function collectEnvironmentArtifacts(config, results, appOutDir) {
|
|
4591
|
+
const occupied = /* @__PURE__ */ new Set();
|
|
4592
|
+
for (const [environmentName, result] of Object.entries(results)) {
|
|
4593
|
+
const environment = config.environments[environmentName];
|
|
4594
|
+
if (!environment) continue;
|
|
4595
|
+
const environmentOutDir = path12.resolve(config.root, environment.build.outDir);
|
|
4596
|
+
for (const artifact of result.output) {
|
|
4597
|
+
const artifactPath = path12.resolve(
|
|
4598
|
+
environmentOutDir,
|
|
4599
|
+
...normalizeEnvironmentFileName(artifact.fileName).split("/")
|
|
4600
|
+
);
|
|
4601
|
+
const relative = path12.relative(appOutDir, artifactPath);
|
|
4602
|
+
if (!relative.startsWith("..") && !path12.isAbsolute(relative)) {
|
|
4603
|
+
occupied.add(artifactCollisionKey(relative));
|
|
4604
|
+
}
|
|
4605
|
+
}
|
|
4606
|
+
}
|
|
4607
|
+
return occupied;
|
|
4608
|
+
}
|
|
4609
|
+
function assertNoSymlinkComponents(outDir, fileName) {
|
|
4610
|
+
let current = outDir;
|
|
4611
|
+
for (const segment of fileName.split("/")) {
|
|
4612
|
+
current = path12.join(current, segment);
|
|
4613
|
+
let stats;
|
|
4614
|
+
try {
|
|
4615
|
+
stats = fs9.lstatSync(current);
|
|
4616
|
+
} catch (error) {
|
|
4617
|
+
if (error.code === "ENOENT") continue;
|
|
4618
|
+
throw error;
|
|
4619
|
+
}
|
|
4620
|
+
if (stats.isSymbolicLink()) {
|
|
4621
|
+
throw new Error(`[nasti] app artifact path cannot traverse a symlink: ${fileName}`);
|
|
4622
|
+
}
|
|
4623
|
+
}
|
|
4624
|
+
}
|
|
4625
|
+
function inferEnvironmentEntries(output) {
|
|
4626
|
+
const entries = {};
|
|
4627
|
+
for (const artifact of output) {
|
|
4628
|
+
if (artifact.type !== "chunk" || !artifact.isEntry || !artifact.name) continue;
|
|
4629
|
+
entries[artifact.name] = normalizeEnvironmentFileName(artifact.fileName);
|
|
4630
|
+
}
|
|
4631
|
+
return Object.keys(entries).length > 0 ? entries : void 0;
|
|
4632
|
+
}
|
|
4633
|
+
var init_build_app_context = __esm({
|
|
4634
|
+
"src/core/build-app-context.ts"() {
|
|
4635
|
+
"use strict";
|
|
4636
|
+
}
|
|
4637
|
+
});
|
|
4638
|
+
|
|
4085
4639
|
// src/build/index.ts
|
|
4086
4640
|
var build_exports = {};
|
|
4087
4641
|
__export(build_exports, {
|
|
@@ -4091,8 +4645,8 @@ __export(build_exports, {
|
|
|
4091
4645
|
resolveClientEntries: () => resolveClientEntries,
|
|
4092
4646
|
toRolldownPlugins: () => toRolldownPlugins
|
|
4093
4647
|
});
|
|
4094
|
-
import
|
|
4095
|
-
import
|
|
4648
|
+
import path13 from "path";
|
|
4649
|
+
import fs10 from "fs";
|
|
4096
4650
|
import { builtinModules as builtinModules2 } from "module";
|
|
4097
4651
|
import { rolldown } from "rolldown";
|
|
4098
4652
|
import pc6 from "picocolors";
|
|
@@ -4100,9 +4654,14 @@ function getRolldownOptions(environment, entryPoints, rolldownPlugins) {
|
|
|
4100
4654
|
const config = environment.config;
|
|
4101
4655
|
const envOptions = environment.options;
|
|
4102
4656
|
const isServer = environment.consumer === "server";
|
|
4103
|
-
const outDir =
|
|
4657
|
+
const outDir = path13.resolve(config.root, envOptions.build.outDir);
|
|
4104
4658
|
const assetsDir = envOptions.build.assetsDir;
|
|
4105
|
-
const {
|
|
4659
|
+
const {
|
|
4660
|
+
output: userOutput,
|
|
4661
|
+
transform: userTransform,
|
|
4662
|
+
resolve: userResolve,
|
|
4663
|
+
...restInputOptions
|
|
4664
|
+
} = envOptions.build.rolldownOptions;
|
|
4106
4665
|
const vueDefine = config.framework === "vue" ? {
|
|
4107
4666
|
__VUE_OPTIONS_API__: "true",
|
|
4108
4667
|
__VUE_PROD_DEVTOOLS__: "false",
|
|
@@ -4116,19 +4675,22 @@ function getRolldownOptions(environment, entryPoints, rolldownPlugins) {
|
|
|
4116
4675
|
input: entryPoints,
|
|
4117
4676
|
transform: { ...userTransform, define: mergedDefine },
|
|
4118
4677
|
plugins: rolldownPlugins,
|
|
4678
|
+
// client/server consumer 都必须使用当前环境的 conditions/mainFields;Lynx
|
|
4679
|
+
// BG/MT 通常同为 client consumer,但仍可能声明不同的运行时条件。
|
|
4680
|
+
resolve: {
|
|
4681
|
+
...userResolve ?? {},
|
|
4682
|
+
// Environment API 是条件解析的唯一高层入口,优先于继承来的底层选项。
|
|
4683
|
+
conditionNames: envOptions.resolve.conditions,
|
|
4684
|
+
mainFields: envOptions.resolve.mainFields
|
|
4685
|
+
},
|
|
4119
4686
|
...isServer ? {
|
|
4120
4687
|
platform: restInputOptions.platform ?? "node",
|
|
4121
|
-
resolve: {
|
|
4122
|
-
conditionNames: envOptions.resolve.conditions,
|
|
4123
|
-
mainFields: envOptions.resolve.mainFields,
|
|
4124
|
-
...restInputOptions.resolve
|
|
4125
|
-
},
|
|
4126
4688
|
// server 产物:node 内建恒外部化;bare specifier 默认外部化
|
|
4127
4689
|
//(同 Vite ssr.external 默认 —— 依赖由 node_modules 运行时解析),
|
|
4128
4690
|
// 相对/绝对/虚拟模块照常打包。需要内联依赖时经 rolldownOptions.external 覆盖。
|
|
4129
4691
|
external: restInputOptions.external ?? ((id) => {
|
|
4130
4692
|
if (NODE_BUILTINS2.has(id)) return true;
|
|
4131
|
-
return !id.startsWith(".") && !
|
|
4693
|
+
return !id.startsWith(".") && !path13.isAbsolute(id) && !id.startsWith("\0");
|
|
4132
4694
|
})
|
|
4133
4695
|
} : {}
|
|
4134
4696
|
};
|
|
@@ -4155,27 +4717,122 @@ function getRolldownOptions(environment, entryPoints, rolldownPlugins) {
|
|
|
4155
4717
|
};
|
|
4156
4718
|
return { inputOptions, outputOptions, outDir };
|
|
4157
4719
|
}
|
|
4158
|
-
function toRolldownPlugins(plugins) {
|
|
4720
|
+
function toRolldownPlugins(plugins, environment) {
|
|
4721
|
+
const wrap = (hook) => {
|
|
4722
|
+
if (!hook) return hook;
|
|
4723
|
+
return function(...args) {
|
|
4724
|
+
return hook.apply(attachEnvironment(this, environment), args);
|
|
4725
|
+
};
|
|
4726
|
+
};
|
|
4159
4727
|
return plugins.map((p) => ({
|
|
4160
4728
|
name: p.name,
|
|
4161
|
-
resolveId: p.resolveId,
|
|
4162
|
-
load: p.load,
|
|
4163
|
-
transform: p.transform,
|
|
4164
|
-
buildStart: p.buildStart,
|
|
4165
|
-
buildEnd: p.buildEnd,
|
|
4729
|
+
resolveId: wrap(p.resolveId),
|
|
4730
|
+
load: wrap(p.load),
|
|
4731
|
+
transform: wrap(p.transform),
|
|
4732
|
+
buildStart: wrap(p.buildStart),
|
|
4733
|
+
buildEnd: wrap(p.buildEnd),
|
|
4166
4734
|
// closeBundle 在 bundle.close() 时触发 —— PWA manifest/SW 等终态产物依赖
|
|
4167
|
-
closeBundle: p.closeBundle,
|
|
4168
|
-
renderChunk: p.renderChunk,
|
|
4169
|
-
augmentChunkHash: p.augmentChunkHash,
|
|
4170
|
-
generateBundle: p.generateBundle
|
|
4735
|
+
closeBundle: wrap(p.closeBundle),
|
|
4736
|
+
renderChunk: wrap(p.renderChunk),
|
|
4737
|
+
augmentChunkHash: wrap(p.augmentChunkHash),
|
|
4738
|
+
generateBundle: wrap(p.generateBundle)
|
|
4171
4739
|
}));
|
|
4172
4740
|
}
|
|
4741
|
+
function attachEnvironment(context, environment) {
|
|
4742
|
+
if (context?.environment === environment) return context;
|
|
4743
|
+
try {
|
|
4744
|
+
Object.defineProperty(context, "environment", {
|
|
4745
|
+
configurable: true,
|
|
4746
|
+
enumerable: false,
|
|
4747
|
+
writable: false,
|
|
4748
|
+
value: environment
|
|
4749
|
+
});
|
|
4750
|
+
return context;
|
|
4751
|
+
} catch {
|
|
4752
|
+
return new Proxy(context, {
|
|
4753
|
+
get(target, property) {
|
|
4754
|
+
if (property === "environment") return environment;
|
|
4755
|
+
const value = Reflect.get(target, property, target);
|
|
4756
|
+
return typeof value === "function" ? value.bind(target) : value;
|
|
4757
|
+
},
|
|
4758
|
+
set(target, property, value) {
|
|
4759
|
+
return Reflect.set(target, property, value, target);
|
|
4760
|
+
}
|
|
4761
|
+
});
|
|
4762
|
+
}
|
|
4763
|
+
}
|
|
4764
|
+
function finalizeEnvironmentResult(environment, result) {
|
|
4765
|
+
const metadata = environment.getBuildMetadata();
|
|
4766
|
+
const inferredEntries = inferEnvironmentEntries(result.output);
|
|
4767
|
+
const entries = {
|
|
4768
|
+
...inferredEntries,
|
|
4769
|
+
...metadata.entries,
|
|
4770
|
+
...result.entries
|
|
4771
|
+
};
|
|
4772
|
+
const normalizedEntries = Object.fromEntries(
|
|
4773
|
+
Object.entries(entries).map(([name, fileName]) => {
|
|
4774
|
+
const normalized = normalizeEnvironmentFileName(fileName);
|
|
4775
|
+
if (isInvalidEnvironmentFileName(normalized)) {
|
|
4776
|
+
throw new Error(
|
|
4777
|
+
`[nasti] environment "${environment.name}" returned invalid entry "${name}": ${fileName}`
|
|
4778
|
+
);
|
|
4779
|
+
}
|
|
4780
|
+
return [name, normalized];
|
|
4781
|
+
})
|
|
4782
|
+
);
|
|
4783
|
+
return {
|
|
4784
|
+
...metadata,
|
|
4785
|
+
...result,
|
|
4786
|
+
output: result.output,
|
|
4787
|
+
...Object.keys(normalizedEntries).length > 0 ? { entries: normalizedEntries } : {}
|
|
4788
|
+
};
|
|
4789
|
+
}
|
|
4790
|
+
function prepareBuildOutputDirectories(config, buildableNames) {
|
|
4791
|
+
const directories = /* @__PURE__ */ new Set();
|
|
4792
|
+
const protectedPaths = /* @__PURE__ */ new Set();
|
|
4793
|
+
const clientIsBuilt = buildableNames.includes("client");
|
|
4794
|
+
if (!clientIsBuilt && config.build.emptyOutDir) {
|
|
4795
|
+
directories.add(path13.resolve(config.root, config.build.outDir));
|
|
4796
|
+
}
|
|
4797
|
+
for (const name of buildableNames) {
|
|
4798
|
+
const environment = config.environments[name];
|
|
4799
|
+
const outDir = path13.resolve(config.root, environment.build.outDir);
|
|
4800
|
+
if (!environment.build.emptyOutDir) {
|
|
4801
|
+
protectedPaths.add(outDir);
|
|
4802
|
+
continue;
|
|
4803
|
+
}
|
|
4804
|
+
if (!environment.driver) directories.add(outDir);
|
|
4805
|
+
}
|
|
4806
|
+
const containsPath = (parent, child) => {
|
|
4807
|
+
const relative = path13.relative(parent, child);
|
|
4808
|
+
return relative === "" || !relative.startsWith("..") && !path13.isAbsolute(relative);
|
|
4809
|
+
};
|
|
4810
|
+
const roots = [...directories].filter(
|
|
4811
|
+
(directory) => ![...protectedPaths].some((protectedPath) => containsPath(directory, protectedPath))
|
|
4812
|
+
).sort((a, b) => a.length - b.length).filter(
|
|
4813
|
+
(directory, index2, all) => !all.slice(0, index2).some((parent) => containsPath(parent, directory))
|
|
4814
|
+
);
|
|
4815
|
+
for (const directory of roots) {
|
|
4816
|
+
if (fs10.existsSync(directory)) fs10.rmSync(directory, { recursive: true, force: true });
|
|
4817
|
+
}
|
|
4818
|
+
}
|
|
4819
|
+
function assertDriverBuildResult(environment, result) {
|
|
4820
|
+
const output = result != null && typeof result === "object" ? result.output : void 0;
|
|
4821
|
+
const hasValidOutput = Array.isArray(output) && output.every(
|
|
4822
|
+
(artifact) => artifact != null && typeof artifact === "object" && typeof artifact.fileName === "string" && typeof artifact.type === "string"
|
|
4823
|
+
);
|
|
4824
|
+
if (!hasValidOutput) {
|
|
4825
|
+
throw new Error(
|
|
4826
|
+
`[nasti] environment "${environment.name}" driver "${environment.driver?.name}" returned an invalid build result; expected { output: EnvironmentBuildOutput[] }`
|
|
4827
|
+
);
|
|
4828
|
+
}
|
|
4829
|
+
}
|
|
4173
4830
|
function resolveClientEntries(config, html) {
|
|
4174
4831
|
const configuredEntries = config.environments.client?.entry ?? [];
|
|
4175
4832
|
if (configuredEntries.length > 0) return configuredEntries;
|
|
4176
4833
|
const entryPoints = [];
|
|
4177
4834
|
const htmlFile = config.environments.client?.html;
|
|
4178
|
-
const htmlDir = htmlFile ?
|
|
4835
|
+
const htmlDir = htmlFile ? path13.dirname(htmlFile) : config.root;
|
|
4179
4836
|
if (html) {
|
|
4180
4837
|
const scriptMatches = html.matchAll(/<script[^>]+src=["']([^"']+)["'][^>]*>/gi);
|
|
4181
4838
|
for (const match of scriptMatches) {
|
|
@@ -4183,7 +4840,7 @@ function resolveClientEntries(config, html) {
|
|
|
4183
4840
|
if (src && !src.startsWith("http")) {
|
|
4184
4841
|
const cleanSrc = src.split(/[?#]/, 1)[0];
|
|
4185
4842
|
entryPoints.push(
|
|
4186
|
-
cleanSrc.startsWith("/") ?
|
|
4843
|
+
cleanSrc.startsWith("/") ? path13.resolve(config.root, cleanSrc.replace(/^\//, "")) : path13.resolve(htmlDir, cleanSrc)
|
|
4187
4844
|
);
|
|
4188
4845
|
}
|
|
4189
4846
|
}
|
|
@@ -4191,8 +4848,8 @@ function resolveClientEntries(config, html) {
|
|
|
4191
4848
|
if (entryPoints.length === 0) {
|
|
4192
4849
|
const fallbackEntries = ["src/main.ts", "src/main.tsx", "src/main.js", "src/index.ts", "src/index.tsx", "src/index.js"];
|
|
4193
4850
|
for (const entry of fallbackEntries) {
|
|
4194
|
-
const fullPath =
|
|
4195
|
-
if (
|
|
4851
|
+
const fullPath = path13.resolve(config.root, entry);
|
|
4852
|
+
if (fs10.existsSync(fullPath)) {
|
|
4196
4853
|
entryPoints.push(fullPath);
|
|
4197
4854
|
break;
|
|
4198
4855
|
}
|
|
@@ -4220,16 +4877,20 @@ async function build(inlineConfig = {}) {
|
|
|
4220
4877
|
const startTime = performance.now();
|
|
4221
4878
|
logger.info(
|
|
4222
4879
|
pc6.cyan(`
|
|
4223
|
-
nasti v${"2.
|
|
4880
|
+
nasti v${"2.4.0"} `) + pc6.green(`building for ${config.mode}...`)
|
|
4224
4881
|
);
|
|
4225
4882
|
debug5?.(`root: ${config.root}`);
|
|
4226
|
-
const buildableNames = Object.keys(config.environments).filter(
|
|
4227
|
-
|
|
4228
|
-
|
|
4883
|
+
const buildableNames = Object.keys(config.environments).filter((name) => {
|
|
4884
|
+
const environment = config.environments[name];
|
|
4885
|
+
if (!environment.buildEnabled) return false;
|
|
4886
|
+
return name === "client" || environment.entry.length > 0 || !!environment.driver;
|
|
4887
|
+
});
|
|
4229
4888
|
buildableNames.sort((a, b) => a === "client" ? -1 : b === "client" ? 1 : 0);
|
|
4889
|
+
prepareBuildOutputDirectories(config, buildableNames);
|
|
4230
4890
|
const environments = {};
|
|
4231
4891
|
const environmentResults = {};
|
|
4232
4892
|
const initializedEnvironments = [];
|
|
4893
|
+
const buildAppContext = createBuildAppContext(config, environmentResults);
|
|
4233
4894
|
let clientOutput = [];
|
|
4234
4895
|
let buildFailed = false;
|
|
4235
4896
|
try {
|
|
@@ -4245,7 +4906,7 @@ nasti v${"2.3.1"} `) + pc6.green(`building for ${config.mode}...`)
|
|
|
4245
4906
|
}
|
|
4246
4907
|
const pluginApi = getPluginApi(config);
|
|
4247
4908
|
for (const plugin of config.plugins) {
|
|
4248
|
-
await plugin.afterBuildApp?.(environmentResults, pluginApi);
|
|
4909
|
+
await plugin.afterBuildApp?.(environmentResults, pluginApi, buildAppContext);
|
|
4249
4910
|
}
|
|
4250
4911
|
} catch (error) {
|
|
4251
4912
|
buildFailed = true;
|
|
@@ -4272,22 +4933,31 @@ nasti v${"2.3.1"} `) + pc6.green(`building for ${config.mode}...`)
|
|
|
4272
4933
|
}
|
|
4273
4934
|
}
|
|
4274
4935
|
const elapsed = ((performance.now() - startTime) / 1e3).toFixed(2);
|
|
4275
|
-
const
|
|
4936
|
+
const allOutput = [...Object.values(environments).flat(), ...buildAppContext.output];
|
|
4937
|
+
const totalSize = allOutput.reduce((sum, chunk) => {
|
|
4276
4938
|
const content = chunk.type === "chunk" ? chunk.code : chunk.source;
|
|
4277
4939
|
if (content == null) return sum;
|
|
4278
4940
|
return sum + (typeof content === "string" ? Buffer.byteLength(content) : content.byteLength);
|
|
4279
4941
|
}, 0);
|
|
4280
|
-
const fileCount =
|
|
4942
|
+
const fileCount = allOutput.length;
|
|
4281
4943
|
const envSuffix = buildableNames.length > 1 ? ` (${buildableNames.join(" + ")})` : "";
|
|
4282
4944
|
logger.info(pc6.green(`\u2713 built in ${elapsed}s`) + pc6.dim(envSuffix));
|
|
4283
4945
|
logger.info(pc6.dim(` ${fileCount} files, ${displaySize(totalSize)} total \u2192 ${config.build.outDir}/`));
|
|
4284
|
-
return {
|
|
4946
|
+
return {
|
|
4947
|
+
output: clientOutput,
|
|
4948
|
+
environments,
|
|
4949
|
+
environmentResults,
|
|
4950
|
+
appOutput: [...buildAppContext.output]
|
|
4951
|
+
};
|
|
4285
4952
|
}
|
|
4286
4953
|
async function buildClientEnvironment(config) {
|
|
4287
4954
|
const logger = config.logger;
|
|
4288
|
-
const outDir =
|
|
4955
|
+
const outDir = path13.resolve(config.root, config.build.outDir);
|
|
4289
4956
|
const cssEngine = createCssEngine();
|
|
4290
|
-
const pluginList = resolvePluginList(config, config.plugins, {
|
|
4957
|
+
const pluginList = resolvePluginList(config, config.plugins, {
|
|
4958
|
+
cssEngine,
|
|
4959
|
+
environmentName: "client"
|
|
4960
|
+
});
|
|
4291
4961
|
const clientEnv = new NastiEnvironment("client", config, {
|
|
4292
4962
|
mode: "build",
|
|
4293
4963
|
plugins: pluginList,
|
|
@@ -4302,13 +4972,11 @@ async function buildClientEnvironment(config) {
|
|
|
4302
4972
|
);
|
|
4303
4973
|
}
|
|
4304
4974
|
const result = await clientEnv.driver.build(clientEnv.getDriverContext());
|
|
4305
|
-
|
|
4306
|
-
|
|
4307
|
-
if (config.build.emptyOutDir && fs9.existsSync(outDir)) {
|
|
4308
|
-
fs9.rmSync(outDir, { recursive: true, force: true });
|
|
4975
|
+
assertDriverBuildResult(clientEnv, result);
|
|
4976
|
+
return { environment: clientEnv, result: finalizeEnvironmentResult(clientEnv, result) };
|
|
4309
4977
|
}
|
|
4310
|
-
|
|
4311
|
-
const htmlFile = config.environments.client.html ??
|
|
4978
|
+
fs10.mkdirSync(outDir, { recursive: true });
|
|
4979
|
+
const htmlFile = config.environments.client.html ?? path13.resolve(config.root, "index.html");
|
|
4312
4980
|
const html = await readHtmlFile(config.root, htmlFile);
|
|
4313
4981
|
const entryPoints = resolveClientEntries(config, html);
|
|
4314
4982
|
if (entryPoints.length === 0) {
|
|
@@ -4318,7 +4986,7 @@ async function buildClientEnvironment(config) {
|
|
|
4318
4986
|
const nativeReporter = config.logLevel === "silent" ? null : await tryNativeReporterPlugin(config, logger);
|
|
4319
4987
|
const rolldownPlugins = [
|
|
4320
4988
|
createOxcTransformPlugin(config, clientEnv),
|
|
4321
|
-
...toRolldownPlugins(allPlugins),
|
|
4989
|
+
...toRolldownPlugins(allPlugins, clientEnv),
|
|
4322
4990
|
...nativeReporter ? [nativeReporter] : []
|
|
4323
4991
|
];
|
|
4324
4992
|
const { inputOptions, outputOptions } = getRolldownOptions(
|
|
@@ -4355,13 +5023,16 @@ async function buildClientEnvironment(config) {
|
|
|
4355
5023
|
);
|
|
4356
5024
|
}
|
|
4357
5025
|
}
|
|
4358
|
-
|
|
5026
|
+
fs10.writeFileSync(path13.resolve(outDir, "index.html"), processedHtml);
|
|
4359
5027
|
}
|
|
4360
5028
|
if (!nativeReporter && config.logLevel !== "silent") {
|
|
4361
5029
|
reportBuildOutput(output, config, logger);
|
|
4362
5030
|
}
|
|
4363
5031
|
warnLargeChunks(output, config, logger);
|
|
4364
|
-
return {
|
|
5032
|
+
return {
|
|
5033
|
+
environment: clientEnv,
|
|
5034
|
+
result: finalizeEnvironmentResult(clientEnv, { output })
|
|
5035
|
+
};
|
|
4365
5036
|
} catch (error) {
|
|
4366
5037
|
try {
|
|
4367
5038
|
await clientEnv.close();
|
|
@@ -4377,7 +5048,10 @@ async function buildClientEnvironment(config) {
|
|
|
4377
5048
|
async function buildServerEnvironment(config, name) {
|
|
4378
5049
|
const envOptions = config.environments[name];
|
|
4379
5050
|
const logger = config.logger;
|
|
4380
|
-
const pluginList = resolvePluginList(config, config.plugins, {
|
|
5051
|
+
const pluginList = resolvePluginList(config, config.plugins, {
|
|
5052
|
+
consumer: envOptions.consumer,
|
|
5053
|
+
environmentName: name
|
|
5054
|
+
});
|
|
4381
5055
|
const environment = new NastiEnvironment(name, config, {
|
|
4382
5056
|
mode: "build",
|
|
4383
5057
|
plugins: pluginList,
|
|
@@ -4393,38 +5067,39 @@ async function buildServerEnvironment(config, name) {
|
|
|
4393
5067
|
}
|
|
4394
5068
|
try {
|
|
4395
5069
|
const result = await environment.driver.build(environment.getDriverContext());
|
|
4396
|
-
|
|
5070
|
+
assertDriverBuildResult(environment, result);
|
|
5071
|
+
return { environment, result: finalizeEnvironmentResult(environment, result) };
|
|
4397
5072
|
} catch (error) {
|
|
4398
5073
|
await environment.close();
|
|
4399
5074
|
throw error;
|
|
4400
5075
|
}
|
|
4401
5076
|
}
|
|
4402
5077
|
for (const entry of envOptions.entry) {
|
|
4403
|
-
if (!
|
|
5078
|
+
if (!fs10.existsSync(entry)) {
|
|
4404
5079
|
await environment.close();
|
|
4405
5080
|
throw new Error(`[nasti] environment "${name}" entry not found: ${entry}`);
|
|
4406
5081
|
}
|
|
4407
5082
|
}
|
|
4408
5083
|
const rolldownPlugins = [
|
|
4409
5084
|
createOxcTransformPlugin(config, environment),
|
|
4410
|
-
...toRolldownPlugins(environment.plugins)
|
|
5085
|
+
...toRolldownPlugins(environment.plugins, environment)
|
|
4411
5086
|
];
|
|
4412
5087
|
const { inputOptions, outputOptions, outDir } = getRolldownOptions(
|
|
4413
5088
|
environment,
|
|
4414
5089
|
envOptions.entry,
|
|
4415
5090
|
rolldownPlugins
|
|
4416
5091
|
);
|
|
4417
|
-
|
|
4418
|
-
fs9.rmSync(outDir, { recursive: true, force: true });
|
|
4419
|
-
}
|
|
4420
|
-
fs9.mkdirSync(outDir, { recursive: true });
|
|
5092
|
+
fs10.mkdirSync(outDir, { recursive: true });
|
|
4421
5093
|
const bundle2 = await rolldown(inputOptions);
|
|
4422
5094
|
const { output } = await bundle2.write(outputOptions);
|
|
4423
5095
|
await bundle2.close();
|
|
4424
5096
|
logger.info(
|
|
4425
|
-
pc6.dim(` [${name}] `) + output.map((o) =>
|
|
5097
|
+
pc6.dim(` [${name}] `) + output.map((o) => path13.join(envOptions.build.outDir, o.fileName)).join(pc6.dim(", "))
|
|
4426
5098
|
);
|
|
4427
|
-
return {
|
|
5099
|
+
return {
|
|
5100
|
+
environment,
|
|
5101
|
+
result: finalizeEnvironmentResult(environment, { output })
|
|
5102
|
+
};
|
|
4428
5103
|
}
|
|
4429
5104
|
function injectCssLinks(html, cssEngine, config) {
|
|
4430
5105
|
const cssLinkTags = [];
|
|
@@ -4451,9 +5126,9 @@ function escapeRegExp(string) {
|
|
|
4451
5126
|
return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
4452
5127
|
}
|
|
4453
5128
|
function replaceEntryScript(html, facadeModuleId, fileName, config, htmlFile, urlPrefix) {
|
|
4454
|
-
const rootRelative =
|
|
4455
|
-
const resolvedHtmlFile =
|
|
4456
|
-
const htmlRelative =
|
|
5129
|
+
const rootRelative = path13.relative(config.root, facadeModuleId).split(path13.sep).join("/");
|
|
5130
|
+
const resolvedHtmlFile = path13.resolve(config.root, htmlFile);
|
|
5131
|
+
const htmlRelative = path13.relative(path13.dirname(resolvedHtmlFile), facadeModuleId).split(path13.sep).join("/");
|
|
4457
5132
|
const candidates = /* @__PURE__ */ new Set([
|
|
4458
5133
|
rootRelative,
|
|
4459
5134
|
`/${rootRelative}`,
|
|
@@ -4483,6 +5158,7 @@ var init_build = __esm({
|
|
|
4483
5158
|
init_reporter();
|
|
4484
5159
|
init_debug();
|
|
4485
5160
|
init_plugin_api();
|
|
5161
|
+
init_build_app_context();
|
|
4486
5162
|
debug5 = createDebugger("nasti:build");
|
|
4487
5163
|
NODE_BUILTINS2 = /* @__PURE__ */ new Set([...builtinModules2, ...builtinModules2.map((m) => `node:${m}`)]);
|
|
4488
5164
|
}
|
|
@@ -4493,7 +5169,7 @@ var dev_engine_exports = {};
|
|
|
4493
5169
|
__export(dev_engine_exports, {
|
|
4494
5170
|
createBundledDevServer: () => createBundledDevServer
|
|
4495
5171
|
});
|
|
4496
|
-
import
|
|
5172
|
+
import path14 from "path";
|
|
4497
5173
|
import crypto3 from "crypto";
|
|
4498
5174
|
import { WebSocketServer as WsServer2 } from "ws";
|
|
4499
5175
|
import pc7 from "picocolors";
|
|
@@ -4529,7 +5205,7 @@ async function createBundledDevServer(opts) {
|
|
|
4529
5205
|
createReactRefreshRuntimePlugin(entryPoints),
|
|
4530
5206
|
createBundledOxcRefreshPlugin()
|
|
4531
5207
|
] : [],
|
|
4532
|
-
...stripCatchAllLoad(toRolldownPlugins(clientEnv.plugins)),
|
|
5208
|
+
...stripCatchAllLoad(toRolldownPlugins(clientEnv.plugins, clientEnv)),
|
|
4533
5209
|
...useReactRefresh ? [
|
|
4534
5210
|
refreshWrapperFn({
|
|
4535
5211
|
cwd: config.root,
|
|
@@ -4578,7 +5254,7 @@ async function createBundledDevServer(opts) {
|
|
|
4578
5254
|
}
|
|
4579
5255
|
const url = `/${patchPath}`;
|
|
4580
5256
|
logger.info(
|
|
4581
|
-
pc7.green("hmr update ") + pc7.dim(changedFiles.map((f) =>
|
|
5257
|
+
pc7.green("hmr update ") + pc7.dim(changedFiles.map((f) => path14.relative(config.root, f)).join(", ")),
|
|
4582
5258
|
{ timestamp: true }
|
|
4583
5259
|
);
|
|
4584
5260
|
sendTo(clientId, { type: "hmr:update", path: url, url });
|
|
@@ -4714,7 +5390,7 @@ async function createBundledDevServer(opts) {
|
|
|
4714
5390
|
return;
|
|
4715
5391
|
}
|
|
4716
5392
|
res.setHeader("ETag", hit.etag);
|
|
4717
|
-
res.setHeader("Content-Type", MIME_TYPES[
|
|
5393
|
+
res.setHeader("Content-Type", MIME_TYPES[path14.extname(fileName)] ?? "application/octet-stream");
|
|
4718
5394
|
res.setHeader("Cache-Control", "no-cache");
|
|
4719
5395
|
res.end(hit.content);
|
|
4720
5396
|
return;
|
|
@@ -4750,7 +5426,7 @@ function stripCatchAllLoad(plugins) {
|
|
|
4750
5426
|
);
|
|
4751
5427
|
}
|
|
4752
5428
|
function createReactRefreshRuntimePlugin(entryPoints) {
|
|
4753
|
-
const entryIds = new Set(entryPoints.map((p) =>
|
|
5429
|
+
const entryIds = new Set(entryPoints.map((p) => path14.resolve(p)));
|
|
4754
5430
|
return {
|
|
4755
5431
|
name: "nasti:bundled-react-refresh",
|
|
4756
5432
|
resolveId(source) {
|
|
@@ -4768,7 +5444,7 @@ function createReactRefreshRuntimePlugin(entryPoints) {
|
|
|
4768
5444
|
return null;
|
|
4769
5445
|
},
|
|
4770
5446
|
transform(code, id) {
|
|
4771
|
-
if (!entryIds.has(
|
|
5447
|
+
if (!entryIds.has(path14.resolve(id.split("?")[0]))) return null;
|
|
4772
5448
|
return { code: `import ${JSON.stringify(PREAMBLE_SPEC)};
|
|
4773
5449
|
${code}`, map: null };
|
|
4774
5450
|
}
|
|
@@ -4939,7 +5615,7 @@ __export(server_exports, {
|
|
|
4939
5615
|
createServer: () => createServer
|
|
4940
5616
|
});
|
|
4941
5617
|
import http from "http";
|
|
4942
|
-
import
|
|
5618
|
+
import path15 from "path";
|
|
4943
5619
|
import os from "os";
|
|
4944
5620
|
import connect from "connect";
|
|
4945
5621
|
import sirv from "sirv";
|
|
@@ -4949,7 +5625,9 @@ async function createServer(inlineConfig = {}) {
|
|
|
4949
5625
|
const startTime = performance.now();
|
|
4950
5626
|
const config = await resolveConfig(inlineConfig, "serve");
|
|
4951
5627
|
const logger = config.logger;
|
|
4952
|
-
const allPlugins = resolvePluginList(config, config.plugins
|
|
5628
|
+
const allPlugins = resolvePluginList(config, config.plugins, {
|
|
5629
|
+
environmentName: "client"
|
|
5630
|
+
});
|
|
4953
5631
|
const configWithPlugins = { ...config, plugins: allPlugins };
|
|
4954
5632
|
const app = connect();
|
|
4955
5633
|
const httpServer = http.createServer(app);
|
|
@@ -4966,7 +5644,10 @@ async function createServer(inlineConfig = {}) {
|
|
|
4966
5644
|
for (const name of Object.keys(config.environments)) {
|
|
4967
5645
|
if (name === "client") continue;
|
|
4968
5646
|
const consumer = config.environments[name].consumer;
|
|
4969
|
-
const envPlugins = resolvePluginList(config, config.plugins, {
|
|
5647
|
+
const envPlugins = resolvePluginList(config, config.plugins, {
|
|
5648
|
+
consumer,
|
|
5649
|
+
environmentName: name
|
|
5650
|
+
});
|
|
4970
5651
|
environments[name] = new NastiEnvironment(name, config, {
|
|
4971
5652
|
mode: "dev",
|
|
4972
5653
|
plugins: envPlugins,
|
|
@@ -5001,14 +5682,14 @@ async function createServer(inlineConfig = {}) {
|
|
|
5001
5682
|
app.use(bundledServer.middleware);
|
|
5002
5683
|
}
|
|
5003
5684
|
const ignoredSegments = /* @__PURE__ */ new Set(["node_modules", ".git", ".nasti"]);
|
|
5004
|
-
const outDirAbs =
|
|
5685
|
+
const outDirAbs = path15.resolve(config.root, config.build.outDir);
|
|
5005
5686
|
const watcher = watch(config.root, {
|
|
5006
5687
|
ignored: (filePath) => {
|
|
5007
5688
|
if (filePath === config.root) return false;
|
|
5008
|
-
if (filePath === outDirAbs || filePath.startsWith(outDirAbs +
|
|
5009
|
-
const rel =
|
|
5010
|
-
if (!rel || rel.startsWith("..") ||
|
|
5011
|
-
for (const seg of rel.split(
|
|
5689
|
+
if (filePath === outDirAbs || filePath.startsWith(outDirAbs + path15.sep)) return true;
|
|
5690
|
+
const rel = path15.relative(config.root, filePath);
|
|
5691
|
+
if (!rel || rel.startsWith("..") || path15.isAbsolute(rel)) return false;
|
|
5692
|
+
for (const seg of rel.split(path15.sep)) {
|
|
5012
5693
|
if (ignoredSegments.has(seg)) return true;
|
|
5013
5694
|
}
|
|
5014
5695
|
return false;
|
|
@@ -5109,7 +5790,7 @@ async function createServer(inlineConfig = {}) {
|
|
|
5109
5790
|
const readyIn = Math.ceil(performance.now() - startTime);
|
|
5110
5791
|
logger.info(
|
|
5111
5792
|
`
|
|
5112
|
-
${pc8.cyan(pc8.bold("NASTI"))} ${pc8.cyan(`v${"2.
|
|
5793
|
+
${pc8.cyan(pc8.bold("NASTI"))} ${pc8.cyan(`v${"2.4.0"}`)} ${pc8.dim("ready in")} ${pc8.bold(readyIn)} ${pc8.dim("ms")}
|
|
5113
5794
|
`
|
|
5114
5795
|
);
|
|
5115
5796
|
printServerUrls(
|
|
@@ -5137,7 +5818,12 @@ async function createServer(inlineConfig = {}) {
|
|
|
5137
5818
|
},
|
|
5138
5819
|
async transformRequest(url) {
|
|
5139
5820
|
const { transformRequest: transformRequest2 } = await Promise.resolve().then(() => (init_middleware(), middleware_exports));
|
|
5140
|
-
return transformRequest2(url, {
|
|
5821
|
+
return transformRequest2(url, {
|
|
5822
|
+
config: configWithPlugins,
|
|
5823
|
+
pluginContainer,
|
|
5824
|
+
moduleGraph,
|
|
5825
|
+
onPrune: (paths) => ws.send({ type: "prune", paths })
|
|
5826
|
+
});
|
|
5141
5827
|
},
|
|
5142
5828
|
async ssrLoadModule(url) {
|
|
5143
5829
|
const runner = await getSsrRunner();
|
|
@@ -5197,9 +5883,10 @@ async function createServer(inlineConfig = {}) {
|
|
|
5197
5883
|
app.use(transformMiddleware({
|
|
5198
5884
|
config: configWithPlugins,
|
|
5199
5885
|
pluginContainer,
|
|
5200
|
-
moduleGraph
|
|
5886
|
+
moduleGraph,
|
|
5887
|
+
onPrune: (paths) => ws.send({ type: "prune", paths })
|
|
5201
5888
|
}));
|
|
5202
|
-
const publicDir =
|
|
5889
|
+
const publicDir = path15.resolve(config.root, "public");
|
|
5203
5890
|
app.use(sirv(publicDir, { dev: true, etag: true }));
|
|
5204
5891
|
app.use(sirv(config.root, { dev: true, etag: true }));
|
|
5205
5892
|
const postMiddlewares = [];
|
|
@@ -5287,24 +5974,24 @@ __export(electron_exports, {
|
|
|
5287
5974
|
detectInstalledElectron: () => detectInstalledElectron,
|
|
5288
5975
|
normalizePreload: () => normalizePreload
|
|
5289
5976
|
});
|
|
5290
|
-
import
|
|
5291
|
-
import
|
|
5977
|
+
import path16 from "path";
|
|
5978
|
+
import fs11 from "fs";
|
|
5292
5979
|
import { rolldown as rolldown2 } from "rolldown";
|
|
5293
5980
|
import pc9 from "picocolors";
|
|
5294
5981
|
async function buildElectron(inlineConfig = {}) {
|
|
5295
5982
|
const config = await resolveConfig({ ...inlineConfig, target: "electron" }, "build");
|
|
5296
5983
|
const startTime = performance.now();
|
|
5297
5984
|
assertElectronVersion(config);
|
|
5298
|
-
console.log(pc9.cyan("\n\u26A1 nasti build (electron)") + pc9.dim(` v${"2.
|
|
5985
|
+
console.log(pc9.cyan("\n\u26A1 nasti build (electron)") + pc9.dim(` v${"2.4.0"}`));
|
|
5299
5986
|
console.log(pc9.dim(` root: ${config.root}`));
|
|
5300
5987
|
console.log(pc9.dim(` mode: ${config.mode}`));
|
|
5301
5988
|
console.log(pc9.dim(` target: electron (\u2265 ${config.electron.minVersion})`));
|
|
5302
|
-
const outDir =
|
|
5303
|
-
if (config.build.emptyOutDir &&
|
|
5304
|
-
|
|
5989
|
+
const outDir = path16.resolve(config.root, config.build.outDir);
|
|
5990
|
+
if (config.build.emptyOutDir && fs11.existsSync(outDir)) {
|
|
5991
|
+
fs11.rmSync(outDir, { recursive: true, force: true });
|
|
5305
5992
|
}
|
|
5306
|
-
|
|
5307
|
-
const rendererOutDir =
|
|
5993
|
+
fs11.mkdirSync(outDir, { recursive: true });
|
|
5994
|
+
const rendererOutDir = path16.join(outDir, "renderer");
|
|
5308
5995
|
const { build: build2 } = await Promise.resolve().then(() => (init_build(), build_exports));
|
|
5309
5996
|
await build2(createElectronRendererConfig(config, inlineConfig, {
|
|
5310
5997
|
build: {
|
|
@@ -5313,8 +6000,8 @@ async function buildElectron(inlineConfig = {}) {
|
|
|
5313
6000
|
emptyOutDir: false
|
|
5314
6001
|
}
|
|
5315
6002
|
}));
|
|
5316
|
-
const mainEntry =
|
|
5317
|
-
if (!
|
|
6003
|
+
const mainEntry = path16.resolve(config.root, config.electron.main);
|
|
6004
|
+
if (!fs11.existsSync(mainEntry)) {
|
|
5318
6005
|
throw new Error(
|
|
5319
6006
|
`Electron main entry not found: ${config.electron.main}
|
|
5320
6007
|
\u5728 nasti.config.ts \u7684 electron.main \u6307\u5B9A\u4E3B\u8FDB\u7A0B\u5165\u53E3\u6587\u4EF6\u3002`
|
|
@@ -5328,11 +6015,11 @@ async function buildElectron(inlineConfig = {}) {
|
|
|
5328
6015
|
const preloadEntries = normalizePreload(config.electron.preload, config.root);
|
|
5329
6016
|
const preloadFiles = [];
|
|
5330
6017
|
for (const entry of preloadEntries) {
|
|
5331
|
-
if (!
|
|
6018
|
+
if (!fs11.existsSync(entry)) {
|
|
5332
6019
|
console.warn(pc9.yellow(` \u26A0 preload entry not found, skipped: ${entry}`));
|
|
5333
6020
|
continue;
|
|
5334
6021
|
}
|
|
5335
|
-
const base =
|
|
6022
|
+
const base = path16.basename(entry).replace(/\.[^.]+$/, "");
|
|
5336
6023
|
const out = outFileName(outDir, base, config.electron.preloadFormat);
|
|
5337
6024
|
await bundleNode(config, entry, {
|
|
5338
6025
|
outFile: out,
|
|
@@ -5344,10 +6031,10 @@ async function buildElectron(inlineConfig = {}) {
|
|
|
5344
6031
|
const elapsed = ((performance.now() - startTime) / 1e3).toFixed(2);
|
|
5345
6032
|
console.log(pc9.green(`
|
|
5346
6033
|
\u2713 Electron build complete in ${elapsed}s`));
|
|
5347
|
-
console.log(pc9.dim(` renderer: ${
|
|
5348
|
-
console.log(pc9.dim(` main: ${
|
|
6034
|
+
console.log(pc9.dim(` renderer: ${path16.relative(config.root, rendererOutDir)}/`));
|
|
6035
|
+
console.log(pc9.dim(` main: ${path16.relative(config.root, mainFile)}`));
|
|
5349
6036
|
for (const pf of preloadFiles) {
|
|
5350
|
-
console.log(pc9.dim(` preload: ${
|
|
6037
|
+
console.log(pc9.dim(` preload: ${path16.relative(config.root, pf)}`));
|
|
5351
6038
|
}
|
|
5352
6039
|
console.log();
|
|
5353
6040
|
return { rendererOutDir, mainFile, preloadFiles };
|
|
@@ -5385,7 +6072,7 @@ async function bundleNode(config, entry, opts) {
|
|
|
5385
6072
|
},
|
|
5386
6073
|
plugins: [oxcTransformPlugin, electronPlugin(config), resolvePlugin(config)]
|
|
5387
6074
|
});
|
|
5388
|
-
|
|
6075
|
+
fs11.mkdirSync(path16.dirname(opts.outFile), { recursive: true });
|
|
5389
6076
|
await bundle2.write({
|
|
5390
6077
|
sourcemap: !!config.build.sourcemap,
|
|
5391
6078
|
minify: !!config.build.minify,
|
|
@@ -5396,7 +6083,7 @@ async function bundleNode(config, entry, opts) {
|
|
|
5396
6083
|
codeSplitting: false
|
|
5397
6084
|
});
|
|
5398
6085
|
await bundle2.close();
|
|
5399
|
-
console.log(pc9.dim(` \u2713 ${opts.label} \u2192 ${
|
|
6086
|
+
console.log(pc9.dim(` \u2713 ${opts.label} \u2192 ${path16.relative(config.root, opts.outFile)}`));
|
|
5400
6087
|
return opts.outFile;
|
|
5401
6088
|
}
|
|
5402
6089
|
function createElectronRendererConfig(config, inlineConfig = {}, overrides = {}) {
|
|
@@ -5420,11 +6107,11 @@ function createElectronRendererConfig(config, inlineConfig = {}, overrides = {})
|
|
|
5420
6107
|
}
|
|
5421
6108
|
function outFileName(outDir, base, format) {
|
|
5422
6109
|
const ext = format === "cjs" ? ".cjs" : ".mjs";
|
|
5423
|
-
return
|
|
6110
|
+
return path16.join(outDir, base + ext);
|
|
5424
6111
|
}
|
|
5425
6112
|
function normalizePreload(preload, root) {
|
|
5426
6113
|
const list = Array.isArray(preload) ? preload : preload ? [preload] : [];
|
|
5427
|
-
return list.map((p) =>
|
|
6114
|
+
return list.map((p) => path16.resolve(root, p));
|
|
5428
6115
|
}
|
|
5429
6116
|
function assertElectronVersion(config) {
|
|
5430
6117
|
const min = config.electron.minVersion;
|
|
@@ -5439,9 +6126,9 @@ function assertElectronVersion(config) {
|
|
|
5439
6126
|
}
|
|
5440
6127
|
function detectInstalledElectron(root) {
|
|
5441
6128
|
try {
|
|
5442
|
-
const pkgPath =
|
|
5443
|
-
if (!
|
|
5444
|
-
const pkg = JSON.parse(
|
|
6129
|
+
const pkgPath = path16.resolve(root, "node_modules/electron/package.json");
|
|
6130
|
+
if (!fs11.existsSync(pkgPath)) return null;
|
|
6131
|
+
const pkg = JSON.parse(fs11.readFileSync(pkgPath, "utf-8"));
|
|
5445
6132
|
const major = parseInt(String(pkg.version).split(".")[0], 10);
|
|
5446
6133
|
return Number.isFinite(major) ? major : null;
|
|
5447
6134
|
} catch {
|
|
@@ -5465,8 +6152,8 @@ __export(electron_dev_exports, {
|
|
|
5465
6152
|
electronRendererDevPath: () => electronRendererDevPath,
|
|
5466
6153
|
startElectronDev: () => startElectronDev
|
|
5467
6154
|
});
|
|
5468
|
-
import
|
|
5469
|
-
import
|
|
6155
|
+
import path17 from "path";
|
|
6156
|
+
import fs12 from "fs";
|
|
5470
6157
|
import { createRequire as createRequire5 } from "module";
|
|
5471
6158
|
import { spawn } from "child_process";
|
|
5472
6159
|
import chokidar from "chokidar";
|
|
@@ -5476,7 +6163,7 @@ async function startElectronDev(inlineConfig = {}) {
|
|
|
5476
6163
|
const { noSpawn, ...rest } = inlineConfig;
|
|
5477
6164
|
const config = await resolveConfig({ ...rest, target: "electron" }, "serve");
|
|
5478
6165
|
warnElectronVersion(config);
|
|
5479
|
-
console.log(pc10.cyan("\n\u26A1 nasti electron dev") + pc10.dim(` v${"2.
|
|
6166
|
+
console.log(pc10.cyan("\n\u26A1 nasti electron dev") + pc10.dim(` v${"2.4.0"}`));
|
|
5480
6167
|
const { createServer: createServer2 } = await Promise.resolve().then(() => (init_server(), server_exports));
|
|
5481
6168
|
const server = await createServer2({
|
|
5482
6169
|
...rest,
|
|
@@ -5486,11 +6173,11 @@ async function startElectronDev(inlineConfig = {}) {
|
|
|
5486
6173
|
await server.listen();
|
|
5487
6174
|
const devUrl = `http://localhost:${server.config.server.port}` + electronRendererDevPath(config.electron.renderer);
|
|
5488
6175
|
console.log(pc10.dim(` renderer: ${devUrl}`));
|
|
5489
|
-
const stageDir =
|
|
5490
|
-
|
|
5491
|
-
const mainEntry =
|
|
6176
|
+
const stageDir = path17.resolve(config.root, ".nasti");
|
|
6177
|
+
fs12.mkdirSync(stageDir, { recursive: true });
|
|
6178
|
+
const mainEntry = path17.resolve(config.root, config.electron.main);
|
|
5492
6179
|
const preloadEntries = normalizePreload(config.electron.preload, config.root);
|
|
5493
|
-
const builtMainFile =
|
|
6180
|
+
const builtMainFile = path17.join(stageDir, "main" + extFor(config.electron.mainFormat));
|
|
5494
6181
|
const builtPreloadFiles = [];
|
|
5495
6182
|
const compileAll = async () => {
|
|
5496
6183
|
await compileNode(config, mainEntry, {
|
|
@@ -5500,9 +6187,9 @@ async function startElectronDev(inlineConfig = {}) {
|
|
|
5500
6187
|
});
|
|
5501
6188
|
builtPreloadFiles.length = 0;
|
|
5502
6189
|
for (const entry of preloadEntries) {
|
|
5503
|
-
if (!
|
|
5504
|
-
const base =
|
|
5505
|
-
const out =
|
|
6190
|
+
if (!fs12.existsSync(entry)) continue;
|
|
6191
|
+
const base = path17.basename(entry).replace(/\.[^.]+$/, "");
|
|
6192
|
+
const out = path17.join(stageDir, base + extFor(config.electron.preloadFormat));
|
|
5506
6193
|
await compileNode(config, entry, {
|
|
5507
6194
|
outFile: out,
|
|
5508
6195
|
format: config.electron.preloadFormat,
|
|
@@ -5541,7 +6228,7 @@ async function startElectronDev(inlineConfig = {}) {
|
|
|
5541
6228
|
};
|
|
5542
6229
|
spawnElectron();
|
|
5543
6230
|
if (config.electron.autoRestart) {
|
|
5544
|
-
const watchTargets = [mainEntry, ...preloadEntries].filter(
|
|
6231
|
+
const watchTargets = [mainEntry, ...preloadEntries].filter(fs12.existsSync);
|
|
5545
6232
|
const watcher = chokidar.watch(watchTargets, { ignoreInitial: true });
|
|
5546
6233
|
let restarting = null;
|
|
5547
6234
|
let pending = false;
|
|
@@ -5621,7 +6308,7 @@ async function compileNode(config, entry, opts) {
|
|
|
5621
6308
|
platform: "node",
|
|
5622
6309
|
plugins: [oxcTransformPlugin, electronPlugin(config), resolvePlugin(config)]
|
|
5623
6310
|
});
|
|
5624
|
-
|
|
6311
|
+
fs12.mkdirSync(path17.dirname(opts.outFile), { recursive: true });
|
|
5625
6312
|
await bundle2.write({
|
|
5626
6313
|
file: opts.outFile,
|
|
5627
6314
|
format: opts.format === "cjs" ? "cjs" : "esm",
|
|
@@ -5634,18 +6321,18 @@ async function compileNode(config, entry, opts) {
|
|
|
5634
6321
|
await bundle2.close();
|
|
5635
6322
|
}
|
|
5636
6323
|
function electronRendererDevPath(renderer) {
|
|
5637
|
-
const normalized = renderer.split(
|
|
6324
|
+
const normalized = renderer.split(path17.sep).join("/").replace(/^\.?\//, "");
|
|
5638
6325
|
return normalized === "index.html" ? "/" : `/${normalized}`;
|
|
5639
6326
|
}
|
|
5640
6327
|
function resolveElectronBinary(config) {
|
|
5641
|
-
if (config.electron.electronPath &&
|
|
6328
|
+
if (config.electron.electronPath && fs12.existsSync(config.electron.electronPath)) {
|
|
5642
6329
|
return config.electron.electronPath;
|
|
5643
6330
|
}
|
|
5644
6331
|
try {
|
|
5645
|
-
const require2 = createRequire5(
|
|
6332
|
+
const require2 = createRequire5(path17.resolve(config.root, "package.json"));
|
|
5646
6333
|
const pathFile = require2.resolve("electron");
|
|
5647
6334
|
const electronModule = require2(pathFile);
|
|
5648
|
-
if (typeof electronModule === "string" &&
|
|
6335
|
+
if (typeof electronModule === "string" && fs12.existsSync(electronModule)) {
|
|
5649
6336
|
return electronModule;
|
|
5650
6337
|
}
|
|
5651
6338
|
} catch {
|
|
@@ -5820,20 +6507,20 @@ cli.command("preview [root]", "Preview production build").option("--port <port>"
|
|
|
5820
6507
|
const logger = createCliLogger(options);
|
|
5821
6508
|
try {
|
|
5822
6509
|
const http2 = await import("http");
|
|
5823
|
-
const
|
|
6510
|
+
const path18 = await import("path");
|
|
5824
6511
|
const os2 = await import("os");
|
|
5825
6512
|
const sirv2 = (await import("sirv")).default;
|
|
5826
6513
|
const connect2 = (await import("connect")).default;
|
|
5827
6514
|
const { printServerUrls: printServerUrls2 } = await Promise.resolve().then(() => (init_logger(), logger_exports));
|
|
5828
|
-
const resolvedRoot =
|
|
5829
|
-
const outDir =
|
|
6515
|
+
const resolvedRoot = path18.resolve(root ?? ".");
|
|
6516
|
+
const outDir = path18.resolve(resolvedRoot, options.outDir);
|
|
5830
6517
|
const app = connect2();
|
|
5831
6518
|
app.use(sirv2(outDir, { single: true, etag: true, gzip: true, brotli: true }));
|
|
5832
6519
|
const port = options.port;
|
|
5833
6520
|
const host = options.host === true ? "0.0.0.0" : options.host ?? "localhost";
|
|
5834
6521
|
http2.createServer(app).listen(port, host, () => {
|
|
5835
6522
|
logger.info(`
|
|
5836
|
-
${pc11.cyan(pc11.bold("NASTI"))} ${pc11.cyan(`v${"2.
|
|
6523
|
+
${pc11.cyan(pc11.bold("NASTI"))} ${pc11.cyan(`v${"2.4.0"}`)} ${pc11.dim("preview")}
|
|
5837
6524
|
`);
|
|
5838
6525
|
printServerUrls2(
|
|
5839
6526
|
{
|
|
@@ -5850,6 +6537,6 @@ cli.command("preview [root]", "Preview production build").option("--port <port>"
|
|
|
5850
6537
|
}
|
|
5851
6538
|
});
|
|
5852
6539
|
cli.help();
|
|
5853
|
-
cli.version("2.
|
|
6540
|
+
cli.version("2.4.0");
|
|
5854
6541
|
cli.parse();
|
|
5855
6542
|
//# sourceMappingURL=cli.js.map
|