@nasti-toolchain/nasti 2.3.1 → 2.4.1
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 +97 -1
- package/bin/nasti.js +0 -0
- package/client/hmr.ts +4 -3
- package/dist/cli.cjs +1896 -583
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +1891 -575
- 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 +1810 -497
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +233 -18
- package/dist/index.d.ts +233 -18
- package/dist/index.js +1810 -494
- package/dist/index.js.map +1 -1
- package/package.json +8 -4
package/dist/index.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) => (path19) => {
|
|
14
|
+
var fn = map[path19];
|
|
15
15
|
if (fn) return fn();
|
|
16
|
-
throw new Error("Module not found in bundle: " +
|
|
16
|
+
throw new Error("Module not found in bundle: " + path19);
|
|
17
17
|
};
|
|
18
18
|
var __esm = (fn, res) => function __init() {
|
|
19
19
|
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
@@ -70,7 +70,10 @@ var init_defaults = __esm({
|
|
|
70
70
|
target: "es2022",
|
|
71
71
|
rolldownOptions: {},
|
|
72
72
|
emptyOutDir: true,
|
|
73
|
-
css: {
|
|
73
|
+
css: {
|
|
74
|
+
inject: true,
|
|
75
|
+
emit: true
|
|
76
|
+
},
|
|
74
77
|
reportCompressedSize: true,
|
|
75
78
|
chunkSizeWarningLimit: 500,
|
|
76
79
|
cssCodeSplit: true,
|
|
@@ -425,7 +428,11 @@ async function resolveConfig(inlineConfig = {}, command) {
|
|
|
425
428
|
allowClearScreen: clearScreen2,
|
|
426
429
|
customLogger: merged.customLogger
|
|
427
430
|
});
|
|
428
|
-
const mergedBuild = {
|
|
431
|
+
const mergedBuild = {
|
|
432
|
+
...defaults.build,
|
|
433
|
+
...merged.build,
|
|
434
|
+
css: { ...defaults.build.css, ...merged.build?.css }
|
|
435
|
+
};
|
|
429
436
|
if (merged.build?.cssMinify === void 0) {
|
|
430
437
|
mergedBuild.cssMinify = !!mergedBuild.minify;
|
|
431
438
|
}
|
|
@@ -456,11 +463,17 @@ async function resolveConfig(inlineConfig = {}, command) {
|
|
|
456
463
|
bundledDev: merged.experimental?.bundledDev ?? defaults.experimental.bundledDev
|
|
457
464
|
}
|
|
458
465
|
};
|
|
459
|
-
const
|
|
466
|
+
const rawUserEnvironments = {
|
|
460
467
|
client: {},
|
|
461
468
|
ssr: {},
|
|
462
469
|
...merged.environments ?? {}
|
|
463
470
|
};
|
|
471
|
+
const userEnvironments = Object.fromEntries(
|
|
472
|
+
Object.entries(rawUserEnvironments).map(([name, options]) => [
|
|
473
|
+
name,
|
|
474
|
+
deepMerge({}, options)
|
|
475
|
+
])
|
|
476
|
+
);
|
|
464
477
|
for (const [name, envOptions] of Object.entries(userEnvironments)) {
|
|
465
478
|
for (const plugin of rawPlugins) {
|
|
466
479
|
if (plugin.configEnvironment) {
|
|
@@ -471,6 +484,7 @@ async function resolveConfig(inlineConfig = {}, command) {
|
|
|
471
484
|
}
|
|
472
485
|
for (const [name, envOptions] of Object.entries(userEnvironments)) {
|
|
473
486
|
const consumer = envOptions.consumer ?? (name === "client" ? "client" : "server");
|
|
487
|
+
const vueOptions = deepMerge({}, envOptions.vue ?? {});
|
|
474
488
|
if (name === "client") {
|
|
475
489
|
if (envOptions.resolve) {
|
|
476
490
|
Object.assign(resolved.resolve, {
|
|
@@ -478,9 +492,14 @@ async function resolveConfig(inlineConfig = {}, command) {
|
|
|
478
492
|
alias: { ...resolved.resolve.alias, ...envOptions.resolve.alias }
|
|
479
493
|
});
|
|
480
494
|
}
|
|
481
|
-
if (envOptions.build)
|
|
495
|
+
if (envOptions.build) {
|
|
496
|
+
const { css, ...environmentBuild } = envOptions.build;
|
|
497
|
+
Object.assign(resolved.build, environmentBuild);
|
|
498
|
+
if (css) resolved.build.css = { ...resolved.build.css, ...css };
|
|
499
|
+
}
|
|
482
500
|
resolved.environments.client = {
|
|
483
501
|
consumer,
|
|
502
|
+
buildEnabled: envOptions.buildEnabled ?? true,
|
|
484
503
|
entry: normalizeEnvironmentEntries(envOptions.entry, root),
|
|
485
504
|
html: path.resolve(
|
|
486
505
|
root,
|
|
@@ -489,15 +508,18 @@ async function resolveConfig(inlineConfig = {}, command) {
|
|
|
489
508
|
driver: envOptions.driver,
|
|
490
509
|
// 同引用 —— 精确镜像(assertClientEnvironmentMirror 校验)
|
|
491
510
|
resolve: resolved.resolve,
|
|
492
|
-
build: resolved.build
|
|
511
|
+
build: resolved.build,
|
|
512
|
+
vue: vueOptions
|
|
493
513
|
};
|
|
494
514
|
continue;
|
|
495
515
|
}
|
|
496
516
|
resolved.environments[name] = {
|
|
497
517
|
consumer,
|
|
518
|
+
buildEnabled: envOptions.buildEnabled ?? true,
|
|
498
519
|
entry: normalizeEnvironmentEntries(envOptions.entry, root),
|
|
499
520
|
html: envOptions.consumer === "client" && envOptions.html ? path.resolve(root, envOptions.html) : void 0,
|
|
500
521
|
driver: envOptions.driver,
|
|
522
|
+
vue: vueOptions,
|
|
501
523
|
resolve: {
|
|
502
524
|
alias: { ...resolved.resolve.alias, ...envOptions.resolve?.alias },
|
|
503
525
|
extensions: envOptions.resolve?.extensions ?? [...resolved.resolve.extensions],
|
|
@@ -508,6 +530,7 @@ async function resolveConfig(inlineConfig = {}, command) {
|
|
|
508
530
|
build: {
|
|
509
531
|
...resolved.build,
|
|
510
532
|
...envOptions.build,
|
|
533
|
+
css: { ...resolved.build.css, ...envOptions.build?.css },
|
|
511
534
|
// 非 client 环境默认产出到 <outDir>/<envName>(如 dist/ssr),可显式覆盖
|
|
512
535
|
outDir: envOptions.build?.outDir ?? path.join(resolved.build.outDir, name),
|
|
513
536
|
// server 产物默认不压缩(可调试性优先,与 Vite SSR 默认一致),可显式覆盖
|
|
@@ -721,6 +744,7 @@ function resolvePlugin(config) {
|
|
|
721
744
|
}
|
|
722
745
|
if (!source.startsWith("/") && !source.startsWith(".")) {
|
|
723
746
|
if (vueRuntimeEntry && source === "vue") return vueRuntimeEntry;
|
|
747
|
+
if (config.command === "build") return null;
|
|
724
748
|
try {
|
|
725
749
|
const resolved = require2.resolve(source, {
|
|
726
750
|
paths: [importer ? path2.dirname(importer) : config.root]
|
|
@@ -739,7 +763,7 @@ function resolvePlugin(config) {
|
|
|
739
763
|
const content = fs2.readFileSync(id, "utf-8");
|
|
740
764
|
return `export default ${content}`;
|
|
741
765
|
}
|
|
742
|
-
return
|
|
766
|
+
return null;
|
|
743
767
|
}
|
|
744
768
|
};
|
|
745
769
|
}
|
|
@@ -852,27 +876,27 @@ var require_process = __commonJS({
|
|
|
852
876
|
var require_filesystem = __commonJS({
|
|
853
877
|
"node_modules/detect-libc/lib/filesystem.js"(exports, module) {
|
|
854
878
|
"use strict";
|
|
855
|
-
var
|
|
879
|
+
var fs14 = __require("fs");
|
|
856
880
|
var LDD_PATH = "/usr/bin/ldd";
|
|
857
881
|
var SELF_PATH = "/proc/self/exe";
|
|
858
882
|
var MAX_LENGTH = 2048;
|
|
859
|
-
var readFileSync = (
|
|
860
|
-
const fd =
|
|
883
|
+
var readFileSync = (path19) => {
|
|
884
|
+
const fd = fs14.openSync(path19, "r");
|
|
861
885
|
const buffer = Buffer.alloc(MAX_LENGTH);
|
|
862
|
-
const bytesRead =
|
|
863
|
-
|
|
886
|
+
const bytesRead = fs14.readSync(fd, buffer, 0, MAX_LENGTH, 0);
|
|
887
|
+
fs14.close(fd, () => {
|
|
864
888
|
});
|
|
865
889
|
return buffer.subarray(0, bytesRead);
|
|
866
890
|
};
|
|
867
|
-
var readFile = (
|
|
868
|
-
|
|
891
|
+
var readFile = (path19) => new Promise((resolve, reject) => {
|
|
892
|
+
fs14.open(path19, "r", (err, fd) => {
|
|
869
893
|
if (err) {
|
|
870
894
|
reject(err);
|
|
871
895
|
} else {
|
|
872
896
|
const buffer = Buffer.alloc(MAX_LENGTH);
|
|
873
|
-
|
|
897
|
+
fs14.read(fd, buffer, 0, MAX_LENGTH, 0, (_, bytesRead) => {
|
|
874
898
|
resolve(buffer.subarray(0, bytesRead));
|
|
875
|
-
|
|
899
|
+
fs14.close(fd, () => {
|
|
876
900
|
});
|
|
877
901
|
});
|
|
878
902
|
}
|
|
@@ -984,11 +1008,11 @@ var require_detect_libc = __commonJS({
|
|
|
984
1008
|
}
|
|
985
1009
|
return null;
|
|
986
1010
|
};
|
|
987
|
-
var familyFromInterpreterPath = (
|
|
988
|
-
if (
|
|
989
|
-
if (
|
|
1011
|
+
var familyFromInterpreterPath = (path19) => {
|
|
1012
|
+
if (path19) {
|
|
1013
|
+
if (path19.includes("/ld-musl-")) {
|
|
990
1014
|
return MUSL;
|
|
991
|
-
} else if (
|
|
1015
|
+
} else if (path19.includes("/ld-linux-")) {
|
|
992
1016
|
return GLIBC;
|
|
993
1017
|
}
|
|
994
1018
|
}
|
|
@@ -1035,8 +1059,8 @@ var require_detect_libc = __commonJS({
|
|
|
1035
1059
|
cachedFamilyInterpreter = null;
|
|
1036
1060
|
try {
|
|
1037
1061
|
const selfContent = await readFile(SELF_PATH);
|
|
1038
|
-
const
|
|
1039
|
-
cachedFamilyInterpreter = familyFromInterpreterPath(
|
|
1062
|
+
const path19 = interpreterPath(selfContent);
|
|
1063
|
+
cachedFamilyInterpreter = familyFromInterpreterPath(path19);
|
|
1040
1064
|
} catch (e) {
|
|
1041
1065
|
}
|
|
1042
1066
|
return cachedFamilyInterpreter;
|
|
@@ -1048,8 +1072,8 @@ var require_detect_libc = __commonJS({
|
|
|
1048
1072
|
cachedFamilyInterpreter = null;
|
|
1049
1073
|
try {
|
|
1050
1074
|
const selfContent = readFileSync(SELF_PATH);
|
|
1051
|
-
const
|
|
1052
|
-
cachedFamilyInterpreter = familyFromInterpreterPath(
|
|
1075
|
+
const path19 = interpreterPath(selfContent);
|
|
1076
|
+
cachedFamilyInterpreter = familyFromInterpreterPath(path19);
|
|
1053
1077
|
} catch (e) {
|
|
1054
1078
|
}
|
|
1055
1079
|
return cachedFamilyInterpreter;
|
|
@@ -1696,12 +1720,31 @@ var init_node = __esm({
|
|
|
1696
1720
|
function createCssEngine() {
|
|
1697
1721
|
return {
|
|
1698
1722
|
styles: /* @__PURE__ */ new Map(),
|
|
1723
|
+
modules: /* @__PURE__ */ new Map(),
|
|
1724
|
+
chunks: /* @__PURE__ */ new Map(),
|
|
1699
1725
|
entryCss: /* @__PURE__ */ new Map(),
|
|
1700
1726
|
allCss: [],
|
|
1701
1727
|
pendingSingle: [],
|
|
1702
1728
|
singleFileName: null
|
|
1703
1729
|
};
|
|
1704
1730
|
}
|
|
1731
|
+
function getCssMetadata(engine) {
|
|
1732
|
+
return {
|
|
1733
|
+
modules: Object.fromEntries(
|
|
1734
|
+
[...engine.modules].map(([id, module]) => [id, { ...module }])
|
|
1735
|
+
),
|
|
1736
|
+
chunks: Object.fromEntries(
|
|
1737
|
+
[...engine.chunks].map(([fileName, chunk]) => [
|
|
1738
|
+
fileName,
|
|
1739
|
+
{
|
|
1740
|
+
fileName,
|
|
1741
|
+
moduleIds: [...chunk.moduleIds],
|
|
1742
|
+
cssFileNames: [...chunk.cssFileNames]
|
|
1743
|
+
}
|
|
1744
|
+
])
|
|
1745
|
+
)
|
|
1746
|
+
};
|
|
1747
|
+
}
|
|
1705
1748
|
function normalizeCssModuleId(id) {
|
|
1706
1749
|
return id.startsWith("\0") ? id.slice(1) : id;
|
|
1707
1750
|
}
|
|
@@ -1803,6 +1846,7 @@ var init_tailwind = __esm({
|
|
|
1803
1846
|
|
|
1804
1847
|
// src/plugins/css.ts
|
|
1805
1848
|
import path4 from "path";
|
|
1849
|
+
import { SourceMapGenerator } from "source-map-js";
|
|
1806
1850
|
function cssPlugin(config, engine, consumer = "client") {
|
|
1807
1851
|
return {
|
|
1808
1852
|
name: "nasti:css",
|
|
@@ -1822,15 +1866,29 @@ function cssPlugin(config, engine, consumer = "client") {
|
|
|
1822
1866
|
}
|
|
1823
1867
|
const rewritten = rewriteCssUrls(cssSource, file, config.root);
|
|
1824
1868
|
const escaped = JSON.stringify(rewritten);
|
|
1869
|
+
const normalizedId = normalizeCssModuleId(id);
|
|
1870
|
+
const cssModule = { id: normalizedId, source: code, code: rewritten };
|
|
1871
|
+
const map = config.build.sourcemap ? createIdentitySourceMap(code, id) : void 0;
|
|
1872
|
+
engine?.modules.set(normalizedId, cssModule);
|
|
1873
|
+
this.environment?.setCssModule?.(cssModule);
|
|
1825
1874
|
if (query === "inline") {
|
|
1826
1875
|
return { code: `export default ${escaped};
|
|
1827
|
-
`, moduleType: "js" };
|
|
1876
|
+
`, map, moduleType: "js" };
|
|
1828
1877
|
}
|
|
1829
1878
|
if (consumer === "server") {
|
|
1830
1879
|
return { code: `export default ${escaped};
|
|
1831
|
-
`, moduleType: "js" };
|
|
1880
|
+
`, map, moduleType: "js" };
|
|
1832
1881
|
}
|
|
1833
1882
|
if (config.command === "serve") {
|
|
1883
|
+
if (config.build.css.inject === false) {
|
|
1884
|
+
return {
|
|
1885
|
+
code: `export default ${escaped};
|
|
1886
|
+
`,
|
|
1887
|
+
map,
|
|
1888
|
+
moduleType: "js",
|
|
1889
|
+
moduleSideEffects: "no-treeshake"
|
|
1890
|
+
};
|
|
1891
|
+
}
|
|
1834
1892
|
return {
|
|
1835
1893
|
code: `
|
|
1836
1894
|
const css = ${escaped};
|
|
@@ -1854,16 +1912,18 @@ if (import.meta.hot) {
|
|
|
1854
1912
|
|
|
1855
1913
|
export default css;
|
|
1856
1914
|
`,
|
|
1915
|
+
map,
|
|
1857
1916
|
// bundled dev(DevEngine)下该模块会进 Rolldown:不标 js 会按 .css
|
|
1858
1917
|
// 扩展名走 CSS 管线触发 #4271 报错;unbundled 中间件忽略此字段
|
|
1859
1918
|
moduleType: "js"
|
|
1860
1919
|
};
|
|
1861
1920
|
}
|
|
1862
1921
|
if (engine) {
|
|
1863
|
-
engine.styles.set(
|
|
1922
|
+
engine.styles.set(normalizedId, rewritten);
|
|
1864
1923
|
return {
|
|
1865
1924
|
code: `export default '';
|
|
1866
1925
|
`,
|
|
1926
|
+
map,
|
|
1867
1927
|
moduleType: "js",
|
|
1868
1928
|
// 防止空 stub 被 tree-shake 出 chunk.moduleIds(css-post 靠它定位)
|
|
1869
1929
|
moduleSideEffects: "no-treeshake"
|
|
@@ -1883,11 +1943,27 @@ document.head.appendChild(style);
|
|
|
1883
1943
|
|
|
1884
1944
|
export default css;
|
|
1885
1945
|
`,
|
|
1946
|
+
map,
|
|
1886
1947
|
moduleType: "js"
|
|
1887
1948
|
};
|
|
1888
1949
|
}
|
|
1889
1950
|
};
|
|
1890
1951
|
}
|
|
1952
|
+
function createIdentitySourceMap(code, id) {
|
|
1953
|
+
const map = new SourceMapGenerator({ file: id });
|
|
1954
|
+
const lines = code.split("\n");
|
|
1955
|
+
for (let lineIndex = 0; lineIndex < lines.length; lineIndex++) {
|
|
1956
|
+
for (let column = 0; column <= lines[lineIndex].length; column++) {
|
|
1957
|
+
map.addMapping({
|
|
1958
|
+
generated: { line: lineIndex + 1, column },
|
|
1959
|
+
original: { line: lineIndex + 1, column },
|
|
1960
|
+
source: id
|
|
1961
|
+
});
|
|
1962
|
+
}
|
|
1963
|
+
}
|
|
1964
|
+
map.setSourceContent(id, code);
|
|
1965
|
+
return map.toJSON();
|
|
1966
|
+
}
|
|
1891
1967
|
function rewriteCssUrls(css, from, root) {
|
|
1892
1968
|
return css.replace(/url\(\s*['"]?([^'")\s]+)['"]?\s*\)/g, (match, url) => {
|
|
1893
1969
|
if (url.startsWith("/") || url.startsWith("data:") || url.startsWith("http")) {
|
|
@@ -1910,19 +1986,27 @@ var init_css = __esm({
|
|
|
1910
1986
|
function collectChunkCss(chunk, engine) {
|
|
1911
1987
|
const ids = chunk.moduleIds ?? Object.keys(chunk.modules);
|
|
1912
1988
|
let css = "";
|
|
1989
|
+
const moduleIds = [];
|
|
1913
1990
|
for (const id of ids) {
|
|
1914
|
-
const
|
|
1915
|
-
|
|
1991
|
+
const normalizedId = normalizeCssModuleId(id);
|
|
1992
|
+
const styles = engine.styles.get(normalizedId);
|
|
1993
|
+
if (styles) {
|
|
1994
|
+
css += styles + "\n";
|
|
1995
|
+
moduleIds.push(normalizedId);
|
|
1996
|
+
}
|
|
1916
1997
|
}
|
|
1917
|
-
return css;
|
|
1998
|
+
return { css, moduleIds };
|
|
1918
1999
|
}
|
|
1919
2000
|
function cssPostPlugin(config, engine) {
|
|
1920
2001
|
return {
|
|
1921
2002
|
name: "nasti:css-post",
|
|
1922
2003
|
enforce: "post",
|
|
1923
2004
|
async renderChunk(code, chunk) {
|
|
1924
|
-
const css = collectChunkCss(chunk, engine);
|
|
2005
|
+
const { css, moduleIds } = collectChunkCss(chunk, engine);
|
|
1925
2006
|
if (!css) return null;
|
|
2007
|
+
const ownership = { moduleIds, cssFileNames: [] };
|
|
2008
|
+
engine.chunks.set(chunk.fileName, ownership);
|
|
2009
|
+
if (config.build.css.emit === false) return null;
|
|
1926
2010
|
if (!config.build.cssCodeSplit) {
|
|
1927
2011
|
engine.pendingSingle.push(css);
|
|
1928
2012
|
return null;
|
|
@@ -1935,6 +2019,7 @@ function cssPostPlugin(config, engine) {
|
|
|
1935
2019
|
});
|
|
1936
2020
|
const fileName = this.getFileName(ref);
|
|
1937
2021
|
engine.allCss.push(fileName);
|
|
2022
|
+
ownership.cssFileNames.push(fileName);
|
|
1938
2023
|
if (chunk.isEntry) {
|
|
1939
2024
|
const key = chunk.facadeModuleId ?? chunk.name;
|
|
1940
2025
|
const existing = engine.entryCss.get(key) ?? [];
|
|
@@ -1942,13 +2027,14 @@ function cssPostPlugin(config, engine) {
|
|
|
1942
2027
|
engine.entryCss.set(key, existing);
|
|
1943
2028
|
return null;
|
|
1944
2029
|
}
|
|
2030
|
+
if (config.build.css.inject === false) return null;
|
|
1945
2031
|
const href = JSON.stringify(config.base + fileName);
|
|
1946
2032
|
const snippet = `
|
|
1947
2033
|
;(function(){try{var d=document,h=${href};if(!d.querySelector('link[data-nasti-css="'+h+'"]')){var l=d.createElement('link');l.rel='stylesheet';l.href=h;l.setAttribute('data-nasti-css',h);d.head.appendChild(l);}}catch(e){}})();`;
|
|
1948
2034
|
return { code: code + snippet, map: null };
|
|
1949
2035
|
},
|
|
1950
2036
|
augmentChunkHash(chunk) {
|
|
1951
|
-
const css = collectChunkCss(chunk, engine);
|
|
2037
|
+
const { css } = collectChunkCss(chunk, engine);
|
|
1952
2038
|
return css || void 0;
|
|
1953
2039
|
},
|
|
1954
2040
|
async generateBundle() {
|
|
@@ -1959,6 +2045,9 @@ function cssPostPlugin(config, engine) {
|
|
|
1959
2045
|
const fileName = this.getFileName(ref);
|
|
1960
2046
|
engine.singleFileName = fileName;
|
|
1961
2047
|
engine.allCss.push(fileName);
|
|
2048
|
+
for (const ownership of engine.chunks.values()) {
|
|
2049
|
+
if (ownership.moduleIds.length > 0) ownership.cssFileNames.push(fileName);
|
|
2050
|
+
}
|
|
1962
2051
|
}
|
|
1963
2052
|
};
|
|
1964
2053
|
}
|
|
@@ -1974,6 +2063,7 @@ import path5 from "path";
|
|
|
1974
2063
|
import fs3 from "fs";
|
|
1975
2064
|
import crypto from "crypto";
|
|
1976
2065
|
function assetsPlugin(config) {
|
|
2066
|
+
const emittedAssets = /* @__PURE__ */ new Set();
|
|
1977
2067
|
return {
|
|
1978
2068
|
name: "nasti:assets",
|
|
1979
2069
|
resolveId(source) {
|
|
@@ -2002,12 +2092,29 @@ function assetsPlugin(config) {
|
|
|
2002
2092
|
const hash = crypto.createHash("sha256").update(content).digest("hex").slice(0, 8);
|
|
2003
2093
|
const basename = path5.basename(file, ext);
|
|
2004
2094
|
const hashedName = `${config.build.assetsDir}/${basename}.${hash}${ext}`;
|
|
2095
|
+
const environment = this.environment;
|
|
2096
|
+
if (!environment) {
|
|
2097
|
+
throw new Error("[nasti:assets] build environment is not initialized");
|
|
2098
|
+
}
|
|
2099
|
+
if (!emittedAssets.has(hashedName)) {
|
|
2100
|
+
this.emitFile({
|
|
2101
|
+
type: "asset",
|
|
2102
|
+
fileName: hashedName,
|
|
2103
|
+
source: content
|
|
2104
|
+
});
|
|
2105
|
+
emittedAssets.add(hashedName);
|
|
2106
|
+
}
|
|
2107
|
+
environment.setAssetModule(file, hashedName);
|
|
2005
2108
|
return `export default ${JSON.stringify(config.base + hashedName)}`;
|
|
2006
2109
|
}
|
|
2007
2110
|
return null;
|
|
2008
2111
|
}
|
|
2009
2112
|
};
|
|
2010
2113
|
}
|
|
2114
|
+
function isAssetFile(id) {
|
|
2115
|
+
const ext = path5.extname(id.replace(/\?.*$/, ""));
|
|
2116
|
+
return ASSET_EXTENSIONS.has(ext);
|
|
2117
|
+
}
|
|
2011
2118
|
var ASSET_EXTENSIONS;
|
|
2012
2119
|
var init_assets = __esm({
|
|
2013
2120
|
"src/plugins/assets.ts"() {
|
|
@@ -2079,6 +2186,11 @@ var init_transformer = __esm({
|
|
|
2079
2186
|
|
|
2080
2187
|
// src/plugins/vue.ts
|
|
2081
2188
|
import crypto2 from "crypto";
|
|
2189
|
+
import {
|
|
2190
|
+
SourceMapConsumer,
|
|
2191
|
+
SourceMapGenerator as SourceMapGenerator2,
|
|
2192
|
+
SourceNode
|
|
2193
|
+
} from "source-map-js";
|
|
2082
2194
|
async function loadVueCompiler() {
|
|
2083
2195
|
if (compiler) return compiler;
|
|
2084
2196
|
try {
|
|
@@ -2088,9 +2200,10 @@ async function loadVueCompiler() {
|
|
|
2088
2200
|
return null;
|
|
2089
2201
|
}
|
|
2090
2202
|
}
|
|
2091
|
-
function vuePlugin(config) {
|
|
2203
|
+
function vuePlugin(config, environmentName = "client") {
|
|
2092
2204
|
const isDev = config.command === "serve";
|
|
2093
2205
|
const descriptorCache = /* @__PURE__ */ new Map();
|
|
2206
|
+
const vueOptions = config.environments[environmentName]?.vue ?? {};
|
|
2094
2207
|
return {
|
|
2095
2208
|
name: "nasti:vue",
|
|
2096
2209
|
enforce: "pre",
|
|
@@ -2110,32 +2223,63 @@ function vuePlugin(config) {
|
|
|
2110
2223
|
const sfc = await loadVueCompiler();
|
|
2111
2224
|
if (!sfc) return null;
|
|
2112
2225
|
const [, filePath, indexStr] = match;
|
|
2113
|
-
let
|
|
2114
|
-
if (!
|
|
2226
|
+
let cached2 = descriptorCache.get(filePath);
|
|
2227
|
+
if (!cached2) {
|
|
2115
2228
|
try {
|
|
2116
|
-
const
|
|
2117
|
-
const
|
|
2118
|
-
const
|
|
2229
|
+
const fs14 = await import("fs");
|
|
2230
|
+
const rawSource = fs14.readFileSync(filePath, "utf-8");
|
|
2231
|
+
const transformedSfc = await applySourceTransform(
|
|
2232
|
+
vueOptions.transformSfc,
|
|
2233
|
+
rawSource,
|
|
2234
|
+
{ filename: filePath, environmentName, type: "sfc" }
|
|
2235
|
+
);
|
|
2236
|
+
const parsed = sfc.parse(transformedSfc.code, {
|
|
2237
|
+
...vueOptions.parse,
|
|
2238
|
+
filename: filePath,
|
|
2239
|
+
sourceMap: true
|
|
2240
|
+
});
|
|
2119
2241
|
if (parsed.errors.length) return null;
|
|
2120
|
-
|
|
2121
|
-
|
|
2242
|
+
cached2 = {
|
|
2243
|
+
descriptor: parsed.descriptor,
|
|
2244
|
+
sourceMap: transformedSfc.map
|
|
2245
|
+
};
|
|
2246
|
+
descriptorCache.set(filePath, cached2);
|
|
2122
2247
|
} catch {
|
|
2123
2248
|
return null;
|
|
2124
2249
|
}
|
|
2125
2250
|
}
|
|
2251
|
+
const { descriptor, sourceMap: sfcSourceMap } = cached2;
|
|
2126
2252
|
const index2 = parseInt(indexStr ?? "0", 10);
|
|
2127
2253
|
const style = descriptor.styles[index2];
|
|
2128
2254
|
if (!style) return null;
|
|
2129
2255
|
const scopeId = hashId(filePath);
|
|
2256
|
+
const transformedStyle = await applySourceTransform(
|
|
2257
|
+
vueOptions.transformStyle,
|
|
2258
|
+
style.content,
|
|
2259
|
+
{ filename: filePath, environmentName, type: "style", index: index2 }
|
|
2260
|
+
);
|
|
2261
|
+
const wantsStyleSourceMap = !!config.build.sourcemap || transformedStyle.map != null || sfcSourceMap != null;
|
|
2262
|
+
const styleInputMap = wantsStyleSourceMap ? composeSourceMapChain(
|
|
2263
|
+
[transformedStyle.map, style.map, sfcSourceMap],
|
|
2264
|
+
{ filename: filePath, environmentName, type: "style", index: index2 }
|
|
2265
|
+
) : void 0;
|
|
2130
2266
|
const result = await sfc.compileStyleAsync({
|
|
2131
|
-
|
|
2267
|
+
...vueOptions.style,
|
|
2268
|
+
source: transformedStyle.code,
|
|
2132
2269
|
filename: filePath,
|
|
2133
2270
|
id: `data-v-${scopeId}`,
|
|
2134
2271
|
scoped: style.scoped ?? false,
|
|
2272
|
+
inMap: styleInputMap,
|
|
2135
2273
|
// <style lang="scss|less|stylus"> 需经对应预处理器(缺省 undefined = 纯 CSS)
|
|
2136
2274
|
preprocessLang: style.lang
|
|
2137
2275
|
});
|
|
2138
|
-
|
|
2276
|
+
if (transformedStyle.map != null && result.map == null) {
|
|
2277
|
+
warnUnchainableMap(
|
|
2278
|
+
{ filename: filePath, environmentName, type: "style", index: index2 },
|
|
2279
|
+
"compiler-sfc did not return a style map"
|
|
2280
|
+
);
|
|
2281
|
+
}
|
|
2282
|
+
return wantsStyleSourceMap ? { code: result.code, map: result.map } : result.code;
|
|
2139
2283
|
},
|
|
2140
2284
|
async transform(code, id) {
|
|
2141
2285
|
if (!VUE_FILE_RE.test(id) && !VUE_QUERY_RE.test(id)) return null;
|
|
@@ -2147,57 +2291,144 @@ function vuePlugin(config) {
|
|
|
2147
2291
|
if (VUE_QUERY_RE.test(id)) {
|
|
2148
2292
|
return null;
|
|
2149
2293
|
}
|
|
2150
|
-
const
|
|
2294
|
+
const transformedSfc = await applySourceTransform(
|
|
2295
|
+
vueOptions.transformSfc,
|
|
2296
|
+
code,
|
|
2297
|
+
{ filename: id, environmentName, type: "sfc" }
|
|
2298
|
+
);
|
|
2299
|
+
code = transformedSfc.code;
|
|
2300
|
+
const { descriptor, errors } = sfc.parse(code, {
|
|
2301
|
+
...vueOptions.parse,
|
|
2302
|
+
filename: id,
|
|
2303
|
+
sourceMap: true
|
|
2304
|
+
});
|
|
2151
2305
|
if (errors.length) {
|
|
2152
|
-
|
|
2306
|
+
const firstError = errors[0];
|
|
2307
|
+
console.error(
|
|
2308
|
+
`[nasti:vue] Parse error in ${id}:`,
|
|
2309
|
+
typeof firstError === "string" ? firstError : firstError.message
|
|
2310
|
+
);
|
|
2153
2311
|
return null;
|
|
2154
2312
|
}
|
|
2155
|
-
descriptorCache.set(id,
|
|
2313
|
+
descriptorCache.set(id, {
|
|
2314
|
+
descriptor,
|
|
2315
|
+
sourceMap: transformedSfc.map
|
|
2316
|
+
});
|
|
2156
2317
|
const scopeId = hashId(id);
|
|
2318
|
+
const wantsSourceMap = !!config.build.sourcemap || transformedSfc.map != null;
|
|
2157
2319
|
let scriptCode = "";
|
|
2320
|
+
let scriptMap;
|
|
2158
2321
|
if (descriptor.script || descriptor.scriptSetup) {
|
|
2322
|
+
const inlineTemplate = vueOptions.script?.inlineTemplate !== false;
|
|
2159
2323
|
const compiled = sfc.compileScript(descriptor, {
|
|
2324
|
+
...vueOptions.script,
|
|
2160
2325
|
id: scopeId,
|
|
2161
2326
|
isProd: !isDev,
|
|
2162
|
-
inlineTemplate
|
|
2327
|
+
inlineTemplate,
|
|
2328
|
+
sourceMap: wantsSourceMap,
|
|
2163
2329
|
// 让 compileScript 产出 `const __sfc__ = ...`(而非默认的 `export default {...}`)。
|
|
2164
2330
|
// 否则下方追加的 `__sfc__.render` / `__sfc__.__scopeId` / HMR 记录会引用一个
|
|
2165
2331
|
// 不存在的 `__sfc__`,并与 compileScript 自带的 `export default` 形成双重默认导出。
|
|
2166
2332
|
genDefaultAs: "__sfc__"
|
|
2167
2333
|
});
|
|
2168
2334
|
scriptCode = compiled.content;
|
|
2335
|
+
scriptMap = composeSourceMapChain(
|
|
2336
|
+
[compiled.map, transformedSfc.map],
|
|
2337
|
+
{ filename: id, environmentName, type: "sfc" }
|
|
2338
|
+
);
|
|
2339
|
+
if (transformedSfc.map != null && scriptMap == null) {
|
|
2340
|
+
warnUnchainableMap(
|
|
2341
|
+
{ filename: id, environmentName, type: "sfc" },
|
|
2342
|
+
"compiler-sfc did not return a script map"
|
|
2343
|
+
);
|
|
2344
|
+
}
|
|
2169
2345
|
}
|
|
2170
2346
|
let templateCode = "";
|
|
2171
|
-
|
|
2347
|
+
let templateMap;
|
|
2348
|
+
const scriptSetupIsInline = !!descriptor.scriptSetup && vueOptions.script?.inlineTemplate !== false;
|
|
2349
|
+
if (descriptor.template && !scriptSetupIsInline) {
|
|
2350
|
+
const transformedTemplate = await applySourceTransform(
|
|
2351
|
+
vueOptions.transformTemplate,
|
|
2352
|
+
descriptor.template.content,
|
|
2353
|
+
{ filename: id, environmentName, type: "template" }
|
|
2354
|
+
);
|
|
2355
|
+
const templateInputMap = composeSourceMapChain(
|
|
2356
|
+
[
|
|
2357
|
+
transformedTemplate.map,
|
|
2358
|
+
descriptor.template.map,
|
|
2359
|
+
transformedSfc.map
|
|
2360
|
+
],
|
|
2361
|
+
{ filename: id, environmentName, type: "template" }
|
|
2362
|
+
);
|
|
2363
|
+
const customCompilerOptions = vueOptions.template?.compilerOptions ?? {};
|
|
2172
2364
|
const compiled = sfc.compileTemplate({
|
|
2173
|
-
|
|
2365
|
+
...vueOptions.template,
|
|
2366
|
+
source: transformedTemplate.code,
|
|
2174
2367
|
filename: id,
|
|
2175
2368
|
id: scopeId,
|
|
2176
|
-
|
|
2369
|
+
inMap: templateInputMap,
|
|
2370
|
+
compilerOptions: {
|
|
2371
|
+
...customCompilerOptions,
|
|
2372
|
+
scopeId: `data-v-${scopeId}`
|
|
2373
|
+
}
|
|
2177
2374
|
});
|
|
2178
2375
|
templateCode = compiled.code;
|
|
2376
|
+
if (wantsSourceMap || transformedTemplate.map != null) {
|
|
2377
|
+
templateMap = compiled.map;
|
|
2378
|
+
}
|
|
2379
|
+
if (transformedTemplate.map != null && templateMap == null) {
|
|
2380
|
+
warnUnchainableMap(
|
|
2381
|
+
{ filename: id, environmentName, type: "template" },
|
|
2382
|
+
"compiler-sfc did not return a template map"
|
|
2383
|
+
);
|
|
2384
|
+
}
|
|
2179
2385
|
}
|
|
2180
|
-
|
|
2386
|
+
const outputNode = new SourceNode();
|
|
2387
|
+
let hasMappedOutput = false;
|
|
2388
|
+
const append = (fragment, map) => {
|
|
2389
|
+
const normalizedMap = normalizeSourceMap(
|
|
2390
|
+
map,
|
|
2391
|
+
{ filename: id, environmentName, type: "sfc" }
|
|
2392
|
+
);
|
|
2393
|
+
if (!normalizedMap) {
|
|
2394
|
+
outputNode.add(fragment);
|
|
2395
|
+
return;
|
|
2396
|
+
}
|
|
2397
|
+
try {
|
|
2398
|
+
outputNode.add(
|
|
2399
|
+
SourceNode.fromStringWithSourceMap(
|
|
2400
|
+
fragment,
|
|
2401
|
+
new SourceMapConsumer(normalizedMap)
|
|
2402
|
+
)
|
|
2403
|
+
);
|
|
2404
|
+
hasMappedOutput = true;
|
|
2405
|
+
} catch (error) {
|
|
2406
|
+
warnUnchainableMap(
|
|
2407
|
+
{ filename: id, environmentName, type: "sfc" },
|
|
2408
|
+
`source-map assembly failed: ${error instanceof Error ? error.message : String(error)}`
|
|
2409
|
+
);
|
|
2410
|
+
outputNode.add(fragment);
|
|
2411
|
+
}
|
|
2412
|
+
};
|
|
2413
|
+
append(scriptCode || "const __sfc__ = {}", scriptMap);
|
|
2181
2414
|
if (templateCode) {
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
__sfc__.render = render
|
|
2187
|
-
`;
|
|
2415
|
+
append("\n");
|
|
2416
|
+
append(templateCode, templateMap);
|
|
2417
|
+
append("\n");
|
|
2418
|
+
append("\n__sfc__.render = render\n");
|
|
2188
2419
|
}
|
|
2189
2420
|
if (descriptor.styles.length > 0) {
|
|
2190
2421
|
for (let i = 0; i < descriptor.styles.length; i++) {
|
|
2191
|
-
|
|
2422
|
+
append(`
|
|
2192
2423
|
import "${id}?vue&type=style&index=${i}&lang.css"
|
|
2193
|
-
|
|
2424
|
+
`);
|
|
2194
2425
|
}
|
|
2195
2426
|
}
|
|
2196
|
-
|
|
2427
|
+
append(`
|
|
2197
2428
|
__sfc__.__scopeId = "data-v-${scopeId}"
|
|
2198
|
-
|
|
2429
|
+
`);
|
|
2199
2430
|
if (isDev) {
|
|
2200
|
-
|
|
2431
|
+
append(`
|
|
2201
2432
|
__sfc__.__hmrId = ${JSON.stringify(scopeId)}
|
|
2202
2433
|
if (typeof __VUE_HMR_RUNTIME__ !== 'undefined') {
|
|
2203
2434
|
__VUE_HMR_RUNTIME__.createRecord(__sfc__.__hmrId, __sfc__)
|
|
@@ -2211,17 +2442,34 @@ if (import.meta.hot) {
|
|
|
2211
2442
|
}
|
|
2212
2443
|
})
|
|
2213
2444
|
}
|
|
2214
|
-
|
|
2445
|
+
`);
|
|
2446
|
+
}
|
|
2447
|
+
append("\nexport default __sfc__\n");
|
|
2448
|
+
const renderedOutput = outputNode.toStringWithSourceMap({ file: id });
|
|
2449
|
+
const output = renderedOutput.code;
|
|
2450
|
+
const outputMap = hasMappedOutput ? renderedOutput.map.toJSON() : void 0;
|
|
2451
|
+
if (transformedSfc.map != null && outputMap == null) {
|
|
2452
|
+
warnUnchainableMap(
|
|
2453
|
+
{ filename: id, environmentName, type: "sfc" },
|
|
2454
|
+
"the compiled SFC output contained no chainable mappings"
|
|
2455
|
+
);
|
|
2215
2456
|
}
|
|
2216
|
-
output += `
|
|
2217
|
-
export default __sfc__
|
|
2218
|
-
`;
|
|
2219
2457
|
const lang = descriptor.scriptSetup?.lang ?? descriptor.script?.lang;
|
|
2220
2458
|
if (lang === "ts") {
|
|
2221
|
-
const transpiled = transformCode(`${id}.ts`, output, {
|
|
2222
|
-
|
|
2459
|
+
const transpiled = transformCode(`${id}.ts`, output, {
|
|
2460
|
+
sourcemap: wantsSourceMap,
|
|
2461
|
+
target: config.build.target
|
|
2462
|
+
});
|
|
2463
|
+
const transpiledMap = transpiled.map ? JSON.parse(transpiled.map) : void 0;
|
|
2464
|
+
return {
|
|
2465
|
+
code: transpiled.code,
|
|
2466
|
+
map: composeSourceMapChain(
|
|
2467
|
+
[transpiledMap, outputMap],
|
|
2468
|
+
{ filename: id, environmentName, type: "sfc" }
|
|
2469
|
+
)
|
|
2470
|
+
};
|
|
2223
2471
|
}
|
|
2224
|
-
return { code: output };
|
|
2472
|
+
return { code: output, map: outputMap };
|
|
2225
2473
|
},
|
|
2226
2474
|
handleHotUpdate(ctx) {
|
|
2227
2475
|
const { file, modules } = ctx;
|
|
@@ -2235,16 +2483,75 @@ export default __sfc__
|
|
|
2235
2483
|
}
|
|
2236
2484
|
};
|
|
2237
2485
|
}
|
|
2486
|
+
async function applySourceTransform(transform2, source, context) {
|
|
2487
|
+
if (!transform2) return { code: source };
|
|
2488
|
+
const result = await transform2(source, context);
|
|
2489
|
+
return typeof result === "string" ? { code: result } : result;
|
|
2490
|
+
}
|
|
2491
|
+
function normalizeSourceMap(map, context) {
|
|
2492
|
+
if (map == null) return void 0;
|
|
2493
|
+
try {
|
|
2494
|
+
const value = typeof map === "string" ? JSON.parse(map) : map;
|
|
2495
|
+
if (value && typeof value === "object" && Array.isArray(value.sources) && Array.isArray(value.names) && typeof value.mappings === "string") {
|
|
2496
|
+
return value;
|
|
2497
|
+
}
|
|
2498
|
+
} catch {
|
|
2499
|
+
}
|
|
2500
|
+
warnUnchainableMap(context, "the provided map is not a valid source map");
|
|
2501
|
+
return void 0;
|
|
2502
|
+
}
|
|
2503
|
+
function composeSourceMapChain(maps, context) {
|
|
2504
|
+
const pending = maps.filter((map) => map != null);
|
|
2505
|
+
if (pending.length === 0) return void 0;
|
|
2506
|
+
let composed = normalizeSourceMap(pending.shift(), context);
|
|
2507
|
+
for (const map of pending) {
|
|
2508
|
+
const input = normalizeSourceMap(map, context);
|
|
2509
|
+
if (!input) continue;
|
|
2510
|
+
if (!composed) {
|
|
2511
|
+
composed = input;
|
|
2512
|
+
continue;
|
|
2513
|
+
}
|
|
2514
|
+
try {
|
|
2515
|
+
const consumer = new SourceMapConsumer(composed);
|
|
2516
|
+
if (consumer.sources.length !== 1) {
|
|
2517
|
+
warnUnchainableMap(
|
|
2518
|
+
context,
|
|
2519
|
+
"a generated map has multiple sources and cannot be chained safely"
|
|
2520
|
+
);
|
|
2521
|
+
continue;
|
|
2522
|
+
}
|
|
2523
|
+
const generator = SourceMapGenerator2.fromSourceMap(consumer);
|
|
2524
|
+
generator.applySourceMap(
|
|
2525
|
+
new SourceMapConsumer(input),
|
|
2526
|
+
consumer.sources[0]
|
|
2527
|
+
);
|
|
2528
|
+
composed = generator.toJSON();
|
|
2529
|
+
} catch (error) {
|
|
2530
|
+
warnUnchainableMap(
|
|
2531
|
+
context,
|
|
2532
|
+
`source-map composition failed: ${error instanceof Error ? error.message : String(error)}`
|
|
2533
|
+
);
|
|
2534
|
+
}
|
|
2535
|
+
}
|
|
2536
|
+
return composed;
|
|
2537
|
+
}
|
|
2538
|
+
function warnUnchainableMap(context, reason) {
|
|
2539
|
+
debug2?.(
|
|
2540
|
+
`source map warning for ${context.filename} (${context.type}, ${context.environmentName}): ${reason}`
|
|
2541
|
+
);
|
|
2542
|
+
}
|
|
2238
2543
|
function hashId(filename) {
|
|
2239
2544
|
return crypto2.createHash("sha256").update(filename).digest("hex").slice(0, 8);
|
|
2240
2545
|
}
|
|
2241
|
-
var VUE_FILE_RE, VUE_QUERY_RE, compiler;
|
|
2546
|
+
var VUE_FILE_RE, VUE_QUERY_RE, debug2, compiler;
|
|
2242
2547
|
var init_vue = __esm({
|
|
2243
2548
|
"src/plugins/vue.ts"() {
|
|
2244
2549
|
"use strict";
|
|
2245
2550
|
init_transformer();
|
|
2551
|
+
init_debug();
|
|
2246
2552
|
VUE_FILE_RE = /\.vue$/;
|
|
2247
2553
|
VUE_QUERY_RE = /\.vue\?vue&type=(script|template|style)(&index=\d+)?(&lang[.=]\w+)?/;
|
|
2554
|
+
debug2 = createDebugger("nasti:vue");
|
|
2248
2555
|
compiler = null;
|
|
2249
2556
|
}
|
|
2250
2557
|
});
|
|
@@ -2335,16 +2642,27 @@ window.__vite_plugin_react_preamble_installed__ = true;
|
|
|
2335
2642
|
// src/plugins/builtins.ts
|
|
2336
2643
|
function resolvePluginList(config, userPlugins, opts = {}) {
|
|
2337
2644
|
const isServe = config.command === "serve";
|
|
2645
|
+
let environmentOptions;
|
|
2646
|
+
if (opts.environmentName) {
|
|
2647
|
+
environmentOptions = config.environments[opts.environmentName];
|
|
2648
|
+
if (!environmentOptions) {
|
|
2649
|
+
throw new Error(
|
|
2650
|
+
`[nasti] unknown environment "${opts.environmentName}" \u2014 declare it in config.environments`
|
|
2651
|
+
);
|
|
2652
|
+
}
|
|
2653
|
+
}
|
|
2654
|
+
const pluginConfig = environmentOptions ? { ...config, resolve: environmentOptions.resolve, build: environmentOptions.build } : config;
|
|
2655
|
+
const consumer = opts.consumer ?? environmentOptions?.consumer;
|
|
2338
2656
|
return [
|
|
2339
2657
|
// vuePlugin 排最前(enforce: 'pre' 语义):.vue 先编译成 JS 再走后续管道
|
|
2340
|
-
...config.framework === "vue" ? [vuePlugin(
|
|
2341
|
-
resolvePlugin(
|
|
2342
|
-
cssPlugin(
|
|
2343
|
-
assetsPlugin(
|
|
2344
|
-
...isServe ? [htmlPlugin(
|
|
2658
|
+
...config.framework === "vue" ? [vuePlugin(pluginConfig, opts.environmentName ?? "client")] : [],
|
|
2659
|
+
resolvePlugin(pluginConfig),
|
|
2660
|
+
cssPlugin(pluginConfig, opts.cssEngine, consumer),
|
|
2661
|
+
assetsPlugin(pluginConfig),
|
|
2662
|
+
...isServe ? [htmlPlugin(pluginConfig)] : [],
|
|
2345
2663
|
...userPlugins,
|
|
2346
2664
|
// cssPostPlugin 最后(enforce: 'post' 语义):renderChunk 聚合抽取
|
|
2347
|
-
...!isServe && opts.cssEngine ? [cssPostPlugin(
|
|
2665
|
+
...!isServe && opts.cssEngine ? [cssPostPlugin(pluginConfig, opts.cssEngine)] : []
|
|
2348
2666
|
];
|
|
2349
2667
|
}
|
|
2350
2668
|
var init_builtins = __esm({
|
|
@@ -2441,17 +2759,23 @@ var init_plugin_container = __esm({
|
|
|
2441
2759
|
}
|
|
2442
2760
|
async transform(code, id) {
|
|
2443
2761
|
let currentCode = code;
|
|
2762
|
+
let lastResult;
|
|
2444
2763
|
for (const plugin of this.plugins) {
|
|
2445
2764
|
if (!plugin.transform) continue;
|
|
2446
2765
|
const result = await plugin.transform.call(this.ctx, currentCode, id);
|
|
2447
2766
|
if (result == null) continue;
|
|
2448
2767
|
if (typeof result === "string") {
|
|
2449
2768
|
currentCode = result;
|
|
2769
|
+
lastResult = void 0;
|
|
2450
2770
|
} else {
|
|
2451
2771
|
currentCode = result.code;
|
|
2772
|
+
lastResult = result;
|
|
2452
2773
|
}
|
|
2453
2774
|
}
|
|
2454
|
-
return currentCode === code ? null : {
|
|
2775
|
+
return currentCode === code ? null : {
|
|
2776
|
+
...lastResult,
|
|
2777
|
+
code: currentCode
|
|
2778
|
+
};
|
|
2455
2779
|
}
|
|
2456
2780
|
/** 完整的模块处理管道: resolveId → load → transform */
|
|
2457
2781
|
async processModule(source, importer) {
|
|
@@ -2474,17 +2798,39 @@ var init_plugin_container = __esm({
|
|
|
2474
2798
|
}
|
|
2475
2799
|
});
|
|
2476
2800
|
|
|
2801
|
+
// src/core/url.ts
|
|
2802
|
+
function removeTimestampQuery(url) {
|
|
2803
|
+
const hashIndex = url.indexOf("#");
|
|
2804
|
+
const hash = hashIndex >= 0 ? url.slice(hashIndex) : "";
|
|
2805
|
+
const withoutHash = hashIndex >= 0 ? url.slice(0, hashIndex) : url;
|
|
2806
|
+
const queryIndex = withoutHash.indexOf("?");
|
|
2807
|
+
if (queryIndex < 0) return url;
|
|
2808
|
+
const pathname = withoutHash.slice(0, queryIndex);
|
|
2809
|
+
const query = withoutHash.slice(queryIndex + 1).split("&").filter((part) => !/^t=\d+$/.test(part)).join("&");
|
|
2810
|
+
return pathname + (query ? `?${query}` : "") + hash;
|
|
2811
|
+
}
|
|
2812
|
+
var init_url = __esm({
|
|
2813
|
+
"src/core/url.ts"() {
|
|
2814
|
+
"use strict";
|
|
2815
|
+
}
|
|
2816
|
+
});
|
|
2817
|
+
|
|
2477
2818
|
// src/core/module-graph.ts
|
|
2478
2819
|
var ModuleGraph;
|
|
2479
2820
|
var init_module_graph = __esm({
|
|
2480
2821
|
"src/core/module-graph.ts"() {
|
|
2481
2822
|
"use strict";
|
|
2823
|
+
init_url();
|
|
2482
2824
|
ModuleGraph = class {
|
|
2825
|
+
environmentName;
|
|
2483
2826
|
urlToModuleMap = /* @__PURE__ */ new Map();
|
|
2484
2827
|
idToModuleMap = /* @__PURE__ */ new Map();
|
|
2485
2828
|
fileToModulesMap = /* @__PURE__ */ new Map();
|
|
2829
|
+
constructor(environmentName = "client") {
|
|
2830
|
+
this.environmentName = environmentName;
|
|
2831
|
+
}
|
|
2486
2832
|
getModuleByUrl(url) {
|
|
2487
|
-
return this.urlToModuleMap.get(url);
|
|
2833
|
+
return this.urlToModuleMap.get(removeTimestampQuery(url));
|
|
2488
2834
|
}
|
|
2489
2835
|
getModuleById(id) {
|
|
2490
2836
|
return this.idToModuleMap.get(id);
|
|
@@ -2493,10 +2839,11 @@ var init_module_graph = __esm({
|
|
|
2493
2839
|
return this.fileToModulesMap.get(file);
|
|
2494
2840
|
}
|
|
2495
2841
|
async ensureEntryFromUrl(url) {
|
|
2496
|
-
|
|
2842
|
+
const normalizedUrl = removeTimestampQuery(url);
|
|
2843
|
+
let mod = this.urlToModuleMap.get(normalizedUrl);
|
|
2497
2844
|
if (mod) return mod;
|
|
2498
|
-
mod = this.createModule(
|
|
2499
|
-
this.urlToModuleMap.set(
|
|
2845
|
+
mod = this.createModule(normalizedUrl);
|
|
2846
|
+
this.urlToModuleMap.set(normalizedUrl, mod);
|
|
2500
2847
|
return mod;
|
|
2501
2848
|
}
|
|
2502
2849
|
createModule(url, id) {
|
|
@@ -2510,7 +2857,9 @@ var init_module_graph = __esm({
|
|
|
2510
2857
|
acceptedHmrDeps: /* @__PURE__ */ new Set(),
|
|
2511
2858
|
transformResult: null,
|
|
2512
2859
|
lastHMRTimestamp: 0,
|
|
2513
|
-
|
|
2860
|
+
invalidationVersion: 0,
|
|
2861
|
+
isSelfAccepting: false,
|
|
2862
|
+
environment: this.environmentName
|
|
2514
2863
|
};
|
|
2515
2864
|
this.idToModuleMap.set(mod.id, mod);
|
|
2516
2865
|
return mod;
|
|
@@ -2552,10 +2901,64 @@ var init_module_graph = __esm({
|
|
|
2552
2901
|
}
|
|
2553
2902
|
}
|
|
2554
2903
|
}
|
|
2904
|
+
/**
|
|
2905
|
+
* 用一次转换得到的信息原子更新 import 与 HMR accept 关系。
|
|
2906
|
+
* 依赖节点会在真正被浏览器请求前预先创建,这样入口模块先转换时也能建立完整图。
|
|
2907
|
+
*/
|
|
2908
|
+
async updateModuleInfo(mod, importedUrls, acceptedUrls, isSelfAccepting, expectedInvalidationVersion) {
|
|
2909
|
+
const importedModules = await Promise.all(
|
|
2910
|
+
[...importedUrls].map((url) => this.ensureEntryFromUrl(url))
|
|
2911
|
+
);
|
|
2912
|
+
const acceptedModules = await Promise.all(
|
|
2913
|
+
[...acceptedUrls].map((url) => this.ensureEntryFromUrl(url))
|
|
2914
|
+
);
|
|
2915
|
+
if (expectedInvalidationVersion !== void 0 && mod.invalidationVersion !== expectedInvalidationVersion) {
|
|
2916
|
+
return null;
|
|
2917
|
+
}
|
|
2918
|
+
const previousImports = new Set(mod.importedModules);
|
|
2919
|
+
for (const imported of previousImports) {
|
|
2920
|
+
imported.importers.delete(mod);
|
|
2921
|
+
}
|
|
2922
|
+
mod.importedModules.clear();
|
|
2923
|
+
mod.acceptedHmrDeps.clear();
|
|
2924
|
+
for (const imported of importedModules) {
|
|
2925
|
+
mod.importedModules.add(imported);
|
|
2926
|
+
imported.importers.add(mod);
|
|
2927
|
+
}
|
|
2928
|
+
for (const accepted of acceptedModules) {
|
|
2929
|
+
mod.acceptedHmrDeps.add(accepted);
|
|
2930
|
+
}
|
|
2931
|
+
mod.isSelfAccepting = isSelfAccepting;
|
|
2932
|
+
const pruned = /* @__PURE__ */ new Set();
|
|
2933
|
+
for (const imported of previousImports) {
|
|
2934
|
+
if (!mod.importedModules.has(imported) && imported.importers.size === 0) {
|
|
2935
|
+
pruned.add(imported);
|
|
2936
|
+
}
|
|
2937
|
+
}
|
|
2938
|
+
return pruned;
|
|
2939
|
+
}
|
|
2555
2940
|
/** 使模块的转换缓存失效 */
|
|
2556
|
-
invalidateModule(mod) {
|
|
2941
|
+
invalidateModule(mod, timestamp = Date.now()) {
|
|
2557
2942
|
mod.transformResult = null;
|
|
2558
|
-
mod.lastHMRTimestamp =
|
|
2943
|
+
mod.lastHMRTimestamp = timestamp;
|
|
2944
|
+
mod.invalidationVersion++;
|
|
2945
|
+
}
|
|
2946
|
+
/**
|
|
2947
|
+
* 仅失效到 HMR 边界:显式接受依赖的模块本身不会重执行;自接受模块需要失效,
|
|
2948
|
+
* 但不再继续影响其 importer。这样既能传播依赖时间戳,也不会隐式重复副作用。
|
|
2949
|
+
*/
|
|
2950
|
+
invalidateModuleAndImporters(mod, timestamp = Date.now(), seen = /* @__PURE__ */ new Set()) {
|
|
2951
|
+
if (seen.has(mod)) return;
|
|
2952
|
+
seen.add(mod);
|
|
2953
|
+
this.invalidateModule(mod, timestamp);
|
|
2954
|
+
for (const importer of mod.importers) {
|
|
2955
|
+
if (importer.acceptedHmrDeps.has(mod)) continue;
|
|
2956
|
+
if (importer.isSelfAccepting) {
|
|
2957
|
+
this.invalidateModule(importer, timestamp);
|
|
2958
|
+
continue;
|
|
2959
|
+
}
|
|
2960
|
+
this.invalidateModuleAndImporters(importer, timestamp, seen);
|
|
2961
|
+
}
|
|
2559
2962
|
}
|
|
2560
2963
|
/** 使所有模块缓存失效 */
|
|
2561
2964
|
invalidateAll() {
|
|
@@ -2566,34 +2969,32 @@ var init_module_graph = __esm({
|
|
|
2566
2969
|
/** 获取 HMR 传播边界 - 从变更模块向上遍历找到接受更新的边界 */
|
|
2567
2970
|
getHmrBoundaries(mod) {
|
|
2568
2971
|
const boundaries = [];
|
|
2569
|
-
const
|
|
2570
|
-
const
|
|
2571
|
-
if (
|
|
2572
|
-
|
|
2573
|
-
|
|
2574
|
-
boundaries.push({ boundary
|
|
2575
|
-
return true;
|
|
2972
|
+
const traversed = /* @__PURE__ */ new Set();
|
|
2973
|
+
const addBoundary = (boundary, acceptedVia) => {
|
|
2974
|
+
if (!boundaries.some(
|
|
2975
|
+
(item) => item.boundary === boundary && item.acceptedVia === acceptedVia
|
|
2976
|
+
)) {
|
|
2977
|
+
boundaries.push({ boundary, acceptedVia });
|
|
2576
2978
|
}
|
|
2577
|
-
|
|
2578
|
-
|
|
2979
|
+
};
|
|
2980
|
+
const propagate = (node) => {
|
|
2981
|
+
if (traversed.has(node)) return true;
|
|
2982
|
+
traversed.add(node);
|
|
2983
|
+
if (node.isSelfAccepting) {
|
|
2984
|
+
addBoundary(node, node);
|
|
2579
2985
|
return true;
|
|
2580
2986
|
}
|
|
2581
2987
|
if (node.importers.size === 0) return false;
|
|
2582
2988
|
for (const importer of node.importers) {
|
|
2583
|
-
if (
|
|
2989
|
+
if (importer.acceptedHmrDeps.has(node)) {
|
|
2990
|
+
addBoundary(importer, node);
|
|
2991
|
+
continue;
|
|
2992
|
+
}
|
|
2993
|
+
if (!propagate(importer)) return false;
|
|
2584
2994
|
}
|
|
2585
2995
|
return true;
|
|
2586
2996
|
};
|
|
2587
|
-
|
|
2588
|
-
boundaries.push({ boundary: mod, acceptedVia: mod });
|
|
2589
|
-
return boundaries;
|
|
2590
|
-
}
|
|
2591
|
-
for (const importer of mod.importers) {
|
|
2592
|
-
if (!propagate(importer, mod)) {
|
|
2593
|
-
return [];
|
|
2594
|
-
}
|
|
2595
|
-
}
|
|
2596
|
-
return boundaries;
|
|
2997
|
+
return propagate(mod) ? boundaries : [];
|
|
2597
2998
|
}
|
|
2598
2999
|
};
|
|
2599
3000
|
}
|
|
@@ -2616,12 +3017,12 @@ function createNoopHotChannel() {
|
|
|
2616
3017
|
}
|
|
2617
3018
|
};
|
|
2618
3019
|
}
|
|
2619
|
-
function createWsHotChannel(ws) {
|
|
3020
|
+
function createWsHotChannel(ws, environmentName = "client") {
|
|
2620
3021
|
const listeners = /* @__PURE__ */ new Map();
|
|
2621
3022
|
let invokeHandlers;
|
|
2622
3023
|
return {
|
|
2623
3024
|
send(payload) {
|
|
2624
|
-
ws.send(payload);
|
|
3025
|
+
ws.send({ ...payload, environment: payload.environment ?? environmentName });
|
|
2625
3026
|
},
|
|
2626
3027
|
on(event, listener) {
|
|
2627
3028
|
let set = listeners.get(event);
|
|
@@ -2633,8 +3034,8 @@ function createWsHotChannel(ws) {
|
|
|
2633
3034
|
},
|
|
2634
3035
|
listen() {
|
|
2635
3036
|
},
|
|
3037
|
+
// 多个 environment 共享底层 WebSocket server;它由 DevServer.close() 统一关闭。
|
|
2636
3038
|
close() {
|
|
2637
|
-
ws.close();
|
|
2638
3039
|
},
|
|
2639
3040
|
setInvokeHandler(handlers) {
|
|
2640
3041
|
invokeHandlers = handlers;
|
|
@@ -2663,7 +3064,7 @@ function resolveEnvironmentPlugins(environment, plugins) {
|
|
|
2663
3064
|
}
|
|
2664
3065
|
});
|
|
2665
3066
|
}
|
|
2666
|
-
var
|
|
3067
|
+
var debug3, NastiEnvironment;
|
|
2667
3068
|
var init_environment = __esm({
|
|
2668
3069
|
"src/core/environment.ts"() {
|
|
2669
3070
|
"use strict";
|
|
@@ -2672,7 +3073,7 @@ var init_environment = __esm({
|
|
|
2672
3073
|
init_hot_channel();
|
|
2673
3074
|
init_debug();
|
|
2674
3075
|
init_plugin_api();
|
|
2675
|
-
|
|
3076
|
+
debug3 = createDebugger("nasti:environment");
|
|
2676
3077
|
NastiEnvironment = class {
|
|
2677
3078
|
name;
|
|
2678
3079
|
consumer;
|
|
@@ -2689,6 +3090,10 @@ var init_environment = __esm({
|
|
|
2689
3090
|
moduleGraph;
|
|
2690
3091
|
candidatePlugins;
|
|
2691
3092
|
pluginApi;
|
|
3093
|
+
buildMetadata = {};
|
|
3094
|
+
cssModules = /* @__PURE__ */ new Map();
|
|
3095
|
+
assetModules = /* @__PURE__ */ new Map();
|
|
3096
|
+
transformRequestHandler;
|
|
2692
3097
|
initialized = false;
|
|
2693
3098
|
constructor(name, config, init = {}) {
|
|
2694
3099
|
const options = config.environments[name];
|
|
@@ -2703,7 +3108,7 @@ var init_environment = __esm({
|
|
|
2703
3108
|
this.config = config;
|
|
2704
3109
|
this.options = options;
|
|
2705
3110
|
this.hot = init.hot ?? createNoopHotChannel();
|
|
2706
|
-
this.moduleGraph = new ModuleGraph();
|
|
3111
|
+
this.moduleGraph = new ModuleGraph(name);
|
|
2707
3112
|
this.candidatePlugins = init.plugins ?? config.plugins;
|
|
2708
3113
|
this.pluginApi = init.pluginApi ?? getPluginApi(config);
|
|
2709
3114
|
}
|
|
@@ -2733,9 +3138,9 @@ var init_environment = __esm({
|
|
|
2733
3138
|
);
|
|
2734
3139
|
}
|
|
2735
3140
|
this.driver = claimed[0].driver;
|
|
2736
|
-
|
|
3141
|
+
debug3?.(`env "${this.name}" uses driver "${this.driver.name}"`);
|
|
2737
3142
|
}
|
|
2738
|
-
|
|
3143
|
+
debug3?.(`env "${this.name}" initialized (${this.plugins.length} plugins)`);
|
|
2739
3144
|
}
|
|
2740
3145
|
getDriverContext() {
|
|
2741
3146
|
return {
|
|
@@ -2745,6 +3150,53 @@ var init_environment = __esm({
|
|
|
2745
3150
|
logger: this.config.logger
|
|
2746
3151
|
};
|
|
2747
3152
|
}
|
|
3153
|
+
configureDevPipeline(transformRequest2) {
|
|
3154
|
+
this.transformRequestHandler = transformRequest2;
|
|
3155
|
+
}
|
|
3156
|
+
async transformRequest(url) {
|
|
3157
|
+
if (!this.transformRequestHandler) {
|
|
3158
|
+
throw new Error(
|
|
3159
|
+
`[nasti] environment "${this.name}" does not have an initialized dev transform pipeline`
|
|
3160
|
+
);
|
|
3161
|
+
}
|
|
3162
|
+
return this.transformRequestHandler(url);
|
|
3163
|
+
}
|
|
3164
|
+
setCssModule(module) {
|
|
3165
|
+
this.cssModules.set(module.id, { ...module });
|
|
3166
|
+
}
|
|
3167
|
+
getCssModule(id) {
|
|
3168
|
+
const module = this.cssModules.get(id);
|
|
3169
|
+
return module ? { ...module } : void 0;
|
|
3170
|
+
}
|
|
3171
|
+
getCssModules() {
|
|
3172
|
+
return Object.freeze(
|
|
3173
|
+
Object.fromEntries(
|
|
3174
|
+
[...this.cssModules].map(([id, module]) => [id, { ...module }])
|
|
3175
|
+
)
|
|
3176
|
+
);
|
|
3177
|
+
}
|
|
3178
|
+
setAssetModule(id, fileName) {
|
|
3179
|
+
this.assetModules.set(id, fileName);
|
|
3180
|
+
}
|
|
3181
|
+
getAssetModules() {
|
|
3182
|
+
return Object.freeze(Object.fromEntries(this.assetModules));
|
|
3183
|
+
}
|
|
3184
|
+
setBuildMetadata(metadata) {
|
|
3185
|
+
const { entries: currentEntries, ...currentMetadata } = this.buildMetadata;
|
|
3186
|
+
const { entries, ...nextMetadata } = metadata;
|
|
3187
|
+
this.buildMetadata = {
|
|
3188
|
+
...currentMetadata,
|
|
3189
|
+
...nextMetadata,
|
|
3190
|
+
...currentEntries || entries ? { entries: { ...currentEntries, ...entries } } : {}
|
|
3191
|
+
};
|
|
3192
|
+
}
|
|
3193
|
+
getBuildMetadata() {
|
|
3194
|
+
const { entries, ...metadata } = this.buildMetadata;
|
|
3195
|
+
return {
|
|
3196
|
+
...metadata,
|
|
3197
|
+
...entries ? { entries: { ...entries } } : {}
|
|
3198
|
+
};
|
|
3199
|
+
}
|
|
2748
3200
|
async close() {
|
|
2749
3201
|
try {
|
|
2750
3202
|
await this.driver?.close?.(this.getDriverContext());
|
|
@@ -2841,7 +3293,7 @@ async function tryNativeReporterPlugin(config, logger) {
|
|
|
2841
3293
|
logInfo: (msg) => logger.info(msg)
|
|
2842
3294
|
});
|
|
2843
3295
|
} catch (err) {
|
|
2844
|
-
|
|
3296
|
+
debug4?.(`native viteReporterPlugin unavailable, falling back to JS table: ${err}`);
|
|
2845
3297
|
return null;
|
|
2846
3298
|
}
|
|
2847
3299
|
}
|
|
@@ -2896,12 +3348,12 @@ function warnLargeChunks(output, config, logger) {
|
|
|
2896
3348
|
)
|
|
2897
3349
|
);
|
|
2898
3350
|
}
|
|
2899
|
-
var
|
|
3351
|
+
var debug4, numberFormatter;
|
|
2900
3352
|
var init_reporter = __esm({
|
|
2901
3353
|
"src/build/reporter.ts"() {
|
|
2902
3354
|
"use strict";
|
|
2903
3355
|
init_debug();
|
|
2904
|
-
|
|
3356
|
+
debug4 = createDebugger("nasti:reporter");
|
|
2905
3357
|
numberFormatter = new Intl.NumberFormat("en", {
|
|
2906
3358
|
maximumFractionDigits: 2,
|
|
2907
3359
|
minimumFractionDigits: 2
|
|
@@ -2909,6 +3361,155 @@ var init_reporter = __esm({
|
|
|
2909
3361
|
}
|
|
2910
3362
|
});
|
|
2911
3363
|
|
|
3364
|
+
// src/core/build-app-context.ts
|
|
3365
|
+
import fs6 from "fs";
|
|
3366
|
+
import path9 from "path";
|
|
3367
|
+
function createBuildAppContext(config, results) {
|
|
3368
|
+
const output = [];
|
|
3369
|
+
const emitted = /* @__PURE__ */ new Set();
|
|
3370
|
+
const outDir = path9.resolve(config.root, config.build.outDir);
|
|
3371
|
+
let environmentArtifacts;
|
|
3372
|
+
return {
|
|
3373
|
+
config,
|
|
3374
|
+
results,
|
|
3375
|
+
get output() {
|
|
3376
|
+
return Object.freeze([...output]);
|
|
3377
|
+
},
|
|
3378
|
+
getResult(environmentName) {
|
|
3379
|
+
return results[environmentName];
|
|
3380
|
+
},
|
|
3381
|
+
getArtifact(environmentName, fileName) {
|
|
3382
|
+
const normalized = normalizeEnvironmentFileName(fileName);
|
|
3383
|
+
return results[environmentName]?.output.find(
|
|
3384
|
+
(artifact) => normalizeEnvironmentFileName(artifact.fileName) === normalized
|
|
3385
|
+
);
|
|
3386
|
+
},
|
|
3387
|
+
getEntry(environmentName, entryName) {
|
|
3388
|
+
const result = results[environmentName];
|
|
3389
|
+
const fileName = result?.entries?.[entryName];
|
|
3390
|
+
if (!fileName) return void 0;
|
|
3391
|
+
return result.output.find(
|
|
3392
|
+
(artifact) => normalizeEnvironmentFileName(artifact.fileName) === normalizeEnvironmentFileName(fileName)
|
|
3393
|
+
);
|
|
3394
|
+
},
|
|
3395
|
+
getManifest(environmentName) {
|
|
3396
|
+
return results[environmentName]?.manifest;
|
|
3397
|
+
},
|
|
3398
|
+
getChunk(environmentName, fileName) {
|
|
3399
|
+
const normalized = normalizeEnvironmentFileName(fileName);
|
|
3400
|
+
return results[environmentName]?.chunks?.[normalized];
|
|
3401
|
+
},
|
|
3402
|
+
getCss(environmentName) {
|
|
3403
|
+
return results[environmentName]?.css;
|
|
3404
|
+
},
|
|
3405
|
+
getSourceMap(environmentName, fileName) {
|
|
3406
|
+
const normalized = normalizeEnvironmentFileName(fileName);
|
|
3407
|
+
return results[environmentName]?.sourceMaps?.[normalized];
|
|
3408
|
+
},
|
|
3409
|
+
resolvePublicPath(environmentName, fileName) {
|
|
3410
|
+
const result = results[environmentName];
|
|
3411
|
+
if (!result) return void 0;
|
|
3412
|
+
const normalized = normalizeEnvironmentFileName(fileName);
|
|
3413
|
+
const base = result.publicPath ?? config.base;
|
|
3414
|
+
return joinPublicPath(base, normalized);
|
|
3415
|
+
},
|
|
3416
|
+
emitFile(file) {
|
|
3417
|
+
const fileName = normalizeAppFileName(file.fileName);
|
|
3418
|
+
const collisionKey = artifactCollisionKey(fileName);
|
|
3419
|
+
if (emitted.has(collisionKey)) {
|
|
3420
|
+
throw new Error(`[nasti] app artifact already emitted: ${fileName}`);
|
|
3421
|
+
}
|
|
3422
|
+
environmentArtifacts ??= collectEnvironmentArtifacts(config, results, outDir);
|
|
3423
|
+
if (environmentArtifacts.has(collisionKey)) {
|
|
3424
|
+
throw new Error(`[nasti] app artifact conflicts with environment output: ${fileName}`);
|
|
3425
|
+
}
|
|
3426
|
+
const target = path9.resolve(outDir, ...fileName.split("/"));
|
|
3427
|
+
const relative = path9.relative(outDir, target);
|
|
3428
|
+
if (relative.startsWith("..") || path9.isAbsolute(relative)) {
|
|
3429
|
+
throw new Error(`[nasti] app artifact must stay inside build.outDir: ${file.fileName}`);
|
|
3430
|
+
}
|
|
3431
|
+
assertNoSymlinkComponents(outDir, fileName);
|
|
3432
|
+
fs6.mkdirSync(path9.dirname(target), { recursive: true });
|
|
3433
|
+
fs6.writeFileSync(target, file.source);
|
|
3434
|
+
const artifact = {
|
|
3435
|
+
...file,
|
|
3436
|
+
fileName,
|
|
3437
|
+
type: "asset"
|
|
3438
|
+
};
|
|
3439
|
+
emitted.add(collisionKey);
|
|
3440
|
+
output.push(artifact);
|
|
3441
|
+
return fileName;
|
|
3442
|
+
}
|
|
3443
|
+
};
|
|
3444
|
+
}
|
|
3445
|
+
function joinPublicPath(base, fileName) {
|
|
3446
|
+
return `${base.endsWith("/") ? base : `${base}/`}${fileName.replace(/^\//, "")}`;
|
|
3447
|
+
}
|
|
3448
|
+
function normalizeEnvironmentFileName(fileName) {
|
|
3449
|
+
return path9.posix.normalize(fileName.replace(/\\/g, "/").replace(/^\.\//, ""));
|
|
3450
|
+
}
|
|
3451
|
+
function isInvalidEnvironmentFileName(fileName) {
|
|
3452
|
+
return !fileName || fileName === "." || fileName === ".." || fileName.startsWith("../") || path9.posix.isAbsolute(fileName) || /^[A-Za-z]:\//.test(fileName);
|
|
3453
|
+
}
|
|
3454
|
+
function normalizeAppFileName(fileName) {
|
|
3455
|
+
const normalized = normalizeEnvironmentFileName(fileName);
|
|
3456
|
+
if (isInvalidEnvironmentFileName(normalized)) {
|
|
3457
|
+
throw new Error(`[nasti] invalid app artifact fileName: ${fileName}`);
|
|
3458
|
+
}
|
|
3459
|
+
return normalized;
|
|
3460
|
+
}
|
|
3461
|
+
function artifactCollisionKey(fileName) {
|
|
3462
|
+
return normalizeEnvironmentFileName(fileName).toLowerCase();
|
|
3463
|
+
}
|
|
3464
|
+
function collectEnvironmentArtifacts(config, results, appOutDir) {
|
|
3465
|
+
const occupied = /* @__PURE__ */ new Set();
|
|
3466
|
+
for (const [environmentName, result] of Object.entries(results)) {
|
|
3467
|
+
const environment = config.environments[environmentName];
|
|
3468
|
+
if (!environment) continue;
|
|
3469
|
+
const environmentOutDir = path9.resolve(config.root, environment.build.outDir);
|
|
3470
|
+
for (const artifact of result.output) {
|
|
3471
|
+
const artifactPath = path9.resolve(
|
|
3472
|
+
environmentOutDir,
|
|
3473
|
+
...normalizeEnvironmentFileName(artifact.fileName).split("/")
|
|
3474
|
+
);
|
|
3475
|
+
const relative = path9.relative(appOutDir, artifactPath);
|
|
3476
|
+
if (!relative.startsWith("..") && !path9.isAbsolute(relative)) {
|
|
3477
|
+
occupied.add(artifactCollisionKey(relative));
|
|
3478
|
+
}
|
|
3479
|
+
}
|
|
3480
|
+
}
|
|
3481
|
+
return occupied;
|
|
3482
|
+
}
|
|
3483
|
+
function assertNoSymlinkComponents(outDir, fileName) {
|
|
3484
|
+
let current = outDir;
|
|
3485
|
+
for (const segment of fileName.split("/")) {
|
|
3486
|
+
current = path9.join(current, segment);
|
|
3487
|
+
let stats;
|
|
3488
|
+
try {
|
|
3489
|
+
stats = fs6.lstatSync(current);
|
|
3490
|
+
} catch (error) {
|
|
3491
|
+
if (error.code === "ENOENT") continue;
|
|
3492
|
+
throw error;
|
|
3493
|
+
}
|
|
3494
|
+
if (stats.isSymbolicLink()) {
|
|
3495
|
+
throw new Error(`[nasti] app artifact path cannot traverse a symlink: ${fileName}`);
|
|
3496
|
+
}
|
|
3497
|
+
}
|
|
3498
|
+
}
|
|
3499
|
+
function inferEnvironmentEntries(output) {
|
|
3500
|
+
const entries = {};
|
|
3501
|
+
for (const artifact of output) {
|
|
3502
|
+
if (artifact.type !== "chunk" || !artifact.isEntry || !artifact.name) continue;
|
|
3503
|
+
entries[artifact.name] = normalizeEnvironmentFileName(artifact.fileName);
|
|
3504
|
+
}
|
|
3505
|
+
return Object.keys(entries).length > 0 ? entries : void 0;
|
|
3506
|
+
}
|
|
3507
|
+
var init_build_app_context = __esm({
|
|
3508
|
+
"src/core/build-app-context.ts"() {
|
|
3509
|
+
"use strict";
|
|
3510
|
+
}
|
|
3511
|
+
});
|
|
3512
|
+
|
|
2912
3513
|
// src/build/index.ts
|
|
2913
3514
|
var build_exports = {};
|
|
2914
3515
|
__export(build_exports, {
|
|
@@ -2918,8 +3519,8 @@ __export(build_exports, {
|
|
|
2918
3519
|
resolveClientEntries: () => resolveClientEntries,
|
|
2919
3520
|
toRolldownPlugins: () => toRolldownPlugins
|
|
2920
3521
|
});
|
|
2921
|
-
import
|
|
2922
|
-
import
|
|
3522
|
+
import path10 from "path";
|
|
3523
|
+
import fs7 from "fs";
|
|
2923
3524
|
import { builtinModules } from "module";
|
|
2924
3525
|
import { rolldown } from "rolldown";
|
|
2925
3526
|
import pc4 from "picocolors";
|
|
@@ -2927,9 +3528,14 @@ function getRolldownOptions(environment, entryPoints, rolldownPlugins) {
|
|
|
2927
3528
|
const config = environment.config;
|
|
2928
3529
|
const envOptions = environment.options;
|
|
2929
3530
|
const isServer = environment.consumer === "server";
|
|
2930
|
-
const outDir =
|
|
3531
|
+
const outDir = path10.resolve(config.root, envOptions.build.outDir);
|
|
2931
3532
|
const assetsDir = envOptions.build.assetsDir;
|
|
2932
|
-
const {
|
|
3533
|
+
const {
|
|
3534
|
+
output: userOutput,
|
|
3535
|
+
transform: userTransform,
|
|
3536
|
+
resolve: userResolve,
|
|
3537
|
+
...restInputOptions
|
|
3538
|
+
} = envOptions.build.rolldownOptions;
|
|
2933
3539
|
const vueDefine = config.framework === "vue" ? {
|
|
2934
3540
|
__VUE_OPTIONS_API__: "true",
|
|
2935
3541
|
__VUE_PROD_DEVTOOLS__: "false",
|
|
@@ -2941,27 +3547,34 @@ function getRolldownOptions(environment, entryPoints, rolldownPlugins) {
|
|
|
2941
3547
|
const inputOptions = {
|
|
2942
3548
|
...restInputOptions,
|
|
2943
3549
|
input: entryPoints,
|
|
2944
|
-
transform: {
|
|
3550
|
+
transform: {
|
|
3551
|
+
...userTransform,
|
|
3552
|
+
target: userTransform?.target ?? envOptions.build.target,
|
|
3553
|
+
define: mergedDefine
|
|
3554
|
+
},
|
|
2945
3555
|
plugins: rolldownPlugins,
|
|
3556
|
+
// client/server consumer 都必须使用当前环境的 conditions/mainFields;Lynx
|
|
3557
|
+
// BG/MT 通常同为 client consumer,但仍可能声明不同的运行时条件。
|
|
3558
|
+
resolve: {
|
|
3559
|
+
...userResolve ?? {},
|
|
3560
|
+
// Environment API 是条件解析的唯一高层入口,优先于继承来的底层选项。
|
|
3561
|
+
conditionNames: envOptions.resolve.conditions,
|
|
3562
|
+
mainFields: envOptions.resolve.mainFields
|
|
3563
|
+
},
|
|
2946
3564
|
...isServer ? {
|
|
2947
3565
|
platform: restInputOptions.platform ?? "node",
|
|
2948
|
-
resolve: {
|
|
2949
|
-
conditionNames: envOptions.resolve.conditions,
|
|
2950
|
-
mainFields: envOptions.resolve.mainFields,
|
|
2951
|
-
...restInputOptions.resolve
|
|
2952
|
-
},
|
|
2953
3566
|
// server 产物:node 内建恒外部化;bare specifier 默认外部化
|
|
2954
3567
|
//(同 Vite ssr.external 默认 —— 依赖由 node_modules 运行时解析),
|
|
2955
3568
|
// 相对/绝对/虚拟模块照常打包。需要内联依赖时经 rolldownOptions.external 覆盖。
|
|
2956
3569
|
external: restInputOptions.external ?? ((id) => {
|
|
2957
3570
|
if (NODE_BUILTINS.has(id)) return true;
|
|
2958
|
-
return !id.startsWith(".") && !
|
|
3571
|
+
return !id.startsWith(".") && !path10.isAbsolute(id) && !id.startsWith("\0");
|
|
2959
3572
|
})
|
|
2960
3573
|
} : {}
|
|
2961
3574
|
};
|
|
2962
3575
|
const outputOptions = isServer ? {
|
|
2963
3576
|
format: "esm",
|
|
2964
|
-
sourcemap:
|
|
3577
|
+
sourcemap: envOptions.build.sourcemap,
|
|
2965
3578
|
minify: !!envOptions.build.minify,
|
|
2966
3579
|
entryFileNames: "[name].js",
|
|
2967
3580
|
chunkFileNames: "chunks/[name]-[hash].js",
|
|
@@ -2970,7 +3583,7 @@ function getRolldownOptions(environment, entryPoints, rolldownPlugins) {
|
|
|
2970
3583
|
dir: outDir
|
|
2971
3584
|
} : {
|
|
2972
3585
|
format: "esm",
|
|
2973
|
-
sourcemap:
|
|
3586
|
+
sourcemap: envOptions.build.sourcemap,
|
|
2974
3587
|
minify: !!envOptions.build.minify,
|
|
2975
3588
|
entryFileNames: `${assetsDir}/[name].[hash].js`,
|
|
2976
3589
|
chunkFileNames: `${assetsDir}/[name].[hash].js`,
|
|
@@ -2982,27 +3595,177 @@ function getRolldownOptions(environment, entryPoints, rolldownPlugins) {
|
|
|
2982
3595
|
};
|
|
2983
3596
|
return { inputOptions, outputOptions, outDir };
|
|
2984
3597
|
}
|
|
2985
|
-
function toRolldownPlugins(plugins) {
|
|
3598
|
+
function toRolldownPlugins(plugins, environment) {
|
|
3599
|
+
const wrap = (hook) => {
|
|
3600
|
+
if (!hook) return hook;
|
|
3601
|
+
return function(...args) {
|
|
3602
|
+
return hook.apply(attachEnvironment(this, environment), args);
|
|
3603
|
+
};
|
|
3604
|
+
};
|
|
2986
3605
|
return plugins.map((p) => ({
|
|
2987
3606
|
name: p.name,
|
|
2988
|
-
resolveId: p.resolveId,
|
|
2989
|
-
load: p.load,
|
|
2990
|
-
transform: p.transform,
|
|
2991
|
-
buildStart: p.buildStart,
|
|
2992
|
-
buildEnd: p.buildEnd,
|
|
3607
|
+
resolveId: wrap(p.resolveId),
|
|
3608
|
+
load: wrap(p.load),
|
|
3609
|
+
transform: wrap(p.transform),
|
|
3610
|
+
buildStart: wrap(p.buildStart),
|
|
3611
|
+
buildEnd: wrap(p.buildEnd),
|
|
2993
3612
|
// closeBundle 在 bundle.close() 时触发 —— PWA manifest/SW 等终态产物依赖
|
|
2994
|
-
closeBundle: p.closeBundle,
|
|
2995
|
-
renderChunk: p.renderChunk,
|
|
2996
|
-
augmentChunkHash: p.augmentChunkHash,
|
|
2997
|
-
generateBundle: p.generateBundle
|
|
3613
|
+
closeBundle: wrap(p.closeBundle),
|
|
3614
|
+
renderChunk: wrap(p.renderChunk),
|
|
3615
|
+
augmentChunkHash: wrap(p.augmentChunkHash),
|
|
3616
|
+
generateBundle: wrap(p.generateBundle)
|
|
2998
3617
|
}));
|
|
2999
3618
|
}
|
|
3619
|
+
function attachEnvironment(context, environment) {
|
|
3620
|
+
if (context?.environment === environment) return context;
|
|
3621
|
+
try {
|
|
3622
|
+
Object.defineProperty(context, "environment", {
|
|
3623
|
+
configurable: true,
|
|
3624
|
+
enumerable: false,
|
|
3625
|
+
writable: false,
|
|
3626
|
+
value: environment
|
|
3627
|
+
});
|
|
3628
|
+
return context;
|
|
3629
|
+
} catch {
|
|
3630
|
+
return new Proxy(context, {
|
|
3631
|
+
get(target, property) {
|
|
3632
|
+
if (property === "environment") return environment;
|
|
3633
|
+
const value = Reflect.get(target, property, target);
|
|
3634
|
+
return typeof value === "function" ? value.bind(target) : value;
|
|
3635
|
+
},
|
|
3636
|
+
set(target, property, value) {
|
|
3637
|
+
return Reflect.set(target, property, value, target);
|
|
3638
|
+
}
|
|
3639
|
+
});
|
|
3640
|
+
}
|
|
3641
|
+
}
|
|
3642
|
+
function finalizeEnvironmentResult(environment, result) {
|
|
3643
|
+
const metadata = environment.getBuildMetadata();
|
|
3644
|
+
const inferredEntries = inferEnvironmentEntries(result.output);
|
|
3645
|
+
const entries = {
|
|
3646
|
+
...inferredEntries,
|
|
3647
|
+
...metadata.entries,
|
|
3648
|
+
...result.entries
|
|
3649
|
+
};
|
|
3650
|
+
const normalizedEntries = Object.fromEntries(
|
|
3651
|
+
Object.entries(entries).map(([name, fileName]) => {
|
|
3652
|
+
const normalized = normalizeEnvironmentFileName(fileName);
|
|
3653
|
+
if (isInvalidEnvironmentFileName(normalized)) {
|
|
3654
|
+
throw new Error(
|
|
3655
|
+
`[nasti] environment "${environment.name}" returned invalid entry "${name}": ${fileName}`
|
|
3656
|
+
);
|
|
3657
|
+
}
|
|
3658
|
+
return [name, normalized];
|
|
3659
|
+
})
|
|
3660
|
+
);
|
|
3661
|
+
const inferredMetadata = inferOutputMetadata(environment, result.output);
|
|
3662
|
+
return {
|
|
3663
|
+
publicPath: environment.config.base,
|
|
3664
|
+
...inferredMetadata,
|
|
3665
|
+
...metadata,
|
|
3666
|
+
...result,
|
|
3667
|
+
output: result.output,
|
|
3668
|
+
chunks: {
|
|
3669
|
+
...inferredMetadata.chunks,
|
|
3670
|
+
...metadata.chunks,
|
|
3671
|
+
...result.chunks
|
|
3672
|
+
},
|
|
3673
|
+
assets: {
|
|
3674
|
+
...inferredMetadata.assets,
|
|
3675
|
+
...metadata.assets,
|
|
3676
|
+
...result.assets
|
|
3677
|
+
},
|
|
3678
|
+
sourceMaps: {
|
|
3679
|
+
...inferredMetadata.sourceMaps,
|
|
3680
|
+
...metadata.sourceMaps,
|
|
3681
|
+
...result.sourceMaps
|
|
3682
|
+
},
|
|
3683
|
+
...Object.keys(normalizedEntries).length > 0 ? { entries: normalizedEntries } : {}
|
|
3684
|
+
};
|
|
3685
|
+
}
|
|
3686
|
+
function inferOutputMetadata(environment, output) {
|
|
3687
|
+
const chunks = {};
|
|
3688
|
+
const assets = {};
|
|
3689
|
+
const sourceMaps = {};
|
|
3690
|
+
const cssChunks = environment.getBuildMetadata().css?.chunks ?? {};
|
|
3691
|
+
const assetModules = environment.getAssetModules();
|
|
3692
|
+
const publicPath = environment.config.base;
|
|
3693
|
+
for (const artifact of output) {
|
|
3694
|
+
const fileName = normalizeEnvironmentFileName(artifact.fileName);
|
|
3695
|
+
if (artifact.map != null) sourceMaps[fileName] = artifact.map;
|
|
3696
|
+
if (artifact.type === "chunk") {
|
|
3697
|
+
const moduleIds = [...artifact.moduleIds ?? []];
|
|
3698
|
+
chunks[fileName] = {
|
|
3699
|
+
fileName,
|
|
3700
|
+
name: artifact.name ?? fileName,
|
|
3701
|
+
isEntry: !!artifact.isEntry,
|
|
3702
|
+
isDynamicEntry: !!artifact.isDynamicEntry,
|
|
3703
|
+
imports: [...artifact.imports ?? []],
|
|
3704
|
+
dynamicImports: [...artifact.dynamicImports ?? []],
|
|
3705
|
+
moduleIds,
|
|
3706
|
+
css: [...cssChunks[fileName]?.cssFileNames ?? []],
|
|
3707
|
+
assets: [
|
|
3708
|
+
...new Set(
|
|
3709
|
+
moduleIds.map((id) => assetModules[id]).filter((asset) => !!asset)
|
|
3710
|
+
)
|
|
3711
|
+
]
|
|
3712
|
+
};
|
|
3713
|
+
} else if (artifact.type === "asset") {
|
|
3714
|
+
assets[fileName] = {
|
|
3715
|
+
fileName,
|
|
3716
|
+
names: [...artifact.names ?? (artifact.name ? [artifact.name] : [])],
|
|
3717
|
+
publicPath: joinPublicPath(publicPath, fileName)
|
|
3718
|
+
};
|
|
3719
|
+
}
|
|
3720
|
+
}
|
|
3721
|
+
return { chunks, assets, sourceMaps };
|
|
3722
|
+
}
|
|
3723
|
+
function prepareBuildOutputDirectories(config, buildableNames) {
|
|
3724
|
+
const directories = /* @__PURE__ */ new Set();
|
|
3725
|
+
const protectedPaths = /* @__PURE__ */ new Set();
|
|
3726
|
+
const clientIsBuilt = buildableNames.includes("client");
|
|
3727
|
+
if (!clientIsBuilt && config.build.emptyOutDir) {
|
|
3728
|
+
directories.add(path10.resolve(config.root, config.build.outDir));
|
|
3729
|
+
}
|
|
3730
|
+
for (const name of buildableNames) {
|
|
3731
|
+
const environment = config.environments[name];
|
|
3732
|
+
const outDir = path10.resolve(config.root, environment.build.outDir);
|
|
3733
|
+
if (!environment.build.emptyOutDir) {
|
|
3734
|
+
protectedPaths.add(outDir);
|
|
3735
|
+
continue;
|
|
3736
|
+
}
|
|
3737
|
+
if (!environment.driver) directories.add(outDir);
|
|
3738
|
+
}
|
|
3739
|
+
const containsPath = (parent, child) => {
|
|
3740
|
+
const relative = path10.relative(parent, child);
|
|
3741
|
+
return relative === "" || !relative.startsWith("..") && !path10.isAbsolute(relative);
|
|
3742
|
+
};
|
|
3743
|
+
const roots = [...directories].filter(
|
|
3744
|
+
(directory) => ![...protectedPaths].some((protectedPath) => containsPath(directory, protectedPath))
|
|
3745
|
+
).sort((a, b) => a.length - b.length).filter(
|
|
3746
|
+
(directory, index2, all) => !all.slice(0, index2).some((parent) => containsPath(parent, directory))
|
|
3747
|
+
);
|
|
3748
|
+
for (const directory of roots) {
|
|
3749
|
+
if (fs7.existsSync(directory)) fs7.rmSync(directory, { recursive: true, force: true });
|
|
3750
|
+
}
|
|
3751
|
+
}
|
|
3752
|
+
function assertDriverBuildResult(environment, result) {
|
|
3753
|
+
const output = result != null && typeof result === "object" ? result.output : void 0;
|
|
3754
|
+
const hasValidOutput = Array.isArray(output) && output.every(
|
|
3755
|
+
(artifact) => artifact != null && typeof artifact === "object" && typeof artifact.fileName === "string" && typeof artifact.type === "string"
|
|
3756
|
+
);
|
|
3757
|
+
if (!hasValidOutput) {
|
|
3758
|
+
throw new Error(
|
|
3759
|
+
`[nasti] environment "${environment.name}" driver "${environment.driver?.name}" returned an invalid build result; expected { output: EnvironmentBuildOutput[] }`
|
|
3760
|
+
);
|
|
3761
|
+
}
|
|
3762
|
+
}
|
|
3000
3763
|
function resolveClientEntries(config, html) {
|
|
3001
3764
|
const configuredEntries = config.environments.client?.entry ?? [];
|
|
3002
3765
|
if (configuredEntries.length > 0) return configuredEntries;
|
|
3003
3766
|
const entryPoints = [];
|
|
3004
3767
|
const htmlFile = config.environments.client?.html;
|
|
3005
|
-
const htmlDir = htmlFile ?
|
|
3768
|
+
const htmlDir = htmlFile ? path10.dirname(htmlFile) : config.root;
|
|
3006
3769
|
if (html) {
|
|
3007
3770
|
const scriptMatches = html.matchAll(/<script[^>]+src=["']([^"']+)["'][^>]*>/gi);
|
|
3008
3771
|
for (const match of scriptMatches) {
|
|
@@ -3010,7 +3773,7 @@ function resolveClientEntries(config, html) {
|
|
|
3010
3773
|
if (src && !src.startsWith("http")) {
|
|
3011
3774
|
const cleanSrc = src.split(/[?#]/, 1)[0];
|
|
3012
3775
|
entryPoints.push(
|
|
3013
|
-
cleanSrc.startsWith("/") ?
|
|
3776
|
+
cleanSrc.startsWith("/") ? path10.resolve(config.root, cleanSrc.replace(/^\//, "")) : path10.resolve(htmlDir, cleanSrc)
|
|
3014
3777
|
);
|
|
3015
3778
|
}
|
|
3016
3779
|
}
|
|
@@ -3018,8 +3781,8 @@ function resolveClientEntries(config, html) {
|
|
|
3018
3781
|
if (entryPoints.length === 0) {
|
|
3019
3782
|
const fallbackEntries = ["src/main.ts", "src/main.tsx", "src/main.js", "src/index.ts", "src/index.tsx", "src/index.js"];
|
|
3020
3783
|
for (const entry of fallbackEntries) {
|
|
3021
|
-
const fullPath =
|
|
3022
|
-
if (
|
|
3784
|
+
const fullPath = path10.resolve(config.root, entry);
|
|
3785
|
+
if (fs7.existsSync(fullPath)) {
|
|
3023
3786
|
entryPoints.push(fullPath);
|
|
3024
3787
|
break;
|
|
3025
3788
|
}
|
|
@@ -3034,6 +3797,7 @@ function createOxcTransformPlugin(config, environment) {
|
|
|
3034
3797
|
if (!shouldTransform(id)) return null;
|
|
3035
3798
|
const result = transformCode(id, code, {
|
|
3036
3799
|
sourcemap: !!environment.options.build.sourcemap,
|
|
3800
|
+
target: environment.options.build.target,
|
|
3037
3801
|
jsxRuntime: "automatic",
|
|
3038
3802
|
jsxImportSource: config.framework === "vue" ? "vue" : "react"
|
|
3039
3803
|
});
|
|
@@ -3047,16 +3811,20 @@ async function build(inlineConfig = {}) {
|
|
|
3047
3811
|
const startTime = performance.now();
|
|
3048
3812
|
logger.info(
|
|
3049
3813
|
pc4.cyan(`
|
|
3050
|
-
nasti v${"2.
|
|
3051
|
-
);
|
|
3052
|
-
debug4?.(`root: ${config.root}`);
|
|
3053
|
-
const buildableNames = Object.keys(config.environments).filter(
|
|
3054
|
-
(name) => name === "client" || config.environments[name].entry.length > 0 || !!config.environments[name].driver
|
|
3814
|
+
nasti v${"2.4.1"} `) + pc4.green(`building for ${config.mode}...`)
|
|
3055
3815
|
);
|
|
3816
|
+
debug5?.(`root: ${config.root}`);
|
|
3817
|
+
const buildableNames = Object.keys(config.environments).filter((name) => {
|
|
3818
|
+
const environment = config.environments[name];
|
|
3819
|
+
if (!environment.buildEnabled) return false;
|
|
3820
|
+
return name === "client" || environment.entry.length > 0 || !!environment.driver;
|
|
3821
|
+
});
|
|
3056
3822
|
buildableNames.sort((a, b) => a === "client" ? -1 : b === "client" ? 1 : 0);
|
|
3823
|
+
prepareBuildOutputDirectories(config, buildableNames);
|
|
3057
3824
|
const environments = {};
|
|
3058
3825
|
const environmentResults = {};
|
|
3059
3826
|
const initializedEnvironments = [];
|
|
3827
|
+
const buildAppContext = createBuildAppContext(config, environmentResults);
|
|
3060
3828
|
let clientOutput = [];
|
|
3061
3829
|
let buildFailed = false;
|
|
3062
3830
|
try {
|
|
@@ -3067,12 +3835,12 @@ nasti v${"2.3.1"} `) + pc4.green(`building for ${config.mode}...`)
|
|
|
3067
3835
|
environmentResults[name] = built.result;
|
|
3068
3836
|
if (name === "client") clientOutput = built.result.output;
|
|
3069
3837
|
if (buildableNames.length > 1) {
|
|
3070
|
-
|
|
3838
|
+
debug5?.(`environment "${name}" built (${built.result.output.length} files)`);
|
|
3071
3839
|
}
|
|
3072
3840
|
}
|
|
3073
3841
|
const pluginApi = getPluginApi(config);
|
|
3074
3842
|
for (const plugin of config.plugins) {
|
|
3075
|
-
await plugin.afterBuildApp?.(environmentResults, pluginApi);
|
|
3843
|
+
await plugin.afterBuildApp?.(environmentResults, pluginApi, buildAppContext);
|
|
3076
3844
|
}
|
|
3077
3845
|
} catch (error) {
|
|
3078
3846
|
buildFailed = true;
|
|
@@ -3099,22 +3867,31 @@ nasti v${"2.3.1"} `) + pc4.green(`building for ${config.mode}...`)
|
|
|
3099
3867
|
}
|
|
3100
3868
|
}
|
|
3101
3869
|
const elapsed = ((performance.now() - startTime) / 1e3).toFixed(2);
|
|
3102
|
-
const
|
|
3870
|
+
const allOutput = [...Object.values(environments).flat(), ...buildAppContext.output];
|
|
3871
|
+
const totalSize = allOutput.reduce((sum, chunk) => {
|
|
3103
3872
|
const content = chunk.type === "chunk" ? chunk.code : chunk.source;
|
|
3104
3873
|
if (content == null) return sum;
|
|
3105
3874
|
return sum + (typeof content === "string" ? Buffer.byteLength(content) : content.byteLength);
|
|
3106
3875
|
}, 0);
|
|
3107
|
-
const fileCount =
|
|
3876
|
+
const fileCount = allOutput.length;
|
|
3108
3877
|
const envSuffix = buildableNames.length > 1 ? ` (${buildableNames.join(" + ")})` : "";
|
|
3109
3878
|
logger.info(pc4.green(`\u2713 built in ${elapsed}s`) + pc4.dim(envSuffix));
|
|
3110
3879
|
logger.info(pc4.dim(` ${fileCount} files, ${displaySize(totalSize)} total \u2192 ${config.build.outDir}/`));
|
|
3111
|
-
return {
|
|
3880
|
+
return {
|
|
3881
|
+
output: clientOutput,
|
|
3882
|
+
environments,
|
|
3883
|
+
environmentResults,
|
|
3884
|
+
appOutput: [...buildAppContext.output]
|
|
3885
|
+
};
|
|
3112
3886
|
}
|
|
3113
3887
|
async function buildClientEnvironment(config) {
|
|
3114
3888
|
const logger = config.logger;
|
|
3115
|
-
const outDir =
|
|
3889
|
+
const outDir = path10.resolve(config.root, config.build.outDir);
|
|
3116
3890
|
const cssEngine = createCssEngine();
|
|
3117
|
-
const pluginList = resolvePluginList(config, config.plugins, {
|
|
3891
|
+
const pluginList = resolvePluginList(config, config.plugins, {
|
|
3892
|
+
cssEngine,
|
|
3893
|
+
environmentName: "client"
|
|
3894
|
+
});
|
|
3118
3895
|
const clientEnv = new NastiEnvironment("client", config, {
|
|
3119
3896
|
mode: "build",
|
|
3120
3897
|
plugins: pluginList,
|
|
@@ -3129,13 +3906,11 @@ async function buildClientEnvironment(config) {
|
|
|
3129
3906
|
);
|
|
3130
3907
|
}
|
|
3131
3908
|
const result = await clientEnv.driver.build(clientEnv.getDriverContext());
|
|
3132
|
-
|
|
3909
|
+
assertDriverBuildResult(clientEnv, result);
|
|
3910
|
+
return { environment: clientEnv, result: finalizeEnvironmentResult(clientEnv, result) };
|
|
3133
3911
|
}
|
|
3134
|
-
|
|
3135
|
-
|
|
3136
|
-
}
|
|
3137
|
-
fs6.mkdirSync(outDir, { recursive: true });
|
|
3138
|
-
const htmlFile = config.environments.client.html ?? path9.resolve(config.root, "index.html");
|
|
3912
|
+
fs7.mkdirSync(outDir, { recursive: true });
|
|
3913
|
+
const htmlFile = config.environments.client.html ?? path10.resolve(config.root, "index.html");
|
|
3139
3914
|
const html = await readHtmlFile(config.root, htmlFile);
|
|
3140
3915
|
const entryPoints = resolveClientEntries(config, html);
|
|
3141
3916
|
if (entryPoints.length === 0) {
|
|
@@ -3145,7 +3920,7 @@ async function buildClientEnvironment(config) {
|
|
|
3145
3920
|
const nativeReporter = config.logLevel === "silent" ? null : await tryNativeReporterPlugin(config, logger);
|
|
3146
3921
|
const rolldownPlugins = [
|
|
3147
3922
|
createOxcTransformPlugin(config, clientEnv),
|
|
3148
|
-
...toRolldownPlugins(allPlugins),
|
|
3923
|
+
...toRolldownPlugins(allPlugins, clientEnv),
|
|
3149
3924
|
...nativeReporter ? [nativeReporter] : []
|
|
3150
3925
|
];
|
|
3151
3926
|
const { inputOptions, outputOptions } = getRolldownOptions(
|
|
@@ -3156,6 +3931,7 @@ async function buildClientEnvironment(config) {
|
|
|
3156
3931
|
const bundle2 = await rolldown(inputOptions);
|
|
3157
3932
|
const { output } = await bundle2.write(outputOptions);
|
|
3158
3933
|
await bundle2.close();
|
|
3934
|
+
clientEnv.setBuildMetadata({ css: getCssMetadata(cssEngine) });
|
|
3159
3935
|
if (html) {
|
|
3160
3936
|
let processedHtml = html;
|
|
3161
3937
|
const htmlPlugins = [...allPlugins.filter((p) => p.transformIndexHtml), htmlPlugin(config)];
|
|
@@ -3169,7 +3945,9 @@ async function buildClientEnvironment(config) {
|
|
|
3169
3945
|
processedHtml = processHtml(processedHtml, result);
|
|
3170
3946
|
}
|
|
3171
3947
|
}
|
|
3172
|
-
|
|
3948
|
+
if (clientEnv.options.build.css.inject !== false) {
|
|
3949
|
+
processedHtml = injectCssLinks(processedHtml, cssEngine, config);
|
|
3950
|
+
}
|
|
3173
3951
|
for (const chunk of output) {
|
|
3174
3952
|
if (chunk.type === "chunk" && chunk.isEntry && chunk.facadeModuleId) {
|
|
3175
3953
|
processedHtml = replaceEntryScript(
|
|
@@ -3182,13 +3960,16 @@ async function buildClientEnvironment(config) {
|
|
|
3182
3960
|
);
|
|
3183
3961
|
}
|
|
3184
3962
|
}
|
|
3185
|
-
|
|
3963
|
+
fs7.writeFileSync(path10.resolve(outDir, "index.html"), processedHtml);
|
|
3186
3964
|
}
|
|
3187
3965
|
if (!nativeReporter && config.logLevel !== "silent") {
|
|
3188
3966
|
reportBuildOutput(output, config, logger);
|
|
3189
3967
|
}
|
|
3190
3968
|
warnLargeChunks(output, config, logger);
|
|
3191
|
-
return {
|
|
3969
|
+
return {
|
|
3970
|
+
environment: clientEnv,
|
|
3971
|
+
result: finalizeEnvironmentResult(clientEnv, { output })
|
|
3972
|
+
};
|
|
3192
3973
|
} catch (error) {
|
|
3193
3974
|
try {
|
|
3194
3975
|
await clientEnv.close();
|
|
@@ -3204,7 +3985,12 @@ async function buildClientEnvironment(config) {
|
|
|
3204
3985
|
async function buildServerEnvironment(config, name) {
|
|
3205
3986
|
const envOptions = config.environments[name];
|
|
3206
3987
|
const logger = config.logger;
|
|
3207
|
-
const
|
|
3988
|
+
const cssEngine = envOptions.consumer === "client" ? createCssEngine() : void 0;
|
|
3989
|
+
const pluginList = resolvePluginList(config, config.plugins, {
|
|
3990
|
+
consumer: envOptions.consumer,
|
|
3991
|
+
environmentName: name,
|
|
3992
|
+
cssEngine
|
|
3993
|
+
});
|
|
3208
3994
|
const environment = new NastiEnvironment(name, config, {
|
|
3209
3995
|
mode: "build",
|
|
3210
3996
|
plugins: pluginList,
|
|
@@ -3220,38 +4006,40 @@ async function buildServerEnvironment(config, name) {
|
|
|
3220
4006
|
}
|
|
3221
4007
|
try {
|
|
3222
4008
|
const result = await environment.driver.build(environment.getDriverContext());
|
|
3223
|
-
|
|
4009
|
+
assertDriverBuildResult(environment, result);
|
|
4010
|
+
return { environment, result: finalizeEnvironmentResult(environment, result) };
|
|
3224
4011
|
} catch (error) {
|
|
3225
4012
|
await environment.close();
|
|
3226
4013
|
throw error;
|
|
3227
4014
|
}
|
|
3228
4015
|
}
|
|
3229
4016
|
for (const entry of envOptions.entry) {
|
|
3230
|
-
if (!
|
|
4017
|
+
if (!fs7.existsSync(entry)) {
|
|
3231
4018
|
await environment.close();
|
|
3232
4019
|
throw new Error(`[nasti] environment "${name}" entry not found: ${entry}`);
|
|
3233
4020
|
}
|
|
3234
4021
|
}
|
|
3235
4022
|
const rolldownPlugins = [
|
|
3236
4023
|
createOxcTransformPlugin(config, environment),
|
|
3237
|
-
...toRolldownPlugins(environment.plugins)
|
|
4024
|
+
...toRolldownPlugins(environment.plugins, environment)
|
|
3238
4025
|
];
|
|
3239
4026
|
const { inputOptions, outputOptions, outDir } = getRolldownOptions(
|
|
3240
4027
|
environment,
|
|
3241
4028
|
envOptions.entry,
|
|
3242
4029
|
rolldownPlugins
|
|
3243
4030
|
);
|
|
3244
|
-
|
|
3245
|
-
fs6.rmSync(outDir, { recursive: true, force: true });
|
|
3246
|
-
}
|
|
3247
|
-
fs6.mkdirSync(outDir, { recursive: true });
|
|
4031
|
+
fs7.mkdirSync(outDir, { recursive: true });
|
|
3248
4032
|
const bundle2 = await rolldown(inputOptions);
|
|
3249
4033
|
const { output } = await bundle2.write(outputOptions);
|
|
3250
4034
|
await bundle2.close();
|
|
4035
|
+
if (cssEngine) environment.setBuildMetadata({ css: getCssMetadata(cssEngine) });
|
|
3251
4036
|
logger.info(
|
|
3252
|
-
pc4.dim(` [${name}] `) + output.map((o) =>
|
|
4037
|
+
pc4.dim(` [${name}] `) + output.map((o) => path10.join(envOptions.build.outDir, o.fileName)).join(pc4.dim(", "))
|
|
3253
4038
|
);
|
|
3254
|
-
return {
|
|
4039
|
+
return {
|
|
4040
|
+
environment,
|
|
4041
|
+
result: finalizeEnvironmentResult(environment, { output })
|
|
4042
|
+
};
|
|
3255
4043
|
}
|
|
3256
4044
|
function injectCssLinks(html, cssEngine, config) {
|
|
3257
4045
|
const cssLinkTags = [];
|
|
@@ -3278,9 +4066,9 @@ function escapeRegExp(string) {
|
|
|
3278
4066
|
return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
3279
4067
|
}
|
|
3280
4068
|
function replaceEntryScript(html, facadeModuleId, fileName, config, htmlFile, urlPrefix) {
|
|
3281
|
-
const rootRelative =
|
|
3282
|
-
const resolvedHtmlFile =
|
|
3283
|
-
const htmlRelative =
|
|
4069
|
+
const rootRelative = path10.relative(config.root, facadeModuleId).split(path10.sep).join("/");
|
|
4070
|
+
const resolvedHtmlFile = path10.resolve(config.root, htmlFile);
|
|
4071
|
+
const htmlRelative = path10.relative(path10.dirname(resolvedHtmlFile), facadeModuleId).split(path10.sep).join("/");
|
|
3284
4072
|
const candidates = /* @__PURE__ */ new Set([
|
|
3285
4073
|
rootRelative,
|
|
3286
4074
|
`/${rootRelative}`,
|
|
@@ -3296,7 +4084,7 @@ function replaceEntryScript(html, facadeModuleId, fileName, config, htmlFile, ur
|
|
|
3296
4084
|
}
|
|
3297
4085
|
return processed;
|
|
3298
4086
|
}
|
|
3299
|
-
var
|
|
4087
|
+
var debug5, NODE_BUILTINS;
|
|
3300
4088
|
var init_build = __esm({
|
|
3301
4089
|
"src/build/index.ts"() {
|
|
3302
4090
|
"use strict";
|
|
@@ -3310,7 +4098,8 @@ var init_build = __esm({
|
|
|
3310
4098
|
init_reporter();
|
|
3311
4099
|
init_debug();
|
|
3312
4100
|
init_plugin_api();
|
|
3313
|
-
|
|
4101
|
+
init_build_app_context();
|
|
4102
|
+
debug5 = createDebugger("nasti:build");
|
|
3314
4103
|
NODE_BUILTINS = /* @__PURE__ */ new Set([...builtinModules, ...builtinModules.map((m) => `node:${m}`)]);
|
|
3315
4104
|
}
|
|
3316
4105
|
});
|
|
@@ -3360,27 +4149,22 @@ var init_ws = __esm({
|
|
|
3360
4149
|
});
|
|
3361
4150
|
|
|
3362
4151
|
// src/server/middleware.ts
|
|
3363
|
-
|
|
3364
|
-
|
|
3365
|
-
REACT_REFRESH_GLOBAL_PREAMBLE: () => REACT_REFRESH_GLOBAL_PREAMBLE,
|
|
3366
|
-
getReactRefreshRuntimeEsm: () => getReactRefreshRuntimeEsm,
|
|
3367
|
-
transformMiddleware: () => transformMiddleware,
|
|
3368
|
-
transformRequest: () => transformRequest
|
|
3369
|
-
});
|
|
3370
|
-
import path11 from "path";
|
|
3371
|
-
import fs8 from "fs";
|
|
4152
|
+
import path12 from "path";
|
|
4153
|
+
import fs9 from "fs";
|
|
3372
4154
|
import { createRequire as createRequire3 } from "module";
|
|
3373
4155
|
import { fileURLToPath, pathToFileURL as pathToFileURL3 } from "url";
|
|
3374
4156
|
import pc6 from "picocolors";
|
|
3375
|
-
function getReactRefreshRuntimeEsm() {
|
|
3376
|
-
if (__refreshRuntimeCache)
|
|
4157
|
+
function getReactRefreshRuntimeEsm(includeBoundaryHelpers = false) {
|
|
4158
|
+
if (__refreshRuntimeCache) {
|
|
4159
|
+
return includeBoundaryHelpers ? __refreshRuntimeCache + REACT_REFRESH_BOUNDARY_HELPERS : __refreshRuntimeCache;
|
|
4160
|
+
}
|
|
3377
4161
|
let cjsPath;
|
|
3378
4162
|
try {
|
|
3379
4163
|
const pkgPath = __require2.resolve("react-refresh/package.json");
|
|
3380
|
-
cjsPath =
|
|
4164
|
+
cjsPath = path12.join(path12.dirname(pkgPath), "cjs", "react-refresh-runtime.development.js");
|
|
3381
4165
|
} catch (err) {
|
|
3382
|
-
cjsPath =
|
|
3383
|
-
if (!
|
|
4166
|
+
cjsPath = path12.resolve(__dirname_esm, "../../node_modules/react-refresh/cjs/react-refresh-runtime.development.js");
|
|
4167
|
+
if (!fs9.existsSync(cjsPath)) {
|
|
3384
4168
|
const origMsg = err instanceof Error ? err.message : String(err);
|
|
3385
4169
|
throw new Error(
|
|
3386
4170
|
`[nasti] Missing dependency "react-refresh". Install it with: npm install react-refresh
|
|
@@ -3388,7 +4172,7 @@ Original resolve error: ${origMsg}`
|
|
|
3388
4172
|
);
|
|
3389
4173
|
}
|
|
3390
4174
|
}
|
|
3391
|
-
const cjsSource =
|
|
4175
|
+
const cjsSource = fs9.readFileSync(cjsPath, "utf-8");
|
|
3392
4176
|
__refreshRuntimeCache = `// Wrapped react-refresh runtime -> ESM
|
|
3393
4177
|
const exports = {};
|
|
3394
4178
|
const module = { exports };
|
|
@@ -3408,7 +4192,7 @@ export const findAffectedHostInstances = __rt.findAffectedHostInstances;
|
|
|
3408
4192
|
export const collectCustomHooksForSignature = __rt.collectCustomHooksForSignature;
|
|
3409
4193
|
export default __rt;
|
|
3410
4194
|
`;
|
|
3411
|
-
return __refreshRuntimeCache;
|
|
4195
|
+
return includeBoundaryHelpers ? __refreshRuntimeCache + REACT_REFRESH_BOUNDARY_HELPERS : __refreshRuntimeCache;
|
|
3412
4196
|
}
|
|
3413
4197
|
function buildReactRefreshWrapper(moduleUrl, transformedCode) {
|
|
3414
4198
|
const urlLit = JSON.stringify(moduleUrl);
|
|
@@ -3434,27 +4218,46 @@ window.$RefreshReg$ = prevRefreshReg;
|
|
|
3434
4218
|
window.$RefreshSig$ = prevRefreshSig;
|
|
3435
4219
|
|
|
3436
4220
|
if (__nasti_hot__) {
|
|
3437
|
-
|
|
3438
|
-
|
|
3439
|
-
|
|
3440
|
-
|
|
3441
|
-
|
|
4221
|
+
let __nasti_current_exports__;
|
|
4222
|
+
__nasti_hot__.accept((nextExports) => {
|
|
4223
|
+
if (!nextExports) return;
|
|
4224
|
+
if (!__nasti_current_exports__) {
|
|
4225
|
+
__nasti_hot__.invalidate('Could not Fast Refresh (previous exports unavailable)');
|
|
4226
|
+
return;
|
|
4227
|
+
}
|
|
4228
|
+
const invalidateMessage = RefreshRuntime.validateRefreshBoundaryAndEnqueueUpdate(
|
|
4229
|
+
${urlLit},
|
|
4230
|
+
__nasti_current_exports__,
|
|
4231
|
+
nextExports,
|
|
4232
|
+
);
|
|
4233
|
+
if (invalidateMessage) __nasti_hot__.invalidate(invalidateMessage);
|
|
4234
|
+
});
|
|
4235
|
+
RefreshRuntime.__hmr_import(import.meta.url).then((currentExports) => {
|
|
4236
|
+
__nasti_current_exports__ = currentExports;
|
|
4237
|
+
RefreshRuntime.registerExportsForReactRefresh(${urlLit}, currentExports);
|
|
3442
4238
|
});
|
|
3443
4239
|
}
|
|
3444
4240
|
`;
|
|
3445
4241
|
}
|
|
3446
4242
|
function injectImportMetaHot(code, moduleUrl) {
|
|
3447
|
-
|
|
4243
|
+
const hotRE = /\bimport\.meta\.hot\b/g;
|
|
4244
|
+
const matches = [...maskStringsAndComments(code).matchAll(hotRE)];
|
|
4245
|
+
if (matches.length === 0) return code;
|
|
4246
|
+
for (const match of matches.reverse()) {
|
|
4247
|
+
const start = match.index;
|
|
4248
|
+
code = code.slice(0, start) + "__nasti_hot__" + code.slice(start + match[0].length);
|
|
4249
|
+
}
|
|
3448
4250
|
const urlLit = JSON.stringify(moduleUrl);
|
|
3449
4251
|
const header = `import { createHotContext as __nasti_createHotContext__ } from "/@nasti/client";
|
|
3450
4252
|
const __nasti_hot__ = __nasti_createHotContext__(${urlLit});
|
|
3451
4253
|
`;
|
|
3452
|
-
return header + code
|
|
4254
|
+
return header + code;
|
|
3453
4255
|
}
|
|
3454
4256
|
function transformMiddleware(ctx) {
|
|
3455
4257
|
ctx.envDefine = buildEnvDefine(
|
|
3456
4258
|
loadEnv(ctx.config.mode, ctx.config.root, ctx.config.envPrefix),
|
|
3457
|
-
ctx.config.mode
|
|
4259
|
+
ctx.config.mode,
|
|
4260
|
+
ssrDefineOverrides(ctx.environment?.consumer ?? "client")
|
|
3458
4261
|
);
|
|
3459
4262
|
return async (req, res, next) => {
|
|
3460
4263
|
const url = req.url ?? "/";
|
|
@@ -3499,7 +4302,7 @@ function transformMiddleware(ctx) {
|
|
|
3499
4302
|
return;
|
|
3500
4303
|
}
|
|
3501
4304
|
}
|
|
3502
|
-
if (isModuleRequest(url)) {
|
|
4305
|
+
if (isModuleRequest(url, req.headers["sec-fetch-dest"])) {
|
|
3503
4306
|
try {
|
|
3504
4307
|
const result = await transformRequest(url, ctx);
|
|
3505
4308
|
if (result) {
|
|
@@ -3525,13 +4328,14 @@ function transformMiddleware(ctx) {
|
|
|
3525
4328
|
}
|
|
3526
4329
|
async function transformRequest(url, ctx) {
|
|
3527
4330
|
const { config, pluginContainer, moduleGraph } = ctx;
|
|
4331
|
+
url = removeTimestampQuery(url);
|
|
3528
4332
|
const cleanReqUrl = url.split("?")[0];
|
|
3529
4333
|
const cached2 = moduleGraph.getModuleByUrl(url);
|
|
3530
4334
|
if (cached2?.transformResult) {
|
|
3531
4335
|
return cached2.transformResult;
|
|
3532
4336
|
}
|
|
3533
4337
|
if (cleanReqUrl === "/@react-refresh") {
|
|
3534
|
-
return { code: getReactRefreshRuntimeEsm() };
|
|
4338
|
+
return { code: getReactRefreshRuntimeEsm(true) };
|
|
3535
4339
|
}
|
|
3536
4340
|
if (cleanReqUrl.startsWith("/@modules/") && url.includes("?")) {
|
|
3537
4341
|
const idParam = new URLSearchParams(url.slice(url.indexOf("?") + 1)).get("id");
|
|
@@ -3539,8 +4343,8 @@ async function transformRequest(url, ctx) {
|
|
|
3539
4343
|
let realIdValid = false;
|
|
3540
4344
|
try {
|
|
3541
4345
|
if (idParam) {
|
|
3542
|
-
realId =
|
|
3543
|
-
realIdValid =
|
|
4346
|
+
realId = fs9.realpathSync(idParam);
|
|
4347
|
+
realIdValid = fs9.statSync(realId).isFile() && (realId.includes(`${path12.sep}node_modules${path12.sep}`) || isUnderRoot(realId, config.root));
|
|
3544
4348
|
}
|
|
3545
4349
|
} catch {
|
|
3546
4350
|
realId = null;
|
|
@@ -3567,40 +4371,63 @@ async function transformRequest(url, ctx) {
|
|
|
3567
4371
|
}
|
|
3568
4372
|
const rawQuery = url.includes("?") ? url.slice(url.indexOf("?") + 1) : "";
|
|
3569
4373
|
if (rawQuery && !/^t=\d+$/.test(rawQuery)) {
|
|
3570
|
-
const
|
|
3571
|
-
|
|
3572
|
-
|
|
4374
|
+
const mod2 = await moduleGraph.ensureEntryFromUrl(url);
|
|
4375
|
+
const transformVersion2 = mod2.invalidationVersion;
|
|
4376
|
+
const loaded2 = await pluginContainer.load(url);
|
|
4377
|
+
if (loaded2 != null) {
|
|
4378
|
+
let code2 = typeof loaded2 === "string" ? loaded2 : loaded2.code;
|
|
4379
|
+
let map2 = typeof loaded2 === "string" ? void 0 : loaded2.map;
|
|
3573
4380
|
const transformed = await pluginContainer.transform(code2, url);
|
|
3574
4381
|
if (transformed != null) {
|
|
3575
4382
|
code2 = typeof transformed === "string" ? transformed : transformed.code;
|
|
4383
|
+
if (typeof transformed !== "string" && transformed.map != null) {
|
|
4384
|
+
map2 = transformed.map;
|
|
4385
|
+
}
|
|
3576
4386
|
}
|
|
3577
|
-
const
|
|
3578
|
-
moduleGraph.registerModule(mod2,
|
|
3579
|
-
|
|
4387
|
+
const parentFile = resolveUrlToFile(cleanReqUrl, config.root) ?? cleanReqUrl;
|
|
4388
|
+
moduleGraph.registerModule(mod2, parentFile);
|
|
4389
|
+
const hotInfo2 = rewriteHotAcceptDeps(code2, config, parentFile);
|
|
4390
|
+
code2 = injectImportMetaHot(hotInfo2.code, url);
|
|
3580
4391
|
code2 = replaceEnvInCode(code2, ctx.envDefine ?? buildEnvDefine(
|
|
3581
4392
|
loadEnv(config.mode, config.root, config.envPrefix),
|
|
3582
|
-
config.mode
|
|
4393
|
+
config.mode,
|
|
4394
|
+
ssrDefineOverrides(ctx.environment?.consumer ?? "client")
|
|
3583
4395
|
));
|
|
3584
|
-
|
|
3585
|
-
|
|
3586
|
-
|
|
4396
|
+
const importedUrls2 = /* @__PURE__ */ new Set();
|
|
4397
|
+
code2 = rewriteImports(code2, config, parentFile, importedUrls2, moduleGraph);
|
|
4398
|
+
const pruned2 = await moduleGraph.updateModuleInfo(
|
|
4399
|
+
mod2,
|
|
4400
|
+
importedUrls2,
|
|
4401
|
+
hotInfo2.acceptedUrls,
|
|
4402
|
+
hotInfo2.isSelfAccepting,
|
|
4403
|
+
transformVersion2
|
|
4404
|
+
);
|
|
4405
|
+
const transformResult2 = { code: code2, map: map2 };
|
|
4406
|
+
if (pruned2) {
|
|
4407
|
+
if (pruned2.size > 0) ctx.onPrune?.([...pruned2].map((item) => item.url));
|
|
4408
|
+
mod2.transformResult = transformResult2;
|
|
4409
|
+
}
|
|
3587
4410
|
return transformResult2;
|
|
3588
4411
|
}
|
|
3589
4412
|
}
|
|
3590
4413
|
const filePath = resolveUrlToFile(url, config.root);
|
|
3591
|
-
if (!filePath || !
|
|
4414
|
+
if (!filePath || !fs9.existsSync(filePath)) return null;
|
|
3592
4415
|
const mod = await moduleGraph.ensureEntryFromUrl(url);
|
|
3593
4416
|
moduleGraph.registerModule(mod, filePath);
|
|
4417
|
+
const transformVersion = mod.invalidationVersion;
|
|
3594
4418
|
if (cleanReqUrl.startsWith("/@modules/")) {
|
|
3595
4419
|
const code2 = await bundlePackageAsEsm(filePath, config.root);
|
|
3596
4420
|
const transformResult2 = { code: code2 };
|
|
3597
4421
|
mod.transformResult = transformResult2;
|
|
3598
4422
|
return transformResult2;
|
|
3599
4423
|
}
|
|
3600
|
-
|
|
4424
|
+
const loaded = await pluginContainer.load(filePath);
|
|
4425
|
+
let code = loaded == null ? fs9.readFileSync(filePath, "utf-8") : typeof loaded === "string" ? loaded : loaded.code;
|
|
4426
|
+
let map = loaded && typeof loaded !== "string" ? loaded.map : void 0;
|
|
3601
4427
|
const pluginResult = await pluginContainer.transform(code, filePath);
|
|
3602
4428
|
if (pluginResult) {
|
|
3603
4429
|
code = typeof pluginResult === "string" ? pluginResult : pluginResult.code;
|
|
4430
|
+
if (typeof pluginResult !== "string") map = pluginResult.map;
|
|
3604
4431
|
}
|
|
3605
4432
|
const stableUrl = cleanReqUrl;
|
|
3606
4433
|
let wrappedWithRefresh = false;
|
|
@@ -3611,26 +4438,41 @@ async function transformRequest(url, ctx) {
|
|
|
3611
4438
|
sourcemap: true,
|
|
3612
4439
|
jsxRuntime: "automatic",
|
|
3613
4440
|
jsxImportSource: config.framework === "vue" ? "vue" : "react",
|
|
3614
|
-
reactRefresh: useRefresh
|
|
4441
|
+
reactRefresh: useRefresh,
|
|
4442
|
+
target: ctx.environment?.options.build.target ?? config.build.target
|
|
3615
4443
|
});
|
|
3616
4444
|
code = result.code;
|
|
4445
|
+
if (result.map) map = JSON.parse(result.map);
|
|
3617
4446
|
if (useRefresh) {
|
|
3618
4447
|
code = buildReactRefreshWrapper(stableUrl, code);
|
|
3619
4448
|
wrappedWithRefresh = true;
|
|
3620
|
-
mod.isSelfAccepting = true;
|
|
3621
4449
|
}
|
|
3622
4450
|
}
|
|
4451
|
+
const hotInfo = rewriteHotAcceptDeps(code, config, filePath);
|
|
4452
|
+
code = hotInfo.code;
|
|
3623
4453
|
if (!wrappedWithRefresh) {
|
|
3624
4454
|
code = injectImportMetaHot(code, stableUrl);
|
|
3625
4455
|
}
|
|
3626
4456
|
const envDefine = ctx.envDefine ?? buildEnvDefine(
|
|
3627
4457
|
loadEnv(config.mode, config.root, config.envPrefix),
|
|
3628
|
-
config.mode
|
|
4458
|
+
config.mode,
|
|
4459
|
+
ssrDefineOverrides(ctx.environment?.consumer ?? "client")
|
|
3629
4460
|
);
|
|
3630
4461
|
code = replaceEnvInCode(code, envDefine);
|
|
3631
|
-
|
|
3632
|
-
|
|
3633
|
-
|
|
4462
|
+
const importedUrls = /* @__PURE__ */ new Set();
|
|
4463
|
+
code = rewriteImports(code, config, filePath, importedUrls, moduleGraph);
|
|
4464
|
+
const pruned = await moduleGraph.updateModuleInfo(
|
|
4465
|
+
mod,
|
|
4466
|
+
importedUrls,
|
|
4467
|
+
hotInfo.acceptedUrls,
|
|
4468
|
+
wrappedWithRefresh || hotInfo.isSelfAccepting,
|
|
4469
|
+
transformVersion
|
|
4470
|
+
);
|
|
4471
|
+
const transformResult = { code, map };
|
|
4472
|
+
if (pruned) {
|
|
4473
|
+
if (pruned.size > 0) ctx.onPrune?.([...pruned].map((item) => item.url));
|
|
4474
|
+
mod.transformResult = transformResult;
|
|
4475
|
+
}
|
|
3634
4476
|
return transformResult;
|
|
3635
4477
|
}
|
|
3636
4478
|
async function loadVirtualModule(spec, ctx) {
|
|
@@ -3638,7 +4480,7 @@ async function loadVirtualModule(spec, ctx) {
|
|
|
3638
4480
|
const resolved = await pluginContainer.resolveId(spec);
|
|
3639
4481
|
if (resolved == null) return null;
|
|
3640
4482
|
const resolvedId = typeof resolved === "string" ? resolved : resolved.id;
|
|
3641
|
-
const looksVirtual = resolvedId.startsWith("\0") || !
|
|
4483
|
+
const looksVirtual = resolvedId.startsWith("\0") || !fs9.existsSync(resolvedId);
|
|
3642
4484
|
if (!looksVirtual) return null;
|
|
3643
4485
|
const loadResult = await pluginContainer.load(resolvedId);
|
|
3644
4486
|
if (loadResult == null) return null;
|
|
@@ -3649,9 +4491,10 @@ async function loadVirtualModule(spec, ctx) {
|
|
|
3649
4491
|
}
|
|
3650
4492
|
code = replaceEnvInCode(code, ctx.envDefine ?? buildEnvDefine(
|
|
3651
4493
|
loadEnv(config.mode, config.root, config.envPrefix),
|
|
3652
|
-
config.mode
|
|
4494
|
+
config.mode,
|
|
4495
|
+
ssrDefineOverrides(ctx.environment?.consumer ?? "client")
|
|
3653
4496
|
));
|
|
3654
|
-
const anchor =
|
|
4497
|
+
const anchor = path12.join(config.root, "__nasti_virtual__.ts");
|
|
3655
4498
|
code = rewriteImports(code, config, anchor);
|
|
3656
4499
|
return { id: resolvedId, result: { code } };
|
|
3657
4500
|
}
|
|
@@ -3677,7 +4520,7 @@ async function doBundlePackage(entryFile, root) {
|
|
|
3677
4520
|
await bundle2.close();
|
|
3678
4521
|
let code = result.output[0].code;
|
|
3679
4522
|
code = code.replace(/process\.env\.NODE_ENV/g, '"development"');
|
|
3680
|
-
const externalBaseDir =
|
|
4523
|
+
const externalBaseDir = path12.dirname(entryFile);
|
|
3681
4524
|
code = code.replace(
|
|
3682
4525
|
/^(import\b[^;'"]*?\bfrom\s+)(['"])([^'"./][^'"]*)(\2)/gm,
|
|
3683
4526
|
(_, prefix, q, spec) => `${prefix}${q}${externalSpecToModuleUrl(spec, externalBaseDir, root)}${q}`
|
|
@@ -3695,16 +4538,16 @@ async function doBundlePackage(entryFile, root) {
|
|
|
3695
4538
|
return code;
|
|
3696
4539
|
}
|
|
3697
4540
|
async function tryGenerateSubpathShim(entryFile, root) {
|
|
3698
|
-
const NM = `${
|
|
4541
|
+
const NM = `${path12.sep}node_modules${path12.sep}`;
|
|
3699
4542
|
if (!entryFile.includes(NM)) return null;
|
|
3700
4543
|
let pkgDir = null;
|
|
3701
4544
|
let pkgName = null;
|
|
3702
|
-
let dir =
|
|
4545
|
+
let dir = path12.dirname(entryFile);
|
|
3703
4546
|
while (true) {
|
|
3704
|
-
const pkgJsonPath =
|
|
3705
|
-
if (
|
|
4547
|
+
const pkgJsonPath = path12.join(dir, "package.json");
|
|
4548
|
+
if (fs9.existsSync(pkgJsonPath)) {
|
|
3706
4549
|
try {
|
|
3707
|
-
const pkg = JSON.parse(
|
|
4550
|
+
const pkg = JSON.parse(fs9.readFileSync(pkgJsonPath, "utf-8"));
|
|
3708
4551
|
if (typeof pkg?.name === "string" && pkg.name) {
|
|
3709
4552
|
pkgDir = dir;
|
|
3710
4553
|
pkgName = pkg.name;
|
|
@@ -3713,16 +4556,16 @@ async function tryGenerateSubpathShim(entryFile, root) {
|
|
|
3713
4556
|
} catch {
|
|
3714
4557
|
}
|
|
3715
4558
|
}
|
|
3716
|
-
const parent =
|
|
4559
|
+
const parent = path12.dirname(dir);
|
|
3717
4560
|
if (parent === dir) return null;
|
|
3718
4561
|
dir = parent;
|
|
3719
4562
|
if (!dir.includes(NM)) return null;
|
|
3720
4563
|
}
|
|
3721
4564
|
if (!pkgDir || !pkgName) return null;
|
|
3722
|
-
const entryExt =
|
|
4565
|
+
const entryExt = path12.extname(entryFile);
|
|
3723
4566
|
const mainEntry = pickMainEntryByExtension(pkgDir, entryExt);
|
|
3724
4567
|
if (!mainEntry) return null;
|
|
3725
|
-
if (
|
|
4568
|
+
if (path12.resolve(mainEntry) === path12.resolve(entryFile)) return null;
|
|
3726
4569
|
let mainNs;
|
|
3727
4570
|
let subNs;
|
|
3728
4571
|
try {
|
|
@@ -3746,7 +4589,7 @@ async function tryGenerateSubpathShim(entryFile, root) {
|
|
|
3746
4589
|
if (mainNs["default"] !== subNs["default"]) return null;
|
|
3747
4590
|
}
|
|
3748
4591
|
const rootMain = resolveNodeModule(root, pkgName);
|
|
3749
|
-
const mainEntryUrl = rootMain && rootMain.startsWith(pkgDir +
|
|
4592
|
+
const mainEntryUrl = rootMain && rootMain.startsWith(pkgDir + path12.sep) ? `/@modules/${pkgName}` : `/@modules/${pkgName}?id=${encodeURIComponent(mainEntry)}`;
|
|
3750
4593
|
const lines = [
|
|
3751
4594
|
`// Nasti subpath shim \u2192 ${pkgName} (avoid duplicate bundling)`,
|
|
3752
4595
|
`import * as __pkg from "${mainEntryUrl}";`
|
|
@@ -3760,10 +4603,10 @@ async function tryGenerateSubpathShim(entryFile, root) {
|
|
|
3760
4603
|
return lines.join("\n") + "\n";
|
|
3761
4604
|
}
|
|
3762
4605
|
function pickMainEntryByExtension(pkgDir, preferredExt) {
|
|
3763
|
-
const pkgJsonPath =
|
|
4606
|
+
const pkgJsonPath = path12.join(pkgDir, "package.json");
|
|
3764
4607
|
let pkg;
|
|
3765
4608
|
try {
|
|
3766
|
-
pkg = JSON.parse(
|
|
4609
|
+
pkg = JSON.parse(fs9.readFileSync(pkgJsonPath, "utf-8"));
|
|
3767
4610
|
} catch {
|
|
3768
4611
|
return null;
|
|
3769
4612
|
}
|
|
@@ -3782,14 +4625,14 @@ function pickMainEntryByExtension(pkgDir, preferredExt) {
|
|
|
3782
4625
|
if (typeof pkg.module === "string") candidates.push(pkg.module);
|
|
3783
4626
|
if (typeof pkg.main === "string") candidates.push(pkg.main);
|
|
3784
4627
|
for (const cand of candidates) {
|
|
3785
|
-
if (
|
|
3786
|
-
const full =
|
|
3787
|
-
if (
|
|
4628
|
+
if (path12.extname(cand) === preferredExt) {
|
|
4629
|
+
const full = path12.resolve(pkgDir, cand);
|
|
4630
|
+
if (fs9.existsSync(full)) return full;
|
|
3788
4631
|
}
|
|
3789
4632
|
}
|
|
3790
4633
|
for (const cand of candidates) {
|
|
3791
|
-
const full =
|
|
3792
|
-
if (
|
|
4634
|
+
const full = path12.resolve(pkgDir, cand);
|
|
4635
|
+
if (fs9.existsSync(full)) return full;
|
|
3793
4636
|
}
|
|
3794
4637
|
return null;
|
|
3795
4638
|
}
|
|
@@ -3835,72 +4678,231 @@ async function injectCjsNamedExports(code, entryFile) {
|
|
|
3835
4678
|
return code;
|
|
3836
4679
|
}
|
|
3837
4680
|
}
|
|
3838
|
-
function rewriteImports(code, config, filePath) {
|
|
4681
|
+
function rewriteImports(code, config, filePath, importedUrls, moduleGraph) {
|
|
4682
|
+
const resolveSpec = createModuleSpecifierResolver(config, filePath);
|
|
4683
|
+
const transformSpec = (spec) => {
|
|
4684
|
+
const resolved = removeTimestampQuery(resolveSpec(spec));
|
|
4685
|
+
importedUrls?.add(resolved);
|
|
4686
|
+
const timestamp = moduleGraph?.getModuleByUrl(resolved)?.lastHMRTimestamp ?? 0;
|
|
4687
|
+
return timestamp > 0 ? appendTimestampQuery(resolved, timestamp) : resolved;
|
|
4688
|
+
};
|
|
4689
|
+
return code.replace(
|
|
4690
|
+
/\bfrom\s+(['"])([^'"]+)\1/g,
|
|
4691
|
+
(_m, q, s) => `from ${q}${transformSpec(s)}${q}`
|
|
4692
|
+
).replace(
|
|
4693
|
+
/\bimport\s+(['"])([^'"]+)\1/g,
|
|
4694
|
+
(_m, q, s) => `import ${q}${transformSpec(s)}${q}`
|
|
4695
|
+
).replace(
|
|
4696
|
+
/\bimport\s*\(\s*(['"])([^'"]+)\1\s*\)/g,
|
|
4697
|
+
(_m, q, s) => `import(${q}${transformSpec(s)}${q})`
|
|
4698
|
+
);
|
|
4699
|
+
}
|
|
4700
|
+
function createModuleSpecifierResolver(config, filePath) {
|
|
3839
4701
|
const root = config.root;
|
|
3840
|
-
const fileDir =
|
|
4702
|
+
const fileDir = path12.dirname(filePath);
|
|
3841
4703
|
const aliasEntries = Object.entries(config.resolve.alias).sort(
|
|
3842
4704
|
([a], [b]) => b.length - a.length
|
|
3843
4705
|
);
|
|
3844
|
-
const toRootUrl = (abs) => "/" +
|
|
3845
|
-
|
|
3846
|
-
const suffixMatch =
|
|
4706
|
+
const toRootUrl = (abs) => "/" + path12.relative(root, abs).replace(/\\/g, "/");
|
|
4707
|
+
return (specifier) => {
|
|
4708
|
+
const suffixMatch = specifier.match(/[?#].*$/);
|
|
3847
4709
|
const suffix = suffixMatch ? suffixMatch[0] : "";
|
|
3848
|
-
const baseSpec = suffix ?
|
|
4710
|
+
const baseSpec = suffix ? specifier.slice(0, -suffix.length) : specifier;
|
|
3849
4711
|
for (const [key, value] of aliasEntries) {
|
|
3850
4712
|
if (baseSpec === key || baseSpec.startsWith(key + "/")) {
|
|
3851
4713
|
const aliasBase = resolveAliasTarget2(value, root);
|
|
3852
4714
|
const sub = baseSpec.slice(key.length).replace(/^\//, "");
|
|
3853
|
-
const target = sub ?
|
|
4715
|
+
const target = sub ? path12.join(aliasBase, sub) : aliasBase;
|
|
3854
4716
|
const resolved = tryResolveDiskPath(target);
|
|
3855
|
-
return resolved && isUnderRoot(resolved, root) ? toRootUrl(resolved) + suffix :
|
|
4717
|
+
return resolved && isUnderRoot(resolved, root) ? toRootUrl(resolved) + suffix : specifier;
|
|
3856
4718
|
}
|
|
3857
4719
|
}
|
|
3858
4720
|
if (baseSpec.startsWith("./") || baseSpec.startsWith("../")) {
|
|
3859
|
-
const
|
|
3860
|
-
|
|
3861
|
-
return resolved && isUnderRoot(resolved, root) ? toRootUrl(resolved) + suffix : spec;
|
|
4721
|
+
const resolved = tryResolveDiskPath(path12.resolve(fileDir, baseSpec));
|
|
4722
|
+
return resolved && isUnderRoot(resolved, root) ? toRootUrl(resolved) + suffix : specifier;
|
|
3862
4723
|
}
|
|
3863
4724
|
if (baseSpec.startsWith("/") && !baseSpec.startsWith("/@")) {
|
|
3864
|
-
const
|
|
3865
|
-
|
|
3866
|
-
return resolved && isUnderRoot(resolved, root) ? toRootUrl(resolved) + suffix : spec;
|
|
4725
|
+
const resolved = tryResolveDiskPath(path12.join(root, baseSpec.replace(/^\//, "")));
|
|
4726
|
+
return resolved && isUnderRoot(resolved, root) ? toRootUrl(resolved) + suffix : specifier;
|
|
3867
4727
|
}
|
|
3868
|
-
if (baseSpec.startsWith("/")) return
|
|
3869
|
-
return `/@modules/${
|
|
4728
|
+
if (baseSpec.startsWith("/")) return specifier;
|
|
4729
|
+
return `/@modules/${specifier}`;
|
|
3870
4730
|
};
|
|
3871
|
-
|
|
3872
|
-
|
|
3873
|
-
|
|
3874
|
-
|
|
3875
|
-
|
|
3876
|
-
|
|
3877
|
-
)
|
|
3878
|
-
|
|
3879
|
-
|
|
3880
|
-
)
|
|
4731
|
+
}
|
|
4732
|
+
function rewriteHotAcceptDeps(code, config, filePath) {
|
|
4733
|
+
const acceptedUrls = /* @__PURE__ */ new Set();
|
|
4734
|
+
const edits = [];
|
|
4735
|
+
const resolveSpec = createModuleSpecifierResolver(config, filePath);
|
|
4736
|
+
const acceptRE = /(?:\bimport\.meta\.hot|\b__nasti_hot__)(?:(?:\?\.)|\.)accept\s*\(/g;
|
|
4737
|
+
const searchableCode = maskStringsAndComments(code);
|
|
4738
|
+
let isSelfAccepting = false;
|
|
4739
|
+
let match;
|
|
4740
|
+
while (match = acceptRE.exec(searchableCode)) {
|
|
4741
|
+
let cursor = match.index + match[0].length;
|
|
4742
|
+
const skipTrivia = () => {
|
|
4743
|
+
while (cursor < code.length) {
|
|
4744
|
+
if (/\s/.test(code[cursor])) {
|
|
4745
|
+
cursor++;
|
|
4746
|
+
continue;
|
|
4747
|
+
}
|
|
4748
|
+
if (code[cursor] === "/" && code[cursor + 1] === "/") {
|
|
4749
|
+
cursor += 2;
|
|
4750
|
+
while (cursor < code.length && code[cursor] !== "\n") cursor++;
|
|
4751
|
+
continue;
|
|
4752
|
+
}
|
|
4753
|
+
if (code[cursor] === "/" && code[cursor + 1] === "*") {
|
|
4754
|
+
cursor += 2;
|
|
4755
|
+
while (cursor < code.length && !(code[cursor] === "*" && code[cursor + 1] === "/")) cursor++;
|
|
4756
|
+
cursor += 2;
|
|
4757
|
+
continue;
|
|
4758
|
+
}
|
|
4759
|
+
break;
|
|
4760
|
+
}
|
|
4761
|
+
};
|
|
4762
|
+
skipTrivia();
|
|
4763
|
+
const first = code[cursor];
|
|
4764
|
+
if (!first || first === ")" || first !== "[" && first !== "'" && first !== '"' && first !== "`") {
|
|
4765
|
+
isSelfAccepting = true;
|
|
4766
|
+
continue;
|
|
4767
|
+
}
|
|
4768
|
+
const readLiteral = () => {
|
|
4769
|
+
const quote = code[cursor];
|
|
4770
|
+
if (quote !== "'" && quote !== '"' && quote !== "`") return;
|
|
4771
|
+
const start = cursor;
|
|
4772
|
+
cursor++;
|
|
4773
|
+
let raw = "";
|
|
4774
|
+
while (cursor < code.length) {
|
|
4775
|
+
const char = code[cursor];
|
|
4776
|
+
if (char === "\\") {
|
|
4777
|
+
raw += code[cursor + 1] ?? "";
|
|
4778
|
+
cursor += 2;
|
|
4779
|
+
continue;
|
|
4780
|
+
}
|
|
4781
|
+
if (char === quote) {
|
|
4782
|
+
cursor++;
|
|
4783
|
+
const resolved = removeTimestampQuery(resolveSpec(raw));
|
|
4784
|
+
acceptedUrls.add(resolved);
|
|
4785
|
+
edits.push({ start, end: cursor, value: JSON.stringify(resolved) });
|
|
4786
|
+
return;
|
|
4787
|
+
}
|
|
4788
|
+
if (quote === "`" && char === "$" && code[cursor + 1] === "{") return;
|
|
4789
|
+
raw += char;
|
|
4790
|
+
cursor++;
|
|
4791
|
+
}
|
|
4792
|
+
};
|
|
4793
|
+
if (first === "[") {
|
|
4794
|
+
cursor++;
|
|
4795
|
+
while (cursor < code.length) {
|
|
4796
|
+
skipTrivia();
|
|
4797
|
+
if (code[cursor] === ",") {
|
|
4798
|
+
cursor++;
|
|
4799
|
+
skipTrivia();
|
|
4800
|
+
}
|
|
4801
|
+
if (code[cursor] === "]") break;
|
|
4802
|
+
const before = cursor;
|
|
4803
|
+
readLiteral();
|
|
4804
|
+
if (cursor === before) break;
|
|
4805
|
+
}
|
|
4806
|
+
} else {
|
|
4807
|
+
readLiteral();
|
|
4808
|
+
}
|
|
4809
|
+
}
|
|
4810
|
+
for (const edit of edits.sort((a, b) => b.start - a.start)) {
|
|
4811
|
+
code = code.slice(0, edit.start) + edit.value + code.slice(edit.end);
|
|
4812
|
+
}
|
|
4813
|
+
return { code, acceptedUrls, isSelfAccepting };
|
|
4814
|
+
}
|
|
4815
|
+
function maskStringsAndComments(code) {
|
|
4816
|
+
const masked = code.split("");
|
|
4817
|
+
let state = "code";
|
|
4818
|
+
const isRegexStart = (index2) => {
|
|
4819
|
+
let previous = index2 - 1;
|
|
4820
|
+
while (previous >= 0 && /\s/.test(code[previous])) previous--;
|
|
4821
|
+
return previous < 0 || "=(:,!&|?{};[]+-*%^~<>".includes(code[previous]);
|
|
4822
|
+
};
|
|
4823
|
+
for (let i = 0; i < code.length; i++) {
|
|
4824
|
+
const char = code[i];
|
|
4825
|
+
const next = code[i + 1];
|
|
4826
|
+
if (state === "code") {
|
|
4827
|
+
if (char === "'") state = "single";
|
|
4828
|
+
else if (char === '"') state = "double";
|
|
4829
|
+
else if (char === "`") state = "template";
|
|
4830
|
+
else if (char === "/" && next === "/") state = "line-comment";
|
|
4831
|
+
else if (char === "/" && next === "*") state = "block-comment";
|
|
4832
|
+
else if (char === "/" && isRegexStart(i)) state = "regex";
|
|
4833
|
+
else continue;
|
|
4834
|
+
masked[i] = " ";
|
|
4835
|
+
continue;
|
|
4836
|
+
}
|
|
4837
|
+
if (state === "line-comment") {
|
|
4838
|
+
if (char === "\n") {
|
|
4839
|
+
state = "code";
|
|
4840
|
+
} else {
|
|
4841
|
+
masked[i] = " ";
|
|
4842
|
+
}
|
|
4843
|
+
continue;
|
|
4844
|
+
}
|
|
4845
|
+
if (state === "block-comment") {
|
|
4846
|
+
masked[i] = char === "\n" ? "\n" : " ";
|
|
4847
|
+
if (char === "*" && next === "/") {
|
|
4848
|
+
masked[i + 1] = " ";
|
|
4849
|
+
i++;
|
|
4850
|
+
state = "code";
|
|
4851
|
+
}
|
|
4852
|
+
continue;
|
|
4853
|
+
}
|
|
4854
|
+
if (state === "regex" || state === "regex-class") {
|
|
4855
|
+
masked[i] = char === "\n" ? "\n" : " ";
|
|
4856
|
+
if (char === "\\") {
|
|
4857
|
+
if (i + 1 < code.length) masked[++i] = " ";
|
|
4858
|
+
} else if (state === "regex" && char === "[") {
|
|
4859
|
+
state = "regex-class";
|
|
4860
|
+
} else if (state === "regex-class" && char === "]") {
|
|
4861
|
+
state = "regex";
|
|
4862
|
+
} else if (state === "regex" && char === "/") {
|
|
4863
|
+
state = "code";
|
|
4864
|
+
}
|
|
4865
|
+
continue;
|
|
4866
|
+
}
|
|
4867
|
+
masked[i] = char === "\n" ? "\n" : " ";
|
|
4868
|
+
if (char === "\\") {
|
|
4869
|
+
if (i + 1 < code.length) masked[++i] = " ";
|
|
4870
|
+
continue;
|
|
4871
|
+
}
|
|
4872
|
+
if (state === "single" && char === "'" || state === "double" && char === '"' || state === "template" && char === "`") {
|
|
4873
|
+
state = "code";
|
|
4874
|
+
}
|
|
4875
|
+
}
|
|
4876
|
+
return masked.join("");
|
|
3881
4877
|
}
|
|
3882
4878
|
function resolveAliasTarget2(value, root) {
|
|
3883
|
-
if (
|
|
3884
|
-
if (value.startsWith("/")) return
|
|
3885
|
-
return
|
|
4879
|
+
if (path12.isAbsolute(value) && fs9.existsSync(value)) return value;
|
|
4880
|
+
if (value.startsWith("/")) return path12.join(root, value.slice(1));
|
|
4881
|
+
return path12.resolve(root, value);
|
|
3886
4882
|
}
|
|
3887
4883
|
function tryResolveDiskPath(target) {
|
|
3888
|
-
if (
|
|
4884
|
+
if (fs9.existsSync(target) && fs9.statSync(target).isFile()) return target;
|
|
3889
4885
|
for (const ext of RESOLVE_EXTENSIONS) {
|
|
3890
4886
|
const withExt = target + ext;
|
|
3891
|
-
if (
|
|
4887
|
+
if (fs9.existsSync(withExt) && fs9.statSync(withExt).isFile()) return withExt;
|
|
3892
4888
|
}
|
|
3893
|
-
if (
|
|
4889
|
+
if (fs9.existsSync(target) && fs9.statSync(target).isDirectory()) {
|
|
3894
4890
|
for (const ext of RESOLVE_EXTENSIONS) {
|
|
3895
|
-
const idx =
|
|
3896
|
-
if (
|
|
4891
|
+
const idx = path12.join(target, "index" + ext);
|
|
4892
|
+
if (fs9.existsSync(idx) && fs9.statSync(idx).isFile()) return idx;
|
|
3897
4893
|
}
|
|
3898
4894
|
}
|
|
3899
4895
|
return null;
|
|
3900
4896
|
}
|
|
3901
4897
|
function isUnderRoot(abs, root) {
|
|
3902
|
-
const rel =
|
|
3903
|
-
return !!rel && !rel.startsWith("..") && !
|
|
4898
|
+
const rel = path12.relative(root, abs);
|
|
4899
|
+
return !!rel && !rel.startsWith("..") && !path12.isAbsolute(rel);
|
|
4900
|
+
}
|
|
4901
|
+
function appendTimestampQuery(url, timestamp) {
|
|
4902
|
+
const hashIndex = url.indexOf("#");
|
|
4903
|
+
const hash = hashIndex >= 0 ? url.slice(hashIndex) : "";
|
|
4904
|
+
const withoutHash = hashIndex >= 0 ? url.slice(0, hashIndex) : url;
|
|
4905
|
+
return `${withoutHash}${withoutHash.includes("?") ? "&" : "?"}t=${timestamp}${hash}`;
|
|
3904
4906
|
}
|
|
3905
4907
|
function externalSpecToModuleUrl(spec, baseDir, root) {
|
|
3906
4908
|
const resolved = resolveNodeModule(baseDir, spec);
|
|
@@ -3913,7 +4915,7 @@ function resolveNodeModule(baseDir, moduleName) {
|
|
|
3913
4915
|
const resolved = resolveNodeModuleEntry(baseDir, moduleName);
|
|
3914
4916
|
if (!resolved) return null;
|
|
3915
4917
|
try {
|
|
3916
|
-
return
|
|
4918
|
+
return fs9.realpathSync(resolved);
|
|
3917
4919
|
} catch {
|
|
3918
4920
|
return resolved;
|
|
3919
4921
|
}
|
|
@@ -3933,21 +4935,21 @@ function resolveNodeModuleEntry(root, moduleName) {
|
|
|
3933
4935
|
let pkgDir = null;
|
|
3934
4936
|
let dir = root;
|
|
3935
4937
|
for (; ; ) {
|
|
3936
|
-
const candidate =
|
|
3937
|
-
if (
|
|
4938
|
+
const candidate = path12.join(dir, "node_modules", pkgName);
|
|
4939
|
+
if (fs9.existsSync(candidate)) {
|
|
3938
4940
|
pkgDir = candidate;
|
|
3939
4941
|
break;
|
|
3940
4942
|
}
|
|
3941
|
-
const parent =
|
|
4943
|
+
const parent = path12.dirname(dir);
|
|
3942
4944
|
if (parent === dir) break;
|
|
3943
4945
|
dir = parent;
|
|
3944
4946
|
}
|
|
3945
4947
|
if (!pkgDir) return null;
|
|
3946
|
-
const pkgJsonPath =
|
|
3947
|
-
if (!
|
|
4948
|
+
const pkgJsonPath = path12.join(pkgDir, "package.json");
|
|
4949
|
+
if (!fs9.existsSync(pkgJsonPath)) return null;
|
|
3948
4950
|
let pkg;
|
|
3949
4951
|
try {
|
|
3950
|
-
pkg = JSON.parse(
|
|
4952
|
+
pkg = JSON.parse(fs9.readFileSync(pkgJsonPath, "utf-8"));
|
|
3951
4953
|
} catch {
|
|
3952
4954
|
return null;
|
|
3953
4955
|
}
|
|
@@ -3960,32 +4962,32 @@ function resolveNodeModuleEntry(root, moduleName) {
|
|
|
3960
4962
|
const subDirs = [""];
|
|
3961
4963
|
for (const field of ["module", "main"]) {
|
|
3962
4964
|
if (typeof pkg[field] === "string") {
|
|
3963
|
-
const dir2 =
|
|
4965
|
+
const dir2 = path12.dirname(pkg[field]);
|
|
3964
4966
|
if (dir2 && dir2 !== "." && !subDirs.includes(dir2)) subDirs.push(dir2);
|
|
3965
4967
|
}
|
|
3966
4968
|
}
|
|
3967
4969
|
for (const dir2 of subDirs) {
|
|
3968
|
-
const direct =
|
|
3969
|
-
if (
|
|
4970
|
+
const direct = path12.join(pkgDir, dir2, subpath);
|
|
4971
|
+
if (fs9.existsSync(direct) && fs9.statSync(direct).isFile()) return direct;
|
|
3970
4972
|
for (const ext of RESOLVE_EXTENSIONS) {
|
|
3971
|
-
if (
|
|
4973
|
+
if (fs9.existsSync(direct + ext)) return direct + ext;
|
|
3972
4974
|
}
|
|
3973
4975
|
}
|
|
3974
4976
|
return null;
|
|
3975
4977
|
}
|
|
3976
4978
|
for (const field of ["module", "jsnext:main", "jsnext", "main"]) {
|
|
3977
4979
|
if (typeof pkg[field] === "string") {
|
|
3978
|
-
const entry =
|
|
3979
|
-
if (
|
|
4980
|
+
const entry = path12.join(pkgDir, pkg[field]);
|
|
4981
|
+
if (fs9.existsSync(entry)) return entry;
|
|
3980
4982
|
}
|
|
3981
4983
|
}
|
|
3982
|
-
const indexFallback =
|
|
3983
|
-
if (
|
|
4984
|
+
const indexFallback = path12.join(pkgDir, "index.js");
|
|
4985
|
+
if (fs9.existsSync(indexFallback)) return indexFallback;
|
|
3984
4986
|
return null;
|
|
3985
4987
|
}
|
|
3986
4988
|
function resolvePackageExports(exports, key, pkgDir) {
|
|
3987
4989
|
if (typeof exports === "string") {
|
|
3988
|
-
return key === "." ?
|
|
4990
|
+
return key === "." ? path12.join(pkgDir, exports) : null;
|
|
3989
4991
|
}
|
|
3990
4992
|
const entry = exports[key];
|
|
3991
4993
|
if (entry === void 0) {
|
|
@@ -3997,7 +4999,7 @@ function resolvePackageExports(exports, key, pkgDir) {
|
|
|
3997
4999
|
return resolveExportValue(entry, pkgDir);
|
|
3998
5000
|
}
|
|
3999
5001
|
function resolveExportValue(value, pkgDir) {
|
|
4000
|
-
if (typeof value === "string") return
|
|
5002
|
+
if (typeof value === "string") return path12.join(pkgDir, value);
|
|
4001
5003
|
if (Array.isArray(value)) {
|
|
4002
5004
|
for (const item of value) {
|
|
4003
5005
|
const r = resolveExportValue(item, pkgDir);
|
|
@@ -4021,54 +5023,62 @@ function resolveUrlToFile(url, root) {
|
|
|
4021
5023
|
const moduleName = cleanUrl.slice("/@modules/".length);
|
|
4022
5024
|
return resolveNodeModule(root, moduleName);
|
|
4023
5025
|
}
|
|
4024
|
-
const filePath =
|
|
4025
|
-
if (
|
|
5026
|
+
const filePath = path12.resolve(root, cleanUrl.replace(/^\//, ""));
|
|
5027
|
+
if (fs9.existsSync(filePath) && fs9.statSync(filePath).isFile()) {
|
|
4026
5028
|
return filePath;
|
|
4027
5029
|
}
|
|
4028
5030
|
for (const ext of RESOLVE_EXTENSIONS) {
|
|
4029
5031
|
const withExt = filePath + ext;
|
|
4030
|
-
if (
|
|
5032
|
+
if (fs9.existsSync(withExt)) return withExt;
|
|
4031
5033
|
}
|
|
4032
5034
|
for (const ext of RESOLVE_EXTENSIONS) {
|
|
4033
|
-
const indexFile =
|
|
4034
|
-
if (
|
|
5035
|
+
const indexFile = path12.join(filePath, "index" + ext);
|
|
5036
|
+
if (fs9.existsSync(indexFile)) return indexFile;
|
|
4035
5037
|
}
|
|
4036
5038
|
return null;
|
|
4037
5039
|
}
|
|
4038
|
-
function isModuleRequest(url) {
|
|
5040
|
+
function isModuleRequest(url, destination) {
|
|
4039
5041
|
const cleanUrl = url.split("?")[0];
|
|
4040
5042
|
if (/\.(ts|tsx|jsx|js|mjs|vue|css|json)$/.test(cleanUrl)) return true;
|
|
4041
5043
|
if (cleanUrl.startsWith("/@modules/")) return true;
|
|
4042
|
-
if (
|
|
5044
|
+
if (isAssetFile(cleanUrl)) {
|
|
5045
|
+
const query = url.includes("?") ? url.slice(url.indexOf("?") + 1) : "";
|
|
5046
|
+
const isExplicitAssetModule = /(?:^|&)(?:url|raw)(?:&|$)/.test(query);
|
|
5047
|
+
return isExplicitAssetModule || destination === "script";
|
|
5048
|
+
}
|
|
5049
|
+
if (!path12.extname(cleanUrl)) return true;
|
|
4043
5050
|
return false;
|
|
4044
5051
|
}
|
|
4045
5052
|
function getHmrClientCode() {
|
|
4046
5053
|
return `
|
|
4047
5054
|
// Nasti HMR Client
|
|
4048
|
-
const
|
|
5055
|
+
const socketProtocol = location.protocol === 'https:' ? 'wss' : 'ws';
|
|
5056
|
+
const socket = new WebSocket(socketProtocol + '://' + location.host, 'nasti-hmr');
|
|
4049
5057
|
const hotModulesMap = new Map();
|
|
4050
5058
|
const disposeMap = new Map();
|
|
4051
5059
|
const pruneMap = new Map();
|
|
5060
|
+
const dataMap = new Map();
|
|
5061
|
+
const customListenersMap = new Map();
|
|
5062
|
+
let updateQueue = [];
|
|
5063
|
+
let pendingUpdateQueue = false;
|
|
4052
5064
|
|
|
4053
5065
|
socket.addEventListener('message', async ({ data }) => {
|
|
4054
5066
|
const payload = JSON.parse(data);
|
|
5067
|
+
// \u9ED8\u8BA4\u6D4F\u89C8\u5668 client \u53EA\u6D88\u8D39\u81EA\u5DF1\u7684 HMR \u6D88\u606F\uFF1Bnative/worker \u73AF\u5883\u901A\u8FC7\u5404\u81EA\u7684
|
|
5068
|
+
// HotChannel \u6216 app-level HMR \u534F\u8C03\u5668\u5904\u7406\u540C\u4E00 transport \u4E0A\u7684\u547D\u540D\u6D88\u606F\u3002
|
|
5069
|
+
if (payload.environment && payload.environment !== 'client') return;
|
|
4055
5070
|
switch (payload.type) {
|
|
4056
5071
|
case 'connected':
|
|
4057
|
-
console.
|
|
5072
|
+
console.debug('[nasti] connected.');
|
|
4058
5073
|
clearErrorOverlay();
|
|
4059
5074
|
break;
|
|
4060
5075
|
case 'update':
|
|
4061
5076
|
try {
|
|
4062
|
-
|
|
4063
|
-
|
|
4064
|
-
|
|
4065
|
-
} else if (update.type === 'css-update') {
|
|
4066
|
-
return updateCss(update.path);
|
|
4067
|
-
}
|
|
4068
|
-
}));
|
|
5077
|
+
// CSS \u5728 unbundled \u6A21\u5F0F\u4E0B\u4E5F\u662F\u4F1A\u6CE8\u5165 <style> \u7684 JS \u6A21\u5757\uFF0C\u548C\u666E\u901A JS
|
|
5078
|
+
// \u4E00\u6837\u91CD\u65B0 import \u624D\u80FD\u6267\u884C dispose/accept \u5E76\u4FDD\u6301\u9875\u9762\u72B6\u6001\u3002
|
|
5079
|
+
await Promise.all(payload.updates.map(queueUpdate));
|
|
4069
5080
|
clearErrorOverlay();
|
|
4070
|
-
console.
|
|
4071
|
-
location.reload();
|
|
5081
|
+
console.debug('[nasti] HMR update complete.');
|
|
4072
5082
|
} catch (err) {
|
|
4073
5083
|
console.error('[nasti] HMR update failed:', err);
|
|
4074
5084
|
showErrorOverlay(err);
|
|
@@ -4079,11 +5089,34 @@ socket.addEventListener('message', async ({ data }) => {
|
|
|
4079
5089
|
location.reload();
|
|
4080
5090
|
break;
|
|
4081
5091
|
case 'prune':
|
|
4082
|
-
payload.paths.
|
|
4083
|
-
const
|
|
4084
|
-
|
|
4085
|
-
|
|
5092
|
+
await Promise.all(payload.paths.map(async (path) => {
|
|
5093
|
+
const data = dataMap.get(path);
|
|
5094
|
+
const dispose = disposeMap.get(path);
|
|
5095
|
+
const prune = pruneMap.get(path);
|
|
5096
|
+
if (dispose) await dispose(data);
|
|
5097
|
+
if (prune) await prune(data);
|
|
5098
|
+
hotModulesMap.delete(path);
|
|
5099
|
+
disposeMap.delete(path);
|
|
5100
|
+
pruneMap.delete(path);
|
|
5101
|
+
dataMap.delete(path);
|
|
5102
|
+
clearCustomListeners(path);
|
|
5103
|
+
}));
|
|
5104
|
+
break;
|
|
5105
|
+
case 'custom': {
|
|
5106
|
+
const listenersByOwner = customListenersMap.get(payload.event);
|
|
5107
|
+
if (!listenersByOwner) break;
|
|
5108
|
+
const results = await Promise.allSettled(
|
|
5109
|
+
[...listenersByOwner.values()]
|
|
5110
|
+
.flatMap((listeners) => [...listeners])
|
|
5111
|
+
.map((listener) => Promise.resolve().then(() => listener(payload.data)))
|
|
5112
|
+
);
|
|
5113
|
+
for (const result of results) {
|
|
5114
|
+
if (result.status === 'rejected') {
|
|
5115
|
+
console.error('[nasti] custom HMR event listener failed:', result.reason);
|
|
5116
|
+
}
|
|
5117
|
+
}
|
|
4086
5118
|
break;
|
|
5119
|
+
}
|
|
4087
5120
|
case 'error':
|
|
4088
5121
|
console.error('[nasti] error:', payload.err.message);
|
|
4089
5122
|
showErrorOverlay(payload.err);
|
|
@@ -4091,33 +5124,64 @@ socket.addEventListener('message', async ({ data }) => {
|
|
|
4091
5124
|
}
|
|
4092
5125
|
});
|
|
4093
5126
|
|
|
4094
|
-
// \
|
|
5127
|
+
// \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
|
|
4095
5128
|
let reconnectTimer = 0;
|
|
4096
5129
|
socket.addEventListener('close', () => {
|
|
4097
5130
|
clearTimeout(reconnectTimer);
|
|
4098
5131
|
reconnectTimer = setTimeout(() => location.reload(), 1000);
|
|
4099
5132
|
});
|
|
4100
5133
|
|
|
5134
|
+
/**
|
|
5135
|
+
* \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
|
|
5136
|
+
* \u6539\u53D8\u6A21\u5757\u5E94\u7528\u987A\u5E8F\u3002\u8FD9\u4E0E Vite HMRClient \u7684 fetch/apply \u4E24\u9636\u6BB5\u4E00\u81F4\u3002
|
|
5137
|
+
*/
|
|
5138
|
+
async function queueUpdate(update) {
|
|
5139
|
+
updateQueue.push(fetchUpdate(update));
|
|
5140
|
+
if (pendingUpdateQueue) return;
|
|
5141
|
+
|
|
5142
|
+
pendingUpdateQueue = true;
|
|
5143
|
+
await Promise.resolve();
|
|
5144
|
+
pendingUpdateQueue = false;
|
|
5145
|
+
const loading = updateQueue;
|
|
5146
|
+
updateQueue = [];
|
|
5147
|
+
const applyUpdates = await Promise.all(loading);
|
|
5148
|
+
for (const apply of applyUpdates) {
|
|
5149
|
+
if (apply) apply();
|
|
5150
|
+
}
|
|
5151
|
+
}
|
|
5152
|
+
|
|
4101
5153
|
async function fetchUpdate(update) {
|
|
4102
5154
|
const mod = hotModulesMap.get(update.path);
|
|
4103
|
-
// \
|
|
4104
|
-
|
|
4105
|
-
if (dispose) dispose();
|
|
5155
|
+
// \u5C1A\u672A\u5728\u5F53\u524D\u9875\u9762\u52A0\u8F7D\u7684\u52A8\u6001\u6A21\u5757\u4E0D\u9700\u8981\u66F4\u65B0\u3002
|
|
5156
|
+
if (!mod) return;
|
|
4106
5157
|
|
|
4107
|
-
|
|
4108
|
-
|
|
4109
|
-
|
|
4110
|
-
|
|
4111
|
-
|
|
5158
|
+
// \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
|
|
5159
|
+
const qualifiedCallbacks = mod.callbacks.filter(({ deps }) =>
|
|
5160
|
+
deps.includes(update.acceptedPath)
|
|
5161
|
+
);
|
|
5162
|
+
const isSelfUpdate = update.path === update.acceptedPath;
|
|
5163
|
+
if (!isSelfUpdate && qualifiedCallbacks.length === 0) return;
|
|
5164
|
+
|
|
5165
|
+
const dispose = disposeMap.get(update.acceptedPath);
|
|
5166
|
+
if (dispose) await dispose(dataMap.get(update.acceptedPath));
|
|
5167
|
+
const newMod = await import(appendTimestampQuery(update.acceptedPath, update.timestamp));
|
|
5168
|
+
|
|
5169
|
+
return () => {
|
|
5170
|
+
for (const { deps, fn } of qualifiedCallbacks) {
|
|
5171
|
+
fn(deps.map((dep) => dep === update.acceptedPath ? newMod : undefined));
|
|
5172
|
+
}
|
|
5173
|
+
const detail = isSelfUpdate
|
|
5174
|
+
? update.path
|
|
5175
|
+
: update.acceptedPath + ' via ' + update.path;
|
|
5176
|
+
console.debug('[nasti] hot updated:', detail);
|
|
5177
|
+
};
|
|
4112
5178
|
}
|
|
4113
5179
|
|
|
4114
|
-
function
|
|
4115
|
-
const
|
|
4116
|
-
|
|
4117
|
-
|
|
4118
|
-
|
|
4119
|
-
.then(css => { el.textContent = css; });
|
|
4120
|
-
}
|
|
5180
|
+
function appendTimestampQuery(url, timestamp) {
|
|
5181
|
+
const hashIndex = url.indexOf('#');
|
|
5182
|
+
const hash = hashIndex >= 0 ? url.slice(hashIndex) : '';
|
|
5183
|
+
const withoutHash = hashIndex >= 0 ? url.slice(0, hashIndex) : url;
|
|
5184
|
+
return withoutHash + (withoutHash.includes('?') ? '&' : '?') + 't=' + timestamp + hash;
|
|
4121
5185
|
}
|
|
4122
5186
|
|
|
4123
5187
|
function clearErrorOverlay() {
|
|
@@ -4145,23 +5209,31 @@ function showErrorOverlay(err) {
|
|
|
4145
5209
|
document.body.appendChild(overlay);
|
|
4146
5210
|
}
|
|
4147
5211
|
|
|
4148
|
-
/**
|
|
4149
|
-
* \u751F\u6210 import.meta.hot \u7684 hot context\u3002
|
|
4150
|
-
* \u5173\u952E\u7EA6\u675F\uFF1A\u540C\u4E00 ownerPath \u7684 accept \u56DE\u8C03\u5FC5\u987B\u66FF\u6362\uFF08\u4E0D\u662F append\uFF09\u3002
|
|
4151
|
-
* \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
|
|
4152
|
-
* \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
|
|
4153
|
-
*/
|
|
4154
5212
|
export function createHotContext(ownerPath) {
|
|
5213
|
+
if (!dataMap.has(ownerPath)) dataMap.set(ownerPath, {});
|
|
5214
|
+
|
|
5215
|
+
// \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
|
|
5216
|
+
const existing = hotModulesMap.get(ownerPath);
|
|
5217
|
+
if (existing) existing.callbacks = [];
|
|
5218
|
+
clearCustomListeners(ownerPath);
|
|
5219
|
+
|
|
5220
|
+
const acceptDeps = (deps, callback = () => {}) => {
|
|
5221
|
+
const mod = hotModulesMap.get(ownerPath) || { id: ownerPath, callbacks: [] };
|
|
5222
|
+
mod.callbacks.push({ deps, fn: callback });
|
|
5223
|
+
hotModulesMap.set(ownerPath, mod);
|
|
5224
|
+
};
|
|
5225
|
+
|
|
4155
5226
|
return {
|
|
4156
5227
|
accept(deps, callback) {
|
|
4157
|
-
// \u81EA\u63A5\u53D7: hot.accept() \u6216 hot.accept(callback)
|
|
4158
5228
|
if (typeof deps === 'function' || deps === undefined) {
|
|
4159
|
-
|
|
4160
|
-
|
|
5229
|
+
acceptDeps([ownerPath], ([mod]) => deps?.(mod));
|
|
5230
|
+
} else if (typeof deps === 'string') {
|
|
5231
|
+
acceptDeps([deps], ([mod]) => callback?.(mod));
|
|
5232
|
+
} else if (Array.isArray(deps)) {
|
|
5233
|
+
acceptDeps(deps, callback);
|
|
5234
|
+
} else {
|
|
5235
|
+
throw new Error('invalid hot.accept() usage');
|
|
4161
5236
|
}
|
|
4162
|
-
// \u4F9D\u8D56\u63A5\u53D7: hot.accept(deps, callback)\uFF0C\u591A\u6B21\u8C03\u7528\u8FFD\u52A0
|
|
4163
|
-
const existing = hotModulesMap.get(ownerPath)?.callbacks ?? [];
|
|
4164
|
-
hotModulesMap.set(ownerPath, { callbacks: [...existing, callback] });
|
|
4165
5237
|
},
|
|
4166
5238
|
prune(callback) {
|
|
4167
5239
|
pruneMap.set(ownerPath, callback);
|
|
@@ -4169,24 +5241,116 @@ export function createHotContext(ownerPath) {
|
|
|
4169
5241
|
dispose(callback) {
|
|
4170
5242
|
disposeMap.set(ownerPath, callback);
|
|
4171
5243
|
},
|
|
5244
|
+
on(event, callback) {
|
|
5245
|
+
let listenersByOwner = customListenersMap.get(event);
|
|
5246
|
+
if (!listenersByOwner) {
|
|
5247
|
+
listenersByOwner = new Map();
|
|
5248
|
+
customListenersMap.set(event, listenersByOwner);
|
|
5249
|
+
}
|
|
5250
|
+
let listeners = listenersByOwner.get(ownerPath);
|
|
5251
|
+
if (!listeners) {
|
|
5252
|
+
listeners = new Set();
|
|
5253
|
+
listenersByOwner.set(ownerPath, listeners);
|
|
5254
|
+
}
|
|
5255
|
+
listeners.add(callback);
|
|
5256
|
+
},
|
|
5257
|
+
off(event, callback) {
|
|
5258
|
+
const listenersByOwner = customListenersMap.get(event);
|
|
5259
|
+
const listeners = listenersByOwner?.get(ownerPath);
|
|
5260
|
+
listeners?.delete(callback);
|
|
5261
|
+
if (listeners?.size === 0) listenersByOwner.delete(ownerPath);
|
|
5262
|
+
if (listenersByOwner?.size === 0) customListenersMap.delete(event);
|
|
5263
|
+
},
|
|
4172
5264
|
invalidate() {
|
|
4173
5265
|
location.reload();
|
|
4174
5266
|
},
|
|
4175
|
-
data:
|
|
5267
|
+
data: dataMap.get(ownerPath),
|
|
4176
5268
|
};
|
|
4177
5269
|
}
|
|
5270
|
+
|
|
5271
|
+
function clearCustomListeners(ownerPath) {
|
|
5272
|
+
for (const [event, listenersByOwner] of customListenersMap) {
|
|
5273
|
+
listenersByOwner.delete(ownerPath);
|
|
5274
|
+
if (listenersByOwner.size === 0) customListenersMap.delete(event);
|
|
5275
|
+
}
|
|
5276
|
+
}
|
|
4178
5277
|
`;
|
|
4179
5278
|
}
|
|
4180
|
-
var __dirname_esm, __require2, __refreshRuntimeCache, REACT_REFRESH_GLOBAL_PREAMBLE, esmBundleCache, VALID_IDENT, RESOLVE_EXTENSIONS, ESM_CONDITIONS;
|
|
5279
|
+
var __dirname_esm, __require2, __refreshRuntimeCache, REACT_REFRESH_BOUNDARY_HELPERS, REACT_REFRESH_GLOBAL_PREAMBLE, esmBundleCache, VALID_IDENT, RESOLVE_EXTENSIONS, ESM_CONDITIONS;
|
|
4181
5280
|
var init_middleware = __esm({
|
|
4182
5281
|
"src/server/middleware.ts"() {
|
|
4183
5282
|
"use strict";
|
|
4184
5283
|
init_transformer();
|
|
4185
5284
|
init_html();
|
|
4186
5285
|
init_env();
|
|
4187
|
-
|
|
5286
|
+
init_url();
|
|
5287
|
+
init_assets();
|
|
5288
|
+
__dirname_esm = path12.dirname(fileURLToPath(import.meta.url));
|
|
4188
5289
|
__require2 = createRequire3(import.meta.url);
|
|
4189
5290
|
__refreshRuntimeCache = null;
|
|
5291
|
+
REACT_REFRESH_BOUNDARY_HELPERS = `
|
|
5292
|
+
function __nastiIsPlainObject(obj) {
|
|
5293
|
+
return Object.prototype.toString.call(obj) === '[object Object]' &&
|
|
5294
|
+
(obj.constructor === Object || obj.constructor === undefined);
|
|
5295
|
+
}
|
|
5296
|
+
function __nastiIsCompoundComponent(type) {
|
|
5297
|
+
if (!__nastiIsPlainObject(type)) return false;
|
|
5298
|
+
for (const key in type) {
|
|
5299
|
+
if (!isLikelyComponentType(type[key])) return false;
|
|
5300
|
+
}
|
|
5301
|
+
return true;
|
|
5302
|
+
}
|
|
5303
|
+
export function registerExportsForReactRefresh(filename, moduleExports) {
|
|
5304
|
+
for (const key in moduleExports) {
|
|
5305
|
+
if (key === '__esModule') continue;
|
|
5306
|
+
const value = moduleExports[key];
|
|
5307
|
+
if (isLikelyComponentType(value)) {
|
|
5308
|
+
register(value, filename + ' export ' + key);
|
|
5309
|
+
} else if (__nastiIsCompoundComponent(value)) {
|
|
5310
|
+
for (const subKey in value) {
|
|
5311
|
+
register(value[subKey], filename + ' export ' + key + '-' + subKey);
|
|
5312
|
+
}
|
|
5313
|
+
}
|
|
5314
|
+
}
|
|
5315
|
+
}
|
|
5316
|
+
let __nastiRefreshTimer;
|
|
5317
|
+
function __nastiEnqueueRefresh() {
|
|
5318
|
+
clearTimeout(__nastiRefreshTimer);
|
|
5319
|
+
__nastiRefreshTimer = setTimeout(() => performReactRefresh(), 16);
|
|
5320
|
+
}
|
|
5321
|
+
function __nastiCheckExports(ignored, exports, predicate) {
|
|
5322
|
+
for (const key in exports) {
|
|
5323
|
+
if (ignored.includes(key)) continue;
|
|
5324
|
+
if (!predicate(key, exports[key])) return key;
|
|
5325
|
+
}
|
|
5326
|
+
return true;
|
|
5327
|
+
}
|
|
5328
|
+
export function validateRefreshBoundaryAndEnqueueUpdate(id, prevExports, nextExports) {
|
|
5329
|
+
const ignored = window.__getReactRefreshIgnoredExports?.({ id }) ?? [];
|
|
5330
|
+
if (__nastiCheckExports(ignored, prevExports, (key) => key in nextExports) !== true) {
|
|
5331
|
+
return 'Could not Fast Refresh (export removed)';
|
|
5332
|
+
}
|
|
5333
|
+
if (__nastiCheckExports(ignored, nextExports, (key) => key in prevExports) !== true) {
|
|
5334
|
+
return 'Could not Fast Refresh (new export)';
|
|
5335
|
+
}
|
|
5336
|
+
let hasExports = false;
|
|
5337
|
+
const compatible = __nastiCheckExports(ignored, nextExports, (key, value) => {
|
|
5338
|
+
hasExports = true;
|
|
5339
|
+
return isLikelyComponentType(value) ||
|
|
5340
|
+
__nastiIsCompoundComponent(value) ||
|
|
5341
|
+
prevExports[key] === value;
|
|
5342
|
+
});
|
|
5343
|
+
if (!hasExports) {
|
|
5344
|
+
return 'Could not Fast Refresh (no exports)';
|
|
5345
|
+
}
|
|
5346
|
+
if (compatible === true) {
|
|
5347
|
+
__nastiEnqueueRefresh();
|
|
5348
|
+
return;
|
|
5349
|
+
}
|
|
5350
|
+
return 'Could not Fast Refresh ("' + compatible + '" export is incompatible)';
|
|
5351
|
+
}
|
|
5352
|
+
export const __hmr_import = (module) => import(module);
|
|
5353
|
+
`;
|
|
4190
5354
|
REACT_REFRESH_GLOBAL_PREAMBLE = `
|
|
4191
5355
|
import RefreshRuntime from "/@react-refresh";
|
|
4192
5356
|
RefreshRuntime.injectIntoGlobalHook(window);
|
|
@@ -4202,31 +5366,40 @@ window.__vite_plugin_react_preamble_installed__ = true;
|
|
|
4202
5366
|
});
|
|
4203
5367
|
|
|
4204
5368
|
// src/server/hmr.ts
|
|
4205
|
-
import
|
|
4206
|
-
import
|
|
5369
|
+
import path13 from "path";
|
|
5370
|
+
import fs10 from "fs";
|
|
4207
5371
|
import pc7 from "picocolors";
|
|
4208
|
-
async function handleFileChange(file, server) {
|
|
4209
|
-
const {
|
|
5372
|
+
async function handleFileChange(file, server, environmentName = "client", timestamp = Date.now()) {
|
|
5373
|
+
const { config } = server;
|
|
5374
|
+
const environment = server.environments[environmentName];
|
|
5375
|
+
if (!environment) {
|
|
5376
|
+
throw new Error(`[nasti] unknown dev environment "${environmentName}"`);
|
|
5377
|
+
}
|
|
5378
|
+
const moduleGraph = environment.moduleGraph;
|
|
4210
5379
|
const logger = config.logger;
|
|
4211
|
-
const relativePath = "/" +
|
|
4212
|
-
const shortFile =
|
|
5380
|
+
const relativePath = "/" + path13.relative(config.root, file);
|
|
5381
|
+
const shortFile = path13.relative(config.root, file);
|
|
4213
5382
|
const mods = moduleGraph.getModulesByFile(file);
|
|
4214
5383
|
if (!mods || mods.size === 0) {
|
|
4215
|
-
return;
|
|
5384
|
+
return null;
|
|
4216
5385
|
}
|
|
4217
5386
|
const updates = [];
|
|
4218
|
-
const
|
|
5387
|
+
const graph = moduleGraph;
|
|
5388
|
+
const invalidatedModules = /* @__PURE__ */ new Set();
|
|
5389
|
+
const affectedSet = /* @__PURE__ */ new Set();
|
|
5390
|
+
let fullReload = false;
|
|
4219
5391
|
for (const mod of mods) {
|
|
4220
|
-
|
|
5392
|
+
graph.invalidateModuleAndImporters(mod, timestamp, invalidatedModules);
|
|
4221
5393
|
const ctx = {
|
|
4222
5394
|
file,
|
|
4223
5395
|
timestamp,
|
|
4224
5396
|
modules: [mod],
|
|
4225
|
-
read: () =>
|
|
4226
|
-
server
|
|
5397
|
+
read: () => fs10.readFileSync(file, "utf-8"),
|
|
5398
|
+
server,
|
|
5399
|
+
environment
|
|
4227
5400
|
};
|
|
4228
5401
|
let affectedModules = [mod];
|
|
4229
|
-
for (const plugin of
|
|
5402
|
+
for (const plugin of environment.plugins) {
|
|
4230
5403
|
if (plugin.handleHotUpdate) {
|
|
4231
5404
|
const result = await plugin.handleHotUpdate(ctx);
|
|
4232
5405
|
if (result) {
|
|
@@ -4235,29 +5408,52 @@ async function handleFileChange(file, server) {
|
|
|
4235
5408
|
}
|
|
4236
5409
|
}
|
|
4237
5410
|
for (const affected of affectedModules) {
|
|
4238
|
-
|
|
5411
|
+
affectedSet.add(affected);
|
|
5412
|
+
graph.invalidateModuleAndImporters(affected, timestamp, invalidatedModules);
|
|
5413
|
+
const boundaries = graph.getHmrBoundaries(affected);
|
|
4239
5414
|
if (boundaries.length === 0) {
|
|
4240
|
-
|
|
4241
|
-
|
|
4242
|
-
return;
|
|
5415
|
+
fullReload = true;
|
|
5416
|
+
continue;
|
|
4243
5417
|
}
|
|
4244
|
-
for (const { boundary } of boundaries) {
|
|
4245
|
-
|
|
5418
|
+
for (const { boundary, acceptedVia } of boundaries) {
|
|
5419
|
+
const update = {
|
|
4246
5420
|
type: boundary.type === "css" ? "css-update" : "js-update",
|
|
4247
5421
|
path: boundary.url,
|
|
4248
|
-
acceptedPath:
|
|
5422
|
+
acceptedPath: acceptedVia.url,
|
|
4249
5423
|
timestamp
|
|
4250
|
-
}
|
|
5424
|
+
};
|
|
5425
|
+
if (!updates.some(
|
|
5426
|
+
(existing) => existing.type === update.type && existing.path === update.path && existing.acceptedPath === update.acceptedPath
|
|
5427
|
+
)) {
|
|
5428
|
+
updates.push(update);
|
|
5429
|
+
}
|
|
4251
5430
|
}
|
|
4252
5431
|
}
|
|
4253
5432
|
}
|
|
4254
|
-
|
|
5433
|
+
const transformed = await Promise.all(
|
|
5434
|
+
[...affectedSet].map(async (module) => ({
|
|
5435
|
+
module,
|
|
5436
|
+
result: await environment.transformRequest(module.url)
|
|
5437
|
+
}))
|
|
5438
|
+
);
|
|
5439
|
+
const logPrefix = environmentName === "client" ? "" : `[${environmentName}] `;
|
|
5440
|
+
if (fullReload) {
|
|
5441
|
+
logger.info(pc7.green(`${logPrefix}reload `) + pc7.dim(shortFile), { timestamp: true });
|
|
5442
|
+
environment.hot.send({ type: "full-reload", path: relativePath });
|
|
5443
|
+
} else if (updates.length > 0) {
|
|
4255
5444
|
logger.info(
|
|
4256
|
-
updates.map((u) => pc7.green(
|
|
5445
|
+
updates.map((u) => pc7.green(`${logPrefix}hmr update `) + pc7.dim(u.path)).join("\n"),
|
|
4257
5446
|
{ timestamp: true }
|
|
4258
5447
|
);
|
|
4259
|
-
|
|
5448
|
+
environment.hot.send({ type: "update", updates });
|
|
4260
5449
|
}
|
|
5450
|
+
return {
|
|
5451
|
+
environment,
|
|
5452
|
+
modules: [...affectedSet],
|
|
5453
|
+
updates,
|
|
5454
|
+
transformed,
|
|
5455
|
+
fullReload
|
|
5456
|
+
};
|
|
4261
5457
|
}
|
|
4262
5458
|
var init_hmr = __esm({
|
|
4263
5459
|
"src/server/hmr.ts"() {
|
|
@@ -4271,8 +5467,8 @@ __export(runnable_environment_exports, {
|
|
|
4271
5467
|
NastiModuleRunner: () => NastiModuleRunner,
|
|
4272
5468
|
createModuleRunner: () => createModuleRunner
|
|
4273
5469
|
});
|
|
4274
|
-
import
|
|
4275
|
-
import
|
|
5470
|
+
import path14 from "path";
|
|
5471
|
+
import fs11 from "fs";
|
|
4276
5472
|
import { builtinModules as builtinModules3, createRequire as createRequire4 } from "module";
|
|
4277
5473
|
import { pathToFileURL as pathToFileURL4 } from "url";
|
|
4278
5474
|
function createModuleRunner(environment) {
|
|
@@ -4283,14 +5479,14 @@ function createModuleRunner(environment) {
|
|
|
4283
5479
|
}
|
|
4284
5480
|
return new NastiModuleRunner(environment);
|
|
4285
5481
|
}
|
|
4286
|
-
var
|
|
5482
|
+
var debug6, NODE_BUILTINS3, NastiModuleRunner, AsyncFunction;
|
|
4287
5483
|
var init_runnable_environment = __esm({
|
|
4288
5484
|
"src/server/runnable-environment.ts"() {
|
|
4289
5485
|
"use strict";
|
|
4290
5486
|
init_transformer();
|
|
4291
5487
|
init_env();
|
|
4292
5488
|
init_debug();
|
|
4293
|
-
|
|
5489
|
+
debug6 = createDebugger("nasti:ssr");
|
|
4294
5490
|
NODE_BUILTINS3 = /* @__PURE__ */ new Set([...builtinModules3, ...builtinModules3.map((m) => `node:${m}`)]);
|
|
4295
5491
|
NastiModuleRunner = class {
|
|
4296
5492
|
environment;
|
|
@@ -4306,7 +5502,7 @@ var init_runnable_environment = __esm({
|
|
|
4306
5502
|
this.config.mode,
|
|
4307
5503
|
ssrDefineOverrides(environment.consumer)
|
|
4308
5504
|
);
|
|
4309
|
-
this.require = createRequire4(
|
|
5505
|
+
this.require = createRequire4(path14.join(this.config.root, "package.json"));
|
|
4310
5506
|
const handlers = {
|
|
4311
5507
|
fetchModule: async (id, importer) => this.fetchModule(id, importer),
|
|
4312
5508
|
getBuiltins: () => [/^node:/, ...builtinModules3]
|
|
@@ -4330,9 +5526,9 @@ var init_runnable_environment = __esm({
|
|
|
4330
5526
|
this.cache.clear();
|
|
4331
5527
|
}
|
|
4332
5528
|
resolveToId(rawUrl) {
|
|
4333
|
-
if (
|
|
5529
|
+
if (path14.isAbsolute(rawUrl) && fs11.existsSync(rawUrl.split("?")[0])) return rawUrl;
|
|
4334
5530
|
const clean = rawUrl.replace(/^\//, "");
|
|
4335
|
-
return
|
|
5531
|
+
return path14.resolve(this.config.root, clean);
|
|
4336
5532
|
}
|
|
4337
5533
|
/**
|
|
4338
5534
|
* fetchModule(invoke 契约方法):环境管线产出 runner 可执行代码。
|
|
@@ -4341,14 +5537,14 @@ var init_runnable_environment = __esm({
|
|
|
4341
5537
|
*/
|
|
4342
5538
|
async fetchModule(id, importer) {
|
|
4343
5539
|
if (NODE_BUILTINS3.has(id)) return { externalize: id };
|
|
4344
|
-
if (!id.startsWith(".") && !
|
|
5540
|
+
if (!id.startsWith(".") && !path14.isAbsolute(id) && !id.startsWith("\0")) {
|
|
4345
5541
|
return { externalize: id };
|
|
4346
5542
|
}
|
|
4347
5543
|
const container = this.environment.pluginContainer;
|
|
4348
5544
|
let resolvedId = id;
|
|
4349
5545
|
if (id.startsWith(".") && importer) {
|
|
4350
5546
|
const resolved = await container.resolveId(id, importer);
|
|
4351
|
-
resolvedId = resolved ? typeof resolved === "string" ? resolved : resolved.id :
|
|
5547
|
+
resolvedId = resolved ? typeof resolved === "string" ? resolved : resolved.id : path14.resolve(path14.dirname(importer.split("?")[0]), id);
|
|
4352
5548
|
}
|
|
4353
5549
|
resolvedId = this.completeExtension(resolvedId);
|
|
4354
5550
|
const cleanId = resolvedId.split("?")[0];
|
|
@@ -4356,8 +5552,8 @@ var init_runnable_environment = __esm({
|
|
|
4356
5552
|
const loaded = await container.load(resolvedId);
|
|
4357
5553
|
if (loaded != null) {
|
|
4358
5554
|
code = typeof loaded === "string" ? loaded : loaded.code;
|
|
4359
|
-
} else if (
|
|
4360
|
-
code =
|
|
5555
|
+
} else if (fs11.existsSync(cleanId)) {
|
|
5556
|
+
code = fs11.readFileSync(cleanId, "utf-8");
|
|
4361
5557
|
} else {
|
|
4362
5558
|
throw new Error(`[nasti:ssr] cannot load module: ${resolvedId}`);
|
|
4363
5559
|
}
|
|
@@ -4368,6 +5564,7 @@ var init_runnable_environment = __esm({
|
|
|
4368
5564
|
if (shouldTransform(cleanId)) {
|
|
4369
5565
|
const result = transformCode(cleanId, code, {
|
|
4370
5566
|
sourcemap: false,
|
|
5567
|
+
target: this.environment.options.build.target,
|
|
4371
5568
|
jsxRuntime: "automatic",
|
|
4372
5569
|
jsxImportSource: this.config.framework === "vue" ? "vue" : "react"
|
|
4373
5570
|
});
|
|
@@ -4384,25 +5581,25 @@ var init_runnable_environment = __esm({
|
|
|
4384
5581
|
);
|
|
4385
5582
|
}
|
|
4386
5583
|
const runnerResult = await moduleRunnerTransform(resolvedId, code);
|
|
4387
|
-
|
|
5584
|
+
debug6?.(`fetchModule ${resolvedId} (${runnerResult.deps?.length ?? 0} deps)`);
|
|
4388
5585
|
return { id: resolvedId, code: runnerResult.code };
|
|
4389
5586
|
}
|
|
4390
5587
|
completeExtension(id) {
|
|
4391
5588
|
const clean = id.split("?")[0];
|
|
4392
5589
|
const query = id.includes("?") ? id.slice(id.indexOf("?")) : "";
|
|
4393
|
-
if (
|
|
5590
|
+
if (fs11.existsSync(clean) && fs11.statSync(clean).isFile()) return id;
|
|
4394
5591
|
const jsMatch = clean.match(/^(.*)\.([mc]?)jsx?$/);
|
|
4395
5592
|
if (jsMatch) {
|
|
4396
5593
|
for (const tsExt of [`.${jsMatch[2]}ts`, `.${jsMatch[2]}tsx`]) {
|
|
4397
|
-
if (
|
|
5594
|
+
if (fs11.existsSync(jsMatch[1] + tsExt)) return jsMatch[1] + tsExt + query;
|
|
4398
5595
|
}
|
|
4399
5596
|
}
|
|
4400
5597
|
for (const ext of this.config.resolve.extensions) {
|
|
4401
|
-
if (
|
|
5598
|
+
if (fs11.existsSync(clean + ext)) return clean + ext + query;
|
|
4402
5599
|
}
|
|
4403
5600
|
for (const ext of this.config.resolve.extensions) {
|
|
4404
|
-
const indexPath =
|
|
4405
|
-
if (
|
|
5601
|
+
const indexPath = path14.join(clean, `index${ext}`);
|
|
5602
|
+
if (fs11.existsSync(indexPath)) return indexPath;
|
|
4406
5603
|
}
|
|
4407
5604
|
return id;
|
|
4408
5605
|
}
|
|
@@ -4429,10 +5626,10 @@ var init_runnable_environment = __esm({
|
|
|
4429
5626
|
return;
|
|
4430
5627
|
}
|
|
4431
5628
|
const ssrImport = async (dep) => {
|
|
4432
|
-
if (NODE_BUILTINS3.has(dep) || !dep.startsWith(".") && !
|
|
5629
|
+
if (NODE_BUILTINS3.has(dep) || !dep.startsWith(".") && !path14.isAbsolute(dep) && !dep.startsWith("\0")) {
|
|
4433
5630
|
return this.importExternal(dep);
|
|
4434
5631
|
}
|
|
4435
|
-
const depId = dep.startsWith(".") ? this.completeExtension(
|
|
5632
|
+
const depId = dep.startsWith(".") ? this.completeExtension(path14.resolve(path14.dirname(fetched.id.split("?")[0]), dep)) : this.completeExtension(dep);
|
|
4436
5633
|
return this.instantiate(depId);
|
|
4437
5634
|
};
|
|
4438
5635
|
const ssrExportAll = (sourceModule) => {
|
|
@@ -4464,7 +5661,7 @@ var init_runnable_environment = __esm({
|
|
|
4464
5661
|
}
|
|
4465
5662
|
async importExternal(spec) {
|
|
4466
5663
|
try {
|
|
4467
|
-
return await (spec.startsWith("node:") || !
|
|
5664
|
+
return await (spec.startsWith("node:") || !path14.isAbsolute(spec) ? import(this.resolveExternalSpecifier(spec)) : import(pathToFileURL4(spec).href));
|
|
4468
5665
|
} catch (err) {
|
|
4469
5666
|
throw new Error(`[nasti:ssr] failed to import external "${spec}": ${err.message}`);
|
|
4470
5667
|
}
|
|
@@ -4490,7 +5687,7 @@ var dev_engine_exports = {};
|
|
|
4490
5687
|
__export(dev_engine_exports, {
|
|
4491
5688
|
createBundledDevServer: () => createBundledDevServer
|
|
4492
5689
|
});
|
|
4493
|
-
import
|
|
5690
|
+
import path15 from "path";
|
|
4494
5691
|
import crypto3 from "crypto";
|
|
4495
5692
|
import { WebSocketServer as WsServer2 } from "ws";
|
|
4496
5693
|
import pc8 from "picocolors";
|
|
@@ -4508,7 +5705,7 @@ async function createBundledDevServer(opts) {
|
|
|
4508
5705
|
}
|
|
4509
5706
|
} catch (err) {
|
|
4510
5707
|
throw new Error(
|
|
4511
|
-
`[nasti] experimental.bundledDev requires rolldown's experimental dev() API (locked
|
|
5708
|
+
`[nasti] experimental.bundledDev requires rolldown's experimental dev() API (locked version is incompatible; got: ${err.message}). Remove --bundle / experimental.bundledDev to use the default unbundled dev server.`
|
|
4512
5709
|
);
|
|
4513
5710
|
}
|
|
4514
5711
|
const html = await readHtmlFile(config.root, config.environments.client?.html);
|
|
@@ -4526,7 +5723,7 @@ async function createBundledDevServer(opts) {
|
|
|
4526
5723
|
createReactRefreshRuntimePlugin(entryPoints),
|
|
4527
5724
|
createBundledOxcRefreshPlugin()
|
|
4528
5725
|
] : [],
|
|
4529
|
-
...stripCatchAllLoad(toRolldownPlugins(clientEnv.plugins)),
|
|
5726
|
+
...stripCatchAllLoad(toRolldownPlugins(clientEnv.plugins, clientEnv)),
|
|
4530
5727
|
...useReactRefresh ? [
|
|
4531
5728
|
refreshWrapperFn({
|
|
4532
5729
|
cwd: config.root,
|
|
@@ -4561,7 +5758,7 @@ async function createBundledDevServer(opts) {
|
|
|
4561
5758
|
for (const { clientId, update } of updates) {
|
|
4562
5759
|
if (update.type === "Noop") continue;
|
|
4563
5760
|
if (update.type === "FullReload") {
|
|
4564
|
-
|
|
5761
|
+
debug7?.(`full reload for ${clientId}: ${update.reason ?? ""}`);
|
|
4565
5762
|
needsLatestOutput = true;
|
|
4566
5763
|
continue;
|
|
4567
5764
|
}
|
|
@@ -4575,7 +5772,7 @@ async function createBundledDevServer(opts) {
|
|
|
4575
5772
|
}
|
|
4576
5773
|
const url = `/${patchPath}`;
|
|
4577
5774
|
logger.info(
|
|
4578
|
-
pc8.green("hmr update ") + pc8.dim(changedFiles.map((f) =>
|
|
5775
|
+
pc8.green("hmr update ") + pc8.dim(changedFiles.map((f) => path15.relative(config.root, f)).join(", ")),
|
|
4579
5776
|
{ timestamp: true }
|
|
4580
5777
|
);
|
|
4581
5778
|
sendTo(clientId, { type: "hmr:update", path: url, url });
|
|
@@ -4611,7 +5808,7 @@ async function createBundledDevServer(opts) {
|
|
|
4611
5808
|
},
|
|
4612
5809
|
{
|
|
4613
5810
|
watch: { skipWrite: true },
|
|
4614
|
-
rebuildStrategy: "
|
|
5811
|
+
rebuildStrategy: "never",
|
|
4615
5812
|
onOutput(result) {
|
|
4616
5813
|
if (result instanceof Error) {
|
|
4617
5814
|
logger.error(pc8.red(`[bundled] build error: ${result.message}`), { error: result });
|
|
@@ -4627,7 +5824,13 @@ async function createBundledDevServer(opts) {
|
|
|
4627
5824
|
memoryFiles.set(`${file.fileName}.map`, JSON.stringify(file.map));
|
|
4628
5825
|
}
|
|
4629
5826
|
}
|
|
4630
|
-
|
|
5827
|
+
debug7?.(`bundle output refreshed (${result.output.length} files)`);
|
|
5828
|
+
},
|
|
5829
|
+
onAdditionalAssets(result) {
|
|
5830
|
+
for (const file of result.output) {
|
|
5831
|
+
const content = file.type === "chunk" ? file.code : file.source;
|
|
5832
|
+
if (content != null) memoryFiles.set(file.fileName, content);
|
|
5833
|
+
}
|
|
4631
5834
|
},
|
|
4632
5835
|
async onHmrUpdates(result) {
|
|
4633
5836
|
if (result instanceof Error) {
|
|
@@ -4636,7 +5839,7 @@ async function createBundledDevServer(opts) {
|
|
|
4636
5839
|
return;
|
|
4637
5840
|
}
|
|
4638
5841
|
const { updates, changedFiles } = result;
|
|
4639
|
-
|
|
5842
|
+
debug7?.(
|
|
4640
5843
|
`onHmrUpdates(engine watcher): ${changedFiles.length} changed, ${updates.length} updates`
|
|
4641
5844
|
);
|
|
4642
5845
|
if (changedFiles.length === 0) return;
|
|
@@ -4655,24 +5858,29 @@ async function createBundledDevServer(opts) {
|
|
|
4655
5858
|
if (!clientId) return;
|
|
4656
5859
|
wss.handleUpgrade(req, socket, head, (ws) => {
|
|
4657
5860
|
bundledClients.set(clientId, ws);
|
|
4658
|
-
|
|
4659
|
-
|
|
5861
|
+
debug7?.(`bundled client connected: ${clientId}`);
|
|
5862
|
+
void engine.registerClient(clientId).then(async () => {
|
|
5863
|
+
for (const fileName of entryFileNames.values()) {
|
|
5864
|
+
await engine.notifyPayloadDelivered(fileName);
|
|
5865
|
+
}
|
|
5866
|
+
ws.send(JSON.stringify({ type: "connected" }));
|
|
5867
|
+
}).catch((err) => {
|
|
5868
|
+
debug7?.(`registerClient failed for ${clientId}: ${err?.message ?? err}`);
|
|
5869
|
+
ws.close();
|
|
5870
|
+
});
|
|
4660
5871
|
ws.on("message", async (raw) => {
|
|
4661
5872
|
try {
|
|
4662
5873
|
const msg = JSON.parse(String(raw));
|
|
4663
|
-
if (msg.type === "hmr:
|
|
4664
|
-
await engine.registerModules(clientId, msg.modules);
|
|
4665
|
-
debug6?.(`registered ${msg.modules.length} modules for ${clientId}`);
|
|
4666
|
-
} else if (msg.type === "hmr:invalidate") {
|
|
5874
|
+
if (msg.type === "hmr:invalidate") {
|
|
4667
5875
|
scheduleFullReload();
|
|
4668
5876
|
}
|
|
4669
5877
|
} catch (err) {
|
|
4670
|
-
|
|
5878
|
+
debug7?.(`bundled ws message error: ${err.message}`);
|
|
4671
5879
|
}
|
|
4672
5880
|
});
|
|
4673
5881
|
ws.on("close", () => {
|
|
4674
5882
|
bundledClients.delete(clientId);
|
|
4675
|
-
engine.removeClient(clientId).catch((err) =>
|
|
5883
|
+
engine.removeClient(clientId).catch((err) => debug7?.(`removeClient failed for ${clientId}: ${err?.message ?? err}`));
|
|
4676
5884
|
});
|
|
4677
5885
|
});
|
|
4678
5886
|
});
|
|
@@ -4689,10 +5897,18 @@ async function createBundledDevServer(opts) {
|
|
|
4689
5897
|
res.end("// [nasti] lazy endpoint requires id & clientId");
|
|
4690
5898
|
return;
|
|
4691
5899
|
}
|
|
4692
|
-
const
|
|
5900
|
+
const output = await engine.compileEntry(id, clientId);
|
|
5901
|
+
if (output.sourcemap && output.sourcemapFilename) {
|
|
5902
|
+
memoryFiles.set(output.sourcemapFilename, output.sourcemap);
|
|
5903
|
+
}
|
|
5904
|
+
res.once("finish", () => {
|
|
5905
|
+
void engine.notifyPayloadDelivered(output.filename).catch(
|
|
5906
|
+
(err) => debug7?.(`notifyPayloadDelivered failed: ${err?.message ?? err}`)
|
|
5907
|
+
);
|
|
5908
|
+
});
|
|
4693
5909
|
res.setHeader("Content-Type", "application/javascript");
|
|
4694
5910
|
res.setHeader("Cache-Control", "no-store");
|
|
4695
|
-
res.end(code + "\n;export {}");
|
|
5911
|
+
res.end(output.code + "\n;export {}");
|
|
4696
5912
|
return;
|
|
4697
5913
|
}
|
|
4698
5914
|
const patchHit = patches.get(pathname.replace(/^\//, ""));
|
|
@@ -4711,8 +5927,13 @@ async function createBundledDevServer(opts) {
|
|
|
4711
5927
|
return;
|
|
4712
5928
|
}
|
|
4713
5929
|
res.setHeader("ETag", hit.etag);
|
|
4714
|
-
res.setHeader("Content-Type", MIME_TYPES[
|
|
5930
|
+
res.setHeader("Content-Type", MIME_TYPES[path15.extname(fileName)] ?? "application/octet-stream");
|
|
4715
5931
|
res.setHeader("Cache-Control", "no-cache");
|
|
5932
|
+
res.once("finish", () => {
|
|
5933
|
+
void engine.notifyPayloadDelivered(fileName).catch(
|
|
5934
|
+
(err) => debug7?.(`notifyPayloadDelivered failed: ${err?.message ?? err}`)
|
|
5935
|
+
);
|
|
5936
|
+
});
|
|
4716
5937
|
res.end(hit.content);
|
|
4717
5938
|
return;
|
|
4718
5939
|
}
|
|
@@ -4747,7 +5968,7 @@ function stripCatchAllLoad(plugins) {
|
|
|
4747
5968
|
);
|
|
4748
5969
|
}
|
|
4749
5970
|
function createReactRefreshRuntimePlugin(entryPoints) {
|
|
4750
|
-
const entryIds = new Set(entryPoints.map((p) =>
|
|
5971
|
+
const entryIds = new Set(entryPoints.map((p) => path15.resolve(p)));
|
|
4751
5972
|
return {
|
|
4752
5973
|
name: "nasti:bundled-react-refresh",
|
|
4753
5974
|
resolveId(source) {
|
|
@@ -4765,7 +5986,7 @@ function createReactRefreshRuntimePlugin(entryPoints) {
|
|
|
4765
5986
|
return null;
|
|
4766
5987
|
},
|
|
4767
5988
|
transform(code, id) {
|
|
4768
|
-
if (!entryIds.has(
|
|
5989
|
+
if (!entryIds.has(path15.resolve(id.split("?")[0]))) return null;
|
|
4769
5990
|
return { code: `import ${JSON.stringify(PREAMBLE_SPEC)};
|
|
4770
5991
|
${code}`, map: null };
|
|
4771
5992
|
}
|
|
@@ -4812,7 +6033,7 @@ async function renderBundledIndexHtml(html, config, entryFileNames) {
|
|
|
4812
6033
|
}
|
|
4813
6034
|
return processed;
|
|
4814
6035
|
}
|
|
4815
|
-
var
|
|
6036
|
+
var debug7, MIME_TYPES, MemoryFiles, PREAMBLE_SPEC, RESOLVED_PREAMBLE_ID, REFRESH_RUNTIME_URL, BUNDLED_PREAMBLE_CODE, WRAPPER_RUNTIME_HELPERS;
|
|
4816
6037
|
var init_dev_engine = __esm({
|
|
4817
6038
|
"src/server/bundled/dev-engine.ts"() {
|
|
4818
6039
|
"use strict";
|
|
@@ -4821,7 +6042,7 @@ var init_dev_engine = __esm({
|
|
|
4821
6042
|
init_transformer();
|
|
4822
6043
|
init_middleware();
|
|
4823
6044
|
init_debug();
|
|
4824
|
-
|
|
6045
|
+
debug7 = createDebugger("nasti:bundled");
|
|
4825
6046
|
MIME_TYPES = {
|
|
4826
6047
|
".js": "application/javascript",
|
|
4827
6048
|
".mjs": "application/javascript",
|
|
@@ -4936,7 +6157,7 @@ __export(server_exports, {
|
|
|
4936
6157
|
createServer: () => createServer
|
|
4937
6158
|
});
|
|
4938
6159
|
import http from "http";
|
|
4939
|
-
import
|
|
6160
|
+
import path16 from "path";
|
|
4940
6161
|
import os from "os";
|
|
4941
6162
|
import connect from "connect";
|
|
4942
6163
|
import sirv from "sirv";
|
|
@@ -4946,14 +6167,16 @@ async function createServer(inlineConfig = {}) {
|
|
|
4946
6167
|
const startTime = performance.now();
|
|
4947
6168
|
const config = await resolveConfig(inlineConfig, "serve");
|
|
4948
6169
|
const logger = config.logger;
|
|
4949
|
-
const allPlugins = resolvePluginList(config, config.plugins
|
|
6170
|
+
const allPlugins = resolvePluginList(config, config.plugins, {
|
|
6171
|
+
environmentName: "client"
|
|
6172
|
+
});
|
|
4950
6173
|
const configWithPlugins = { ...config, plugins: allPlugins };
|
|
4951
6174
|
const app = connect();
|
|
4952
6175
|
const httpServer = http.createServer(app);
|
|
4953
6176
|
const ws = createWebSocketServer(httpServer);
|
|
4954
6177
|
const pluginApi = getPluginApi(config);
|
|
4955
6178
|
const clientEnv = new NastiEnvironment("client", config, {
|
|
4956
|
-
hot: createWsHotChannel(ws),
|
|
6179
|
+
hot: createWsHotChannel(ws, "client"),
|
|
4957
6180
|
mode: "dev",
|
|
4958
6181
|
plugins: allPlugins,
|
|
4959
6182
|
pluginApi
|
|
@@ -4963,15 +6186,45 @@ async function createServer(inlineConfig = {}) {
|
|
|
4963
6186
|
for (const name of Object.keys(config.environments)) {
|
|
4964
6187
|
if (name === "client") continue;
|
|
4965
6188
|
const consumer = config.environments[name].consumer;
|
|
4966
|
-
const envPlugins = resolvePluginList(config, config.plugins, {
|
|
6189
|
+
const envPlugins = resolvePluginList(config, config.plugins, {
|
|
6190
|
+
consumer,
|
|
6191
|
+
environmentName: name
|
|
6192
|
+
});
|
|
4967
6193
|
environments[name] = new NastiEnvironment(name, config, {
|
|
6194
|
+
hot: consumer === "client" ? createWsHotChannel(ws, name) : void 0,
|
|
4968
6195
|
mode: "dev",
|
|
4969
6196
|
plugins: envPlugins,
|
|
4970
6197
|
pluginApi
|
|
4971
6198
|
});
|
|
4972
6199
|
}
|
|
4973
6200
|
for (const [name, environment] of Object.entries(environments)) {
|
|
4974
|
-
if (name
|
|
6201
|
+
if (name === "client" || environment.consumer === "client" || environment.options.driver) {
|
|
6202
|
+
await environment.init();
|
|
6203
|
+
}
|
|
6204
|
+
}
|
|
6205
|
+
const transformContexts = /* @__PURE__ */ new Map();
|
|
6206
|
+
for (const environment of Object.values(environments)) {
|
|
6207
|
+
if (environment.consumer !== "client" || environment.driver) continue;
|
|
6208
|
+
const environmentConfig = {
|
|
6209
|
+
...configWithPlugins,
|
|
6210
|
+
resolve: environment.options.resolve,
|
|
6211
|
+
build: environment.options.build,
|
|
6212
|
+
plugins: environment.plugins
|
|
6213
|
+
};
|
|
6214
|
+
const context = {
|
|
6215
|
+
config: environmentConfig,
|
|
6216
|
+
pluginContainer: environment.pluginContainer,
|
|
6217
|
+
moduleGraph: environment.moduleGraph,
|
|
6218
|
+
environment,
|
|
6219
|
+
envDefine: buildEnvDefine(
|
|
6220
|
+
loadEnv(environmentConfig.mode, environmentConfig.root, environmentConfig.envPrefix),
|
|
6221
|
+
environmentConfig.mode,
|
|
6222
|
+
ssrDefineOverrides(environment.consumer)
|
|
6223
|
+
),
|
|
6224
|
+
onPrune: (paths) => environment.hot.send({ type: "prune", paths })
|
|
6225
|
+
};
|
|
6226
|
+
transformContexts.set(environment.name, context);
|
|
6227
|
+
environment.configureDevPipeline((url) => transformRequest(url, context));
|
|
4975
6228
|
}
|
|
4976
6229
|
let ssrRunner = null;
|
|
4977
6230
|
async function getSsrRunner() {
|
|
@@ -4986,7 +6239,6 @@ async function createServer(inlineConfig = {}) {
|
|
|
4986
6239
|
return ssrRunner;
|
|
4987
6240
|
}
|
|
4988
6241
|
const moduleGraph = clientEnv.moduleGraph;
|
|
4989
|
-
const pluginContainer = clientEnv.pluginContainer;
|
|
4990
6242
|
let bundledServer = null;
|
|
4991
6243
|
if (config.experimental.bundledDev) {
|
|
4992
6244
|
const { createBundledDevServer: createBundledDevServer2 } = await Promise.resolve().then(() => (init_dev_engine(), dev_engine_exports));
|
|
@@ -4998,14 +6250,14 @@ async function createServer(inlineConfig = {}) {
|
|
|
4998
6250
|
app.use(bundledServer.middleware);
|
|
4999
6251
|
}
|
|
5000
6252
|
const ignoredSegments = /* @__PURE__ */ new Set(["node_modules", ".git", ".nasti"]);
|
|
5001
|
-
const outDirAbs =
|
|
6253
|
+
const outDirAbs = path16.resolve(config.root, config.build.outDir);
|
|
5002
6254
|
const watcher = watch(config.root, {
|
|
5003
6255
|
ignored: (filePath) => {
|
|
5004
6256
|
if (filePath === config.root) return false;
|
|
5005
|
-
if (filePath === outDirAbs || filePath.startsWith(outDirAbs +
|
|
5006
|
-
const rel =
|
|
5007
|
-
if (!rel || rel.startsWith("..") ||
|
|
5008
|
-
for (const seg of rel.split(
|
|
6257
|
+
if (filePath === outDirAbs || filePath.startsWith(outDirAbs + path16.sep)) return true;
|
|
6258
|
+
const rel = path16.relative(config.root, filePath);
|
|
6259
|
+
if (!rel || rel.startsWith("..") || path16.isAbsolute(rel)) return false;
|
|
6260
|
+
for (const seg of rel.split(path16.sep)) {
|
|
5009
6261
|
if (ignoredSegments.has(seg)) return true;
|
|
5010
6262
|
}
|
|
5011
6263
|
return false;
|
|
@@ -5015,6 +6267,15 @@ async function createServer(inlineConfig = {}) {
|
|
|
5015
6267
|
let server;
|
|
5016
6268
|
const environmentServices = {};
|
|
5017
6269
|
let environmentDriversStarted = false;
|
|
6270
|
+
let devPipelinesStarted = false;
|
|
6271
|
+
const startDevPipelines = async () => {
|
|
6272
|
+
if (devPipelinesStarted) return;
|
|
6273
|
+
devPipelinesStarted = true;
|
|
6274
|
+
for (const environment of Object.values(environments)) {
|
|
6275
|
+
if (!transformContexts.has(environment.name)) continue;
|
|
6276
|
+
await environment.pluginContainer.buildStart();
|
|
6277
|
+
}
|
|
6278
|
+
};
|
|
5018
6279
|
const logCloseError = (target, error) => {
|
|
5019
6280
|
const normalized = error instanceof Error ? error : new Error(String(error));
|
|
5020
6281
|
logger.error(`[nasti] failed to close ${target}`, { error: normalized });
|
|
@@ -5066,14 +6327,61 @@ async function createServer(inlineConfig = {}) {
|
|
|
5066
6327
|
});
|
|
5067
6328
|
}
|
|
5068
6329
|
};
|
|
6330
|
+
const updateClientEnvironments = async (file) => {
|
|
6331
|
+
const timestamp = Date.now();
|
|
6332
|
+
const results = {};
|
|
6333
|
+
for (const environment of Object.values(environments)) {
|
|
6334
|
+
if (environment.consumer !== "client" || environment.driver) continue;
|
|
6335
|
+
try {
|
|
6336
|
+
const result = await handleFileChange(file, server, environment.name, timestamp);
|
|
6337
|
+
if (result) results[environment.name] = result;
|
|
6338
|
+
} catch (error) {
|
|
6339
|
+
const normalized = error instanceof Error ? error : new Error(String(error));
|
|
6340
|
+
logger.error(
|
|
6341
|
+
`[nasti] HMR failed for environment "${environment.name}": ${normalized.message}`,
|
|
6342
|
+
{ error: normalized }
|
|
6343
|
+
);
|
|
6344
|
+
try {
|
|
6345
|
+
environment.hot.send({
|
|
6346
|
+
type: "error",
|
|
6347
|
+
err: { message: normalized.message, stack: normalized.stack }
|
|
6348
|
+
});
|
|
6349
|
+
} catch (channelError) {
|
|
6350
|
+
const channelFailure = channelError instanceof Error ? channelError : new Error(String(channelError));
|
|
6351
|
+
logger.error(
|
|
6352
|
+
`[nasti] failed to deliver HMR error to environment "${environment.name}"`,
|
|
6353
|
+
{ error: channelFailure }
|
|
6354
|
+
);
|
|
6355
|
+
}
|
|
6356
|
+
}
|
|
6357
|
+
}
|
|
6358
|
+
if (Object.keys(results).length === 0) return;
|
|
6359
|
+
const context = {
|
|
6360
|
+
file,
|
|
6361
|
+
timestamp,
|
|
6362
|
+
environments: Object.freeze({ ...results }),
|
|
6363
|
+
server
|
|
6364
|
+
};
|
|
6365
|
+
for (const plugin of config.plugins) {
|
|
6366
|
+
await plugin.handleHotUpdateApp?.(context);
|
|
6367
|
+
}
|
|
6368
|
+
};
|
|
6369
|
+
const queueClientEnvironmentUpdate = (file) => {
|
|
6370
|
+
void updateClientEnvironments(file).catch((error) => {
|
|
6371
|
+
const normalized = error instanceof Error ? error : new Error(String(error));
|
|
6372
|
+
logger.error(`[nasti] multi-environment HMR failed: ${normalized.message}`, {
|
|
6373
|
+
error: normalized
|
|
6374
|
+
});
|
|
6375
|
+
});
|
|
6376
|
+
};
|
|
5069
6377
|
watcher.on("change", (file) => {
|
|
5070
6378
|
ssrRunner?.invalidateFile(file);
|
|
5071
|
-
|
|
6379
|
+
queueClientEnvironmentUpdate(file);
|
|
5072
6380
|
notifyEnvironmentDrivers(file, "change");
|
|
5073
6381
|
});
|
|
5074
6382
|
watcher.on("add", (file) => {
|
|
5075
6383
|
ssrRunner?.invalidateFile(file);
|
|
5076
|
-
|
|
6384
|
+
queueClientEnvironmentUpdate(file);
|
|
5077
6385
|
notifyEnvironmentDrivers(file, "add");
|
|
5078
6386
|
});
|
|
5079
6387
|
watcher.on("unlink", (file) => {
|
|
@@ -5091,7 +6399,7 @@ async function createServer(inlineConfig = {}) {
|
|
|
5091
6399
|
async listen(port) {
|
|
5092
6400
|
const finalPort = port ?? config.server.port;
|
|
5093
6401
|
const host = config.server.host === true ? "0.0.0.0" : config.server.host;
|
|
5094
|
-
await
|
|
6402
|
+
await startDevPipelines();
|
|
5095
6403
|
await startEnvironmentDrivers();
|
|
5096
6404
|
return new Promise((resolve, reject) => {
|
|
5097
6405
|
let currentPort = finalPort;
|
|
@@ -5106,7 +6414,7 @@ async function createServer(inlineConfig = {}) {
|
|
|
5106
6414
|
const readyIn = Math.ceil(performance.now() - startTime);
|
|
5107
6415
|
logger.info(
|
|
5108
6416
|
`
|
|
5109
|
-
${pc9.cyan(pc9.bold("NASTI"))} ${pc9.cyan(`v${"2.
|
|
6417
|
+
${pc9.cyan(pc9.bold("NASTI"))} ${pc9.cyan(`v${"2.4.1"}`)} ${pc9.dim("ready in")} ${pc9.bold(readyIn)} ${pc9.dim("ms")}
|
|
5110
6418
|
`
|
|
5111
6419
|
);
|
|
5112
6420
|
printServerUrls(
|
|
@@ -5133,15 +6441,26 @@ async function createServer(inlineConfig = {}) {
|
|
|
5133
6441
|
});
|
|
5134
6442
|
},
|
|
5135
6443
|
async transformRequest(url) {
|
|
5136
|
-
|
|
5137
|
-
|
|
6444
|
+
return clientEnv.transformRequest(url);
|
|
6445
|
+
},
|
|
6446
|
+
async transformEnvironmentRequest(environmentName, url) {
|
|
6447
|
+
const environment = environments[environmentName];
|
|
6448
|
+
if (!environment) {
|
|
6449
|
+
throw new Error(`[nasti] unknown dev environment "${environmentName}"`);
|
|
6450
|
+
}
|
|
6451
|
+
return environment.transformRequest(url);
|
|
5138
6452
|
},
|
|
5139
6453
|
async ssrLoadModule(url) {
|
|
5140
6454
|
const runner = await getSsrRunner();
|
|
5141
6455
|
return runner.import(url);
|
|
5142
6456
|
},
|
|
5143
6457
|
async close() {
|
|
5144
|
-
|
|
6458
|
+
if (devPipelinesStarted) {
|
|
6459
|
+
for (const environment of Object.values(environments).reverse()) {
|
|
6460
|
+
if (!transformContexts.has(environment.name)) continue;
|
|
6461
|
+
await environment.pluginContainer.buildEnd();
|
|
6462
|
+
}
|
|
6463
|
+
}
|
|
5145
6464
|
await bundledServer?.close();
|
|
5146
6465
|
let environmentCloseFailed = false;
|
|
5147
6466
|
let firstEnvironmentCloseError;
|
|
@@ -5191,12 +6510,8 @@ async function createServer(inlineConfig = {}) {
|
|
|
5191
6510
|
}
|
|
5192
6511
|
throw error;
|
|
5193
6512
|
}
|
|
5194
|
-
app.use(transformMiddleware(
|
|
5195
|
-
|
|
5196
|
-
pluginContainer,
|
|
5197
|
-
moduleGraph
|
|
5198
|
-
}));
|
|
5199
|
-
const publicDir = path15.resolve(config.root, "public");
|
|
6513
|
+
app.use(transformMiddleware(transformContexts.get("client")));
|
|
6514
|
+
const publicDir = path16.resolve(config.root, "public");
|
|
5200
6515
|
app.use(sirv(publicDir, { dev: true, etag: true }));
|
|
5201
6516
|
app.use(sirv(config.root, { dev: true, etag: true }));
|
|
5202
6517
|
const postMiddlewares = [];
|
|
@@ -5234,6 +6549,7 @@ var init_server = __esm({
|
|
|
5234
6549
|
init_hmr();
|
|
5235
6550
|
init_builtins();
|
|
5236
6551
|
init_plugin_api();
|
|
6552
|
+
init_env();
|
|
5237
6553
|
}
|
|
5238
6554
|
});
|
|
5239
6555
|
|
|
@@ -5244,8 +6560,8 @@ init_build();
|
|
|
5244
6560
|
// src/build/electron.ts
|
|
5245
6561
|
init_config();
|
|
5246
6562
|
init_resolve();
|
|
5247
|
-
import
|
|
5248
|
-
import
|
|
6563
|
+
import path11 from "path";
|
|
6564
|
+
import fs8 from "fs";
|
|
5249
6565
|
import { rolldown as rolldown2 } from "rolldown";
|
|
5250
6566
|
import pc5 from "picocolors";
|
|
5251
6567
|
|
|
@@ -5289,16 +6605,16 @@ async function buildElectron(inlineConfig = {}) {
|
|
|
5289
6605
|
const config = await resolveConfig({ ...inlineConfig, target: "electron" }, "build");
|
|
5290
6606
|
const startTime = performance.now();
|
|
5291
6607
|
assertElectronVersion(config);
|
|
5292
|
-
console.log(pc5.cyan("\n\u26A1 nasti build (electron)") + pc5.dim(` v${"2.
|
|
6608
|
+
console.log(pc5.cyan("\n\u26A1 nasti build (electron)") + pc5.dim(` v${"2.4.1"}`));
|
|
5293
6609
|
console.log(pc5.dim(` root: ${config.root}`));
|
|
5294
6610
|
console.log(pc5.dim(` mode: ${config.mode}`));
|
|
5295
6611
|
console.log(pc5.dim(` target: electron (\u2265 ${config.electron.minVersion})`));
|
|
5296
|
-
const outDir =
|
|
5297
|
-
if (config.build.emptyOutDir &&
|
|
5298
|
-
|
|
6612
|
+
const outDir = path11.resolve(config.root, config.build.outDir);
|
|
6613
|
+
if (config.build.emptyOutDir && fs8.existsSync(outDir)) {
|
|
6614
|
+
fs8.rmSync(outDir, { recursive: true, force: true });
|
|
5299
6615
|
}
|
|
5300
|
-
|
|
5301
|
-
const rendererOutDir =
|
|
6616
|
+
fs8.mkdirSync(outDir, { recursive: true });
|
|
6617
|
+
const rendererOutDir = path11.join(outDir, "renderer");
|
|
5302
6618
|
const { build: build2 } = await Promise.resolve().then(() => (init_build(), build_exports));
|
|
5303
6619
|
await build2(createElectronRendererConfig(config, inlineConfig, {
|
|
5304
6620
|
build: {
|
|
@@ -5307,8 +6623,8 @@ async function buildElectron(inlineConfig = {}) {
|
|
|
5307
6623
|
emptyOutDir: false
|
|
5308
6624
|
}
|
|
5309
6625
|
}));
|
|
5310
|
-
const mainEntry =
|
|
5311
|
-
if (!
|
|
6626
|
+
const mainEntry = path11.resolve(config.root, config.electron.main);
|
|
6627
|
+
if (!fs8.existsSync(mainEntry)) {
|
|
5312
6628
|
throw new Error(
|
|
5313
6629
|
`Electron main entry not found: ${config.electron.main}
|
|
5314
6630
|
\u5728 nasti.config.ts \u7684 electron.main \u6307\u5B9A\u4E3B\u8FDB\u7A0B\u5165\u53E3\u6587\u4EF6\u3002`
|
|
@@ -5322,11 +6638,11 @@ async function buildElectron(inlineConfig = {}) {
|
|
|
5322
6638
|
const preloadEntries = normalizePreload(config.electron.preload, config.root);
|
|
5323
6639
|
const preloadFiles = [];
|
|
5324
6640
|
for (const entry of preloadEntries) {
|
|
5325
|
-
if (!
|
|
6641
|
+
if (!fs8.existsSync(entry)) {
|
|
5326
6642
|
console.warn(pc5.yellow(` \u26A0 preload entry not found, skipped: ${entry}`));
|
|
5327
6643
|
continue;
|
|
5328
6644
|
}
|
|
5329
|
-
const base =
|
|
6645
|
+
const base = path11.basename(entry).replace(/\.[^.]+$/, "");
|
|
5330
6646
|
const out = outFileName(outDir, base, config.electron.preloadFormat);
|
|
5331
6647
|
await bundleNode(config, entry, {
|
|
5332
6648
|
outFile: out,
|
|
@@ -5338,10 +6654,10 @@ async function buildElectron(inlineConfig = {}) {
|
|
|
5338
6654
|
const elapsed = ((performance.now() - startTime) / 1e3).toFixed(2);
|
|
5339
6655
|
console.log(pc5.green(`
|
|
5340
6656
|
\u2713 Electron build complete in ${elapsed}s`));
|
|
5341
|
-
console.log(pc5.dim(` renderer: ${
|
|
5342
|
-
console.log(pc5.dim(` main: ${
|
|
6657
|
+
console.log(pc5.dim(` renderer: ${path11.relative(config.root, rendererOutDir)}/`));
|
|
6658
|
+
console.log(pc5.dim(` main: ${path11.relative(config.root, mainFile)}`));
|
|
5343
6659
|
for (const pf of preloadFiles) {
|
|
5344
|
-
console.log(pc5.dim(` preload: ${
|
|
6660
|
+
console.log(pc5.dim(` preload: ${path11.relative(config.root, pf)}`));
|
|
5345
6661
|
}
|
|
5346
6662
|
console.log();
|
|
5347
6663
|
return { rendererOutDir, mainFile, preloadFiles };
|
|
@@ -5379,7 +6695,7 @@ async function bundleNode(config, entry, opts) {
|
|
|
5379
6695
|
},
|
|
5380
6696
|
plugins: [oxcTransformPlugin, electronPlugin(config), resolvePlugin(config)]
|
|
5381
6697
|
});
|
|
5382
|
-
|
|
6698
|
+
fs8.mkdirSync(path11.dirname(opts.outFile), { recursive: true });
|
|
5383
6699
|
await bundle2.write({
|
|
5384
6700
|
sourcemap: !!config.build.sourcemap,
|
|
5385
6701
|
minify: !!config.build.minify,
|
|
@@ -5390,7 +6706,7 @@ async function bundleNode(config, entry, opts) {
|
|
|
5390
6706
|
codeSplitting: false
|
|
5391
6707
|
});
|
|
5392
6708
|
await bundle2.close();
|
|
5393
|
-
console.log(pc5.dim(` \u2713 ${opts.label} \u2192 ${
|
|
6709
|
+
console.log(pc5.dim(` \u2713 ${opts.label} \u2192 ${path11.relative(config.root, opts.outFile)}`));
|
|
5394
6710
|
return opts.outFile;
|
|
5395
6711
|
}
|
|
5396
6712
|
function createElectronRendererConfig(config, inlineConfig = {}, overrides = {}) {
|
|
@@ -5414,11 +6730,11 @@ function createElectronRendererConfig(config, inlineConfig = {}, overrides = {})
|
|
|
5414
6730
|
}
|
|
5415
6731
|
function outFileName(outDir, base, format) {
|
|
5416
6732
|
const ext = format === "cjs" ? ".cjs" : ".mjs";
|
|
5417
|
-
return
|
|
6733
|
+
return path11.join(outDir, base + ext);
|
|
5418
6734
|
}
|
|
5419
6735
|
function normalizePreload(preload, root) {
|
|
5420
6736
|
const list = Array.isArray(preload) ? preload : preload ? [preload] : [];
|
|
5421
|
-
return list.map((p) =>
|
|
6737
|
+
return list.map((p) => path11.resolve(root, p));
|
|
5422
6738
|
}
|
|
5423
6739
|
function assertElectronVersion(config) {
|
|
5424
6740
|
const min = config.electron.minVersion;
|
|
@@ -5433,9 +6749,9 @@ function assertElectronVersion(config) {
|
|
|
5433
6749
|
}
|
|
5434
6750
|
function detectInstalledElectron(root) {
|
|
5435
6751
|
try {
|
|
5436
|
-
const pkgPath =
|
|
5437
|
-
if (!
|
|
5438
|
-
const pkg = JSON.parse(
|
|
6752
|
+
const pkgPath = path11.resolve(root, "node_modules/electron/package.json");
|
|
6753
|
+
if (!fs8.existsSync(pkgPath)) return null;
|
|
6754
|
+
const pkg = JSON.parse(fs8.readFileSync(pkgPath, "utf-8"));
|
|
5439
6755
|
const major = parseInt(String(pkg.version).split(".")[0], 10);
|
|
5440
6756
|
return Number.isFinite(major) ? major : null;
|
|
5441
6757
|
} catch {
|
|
@@ -5448,8 +6764,8 @@ init_server();
|
|
|
5448
6764
|
|
|
5449
6765
|
// src/server/electron-dev.ts
|
|
5450
6766
|
init_config();
|
|
5451
|
-
import
|
|
5452
|
-
import
|
|
6767
|
+
import path17 from "path";
|
|
6768
|
+
import fs12 from "fs";
|
|
5453
6769
|
import { createRequire as createRequire5 } from "module";
|
|
5454
6770
|
import { spawn } from "child_process";
|
|
5455
6771
|
import chokidar from "chokidar";
|
|
@@ -5462,7 +6778,7 @@ async function startElectronDev(inlineConfig = {}) {
|
|
|
5462
6778
|
const { noSpawn, ...rest } = inlineConfig;
|
|
5463
6779
|
const config = await resolveConfig({ ...rest, target: "electron" }, "serve");
|
|
5464
6780
|
warnElectronVersion(config);
|
|
5465
|
-
console.log(pc10.cyan("\n\u26A1 nasti electron dev") + pc10.dim(` v${"2.
|
|
6781
|
+
console.log(pc10.cyan("\n\u26A1 nasti electron dev") + pc10.dim(` v${"2.4.1"}`));
|
|
5466
6782
|
const { createServer: createServer2 } = await Promise.resolve().then(() => (init_server(), server_exports));
|
|
5467
6783
|
const server = await createServer2({
|
|
5468
6784
|
...rest,
|
|
@@ -5472,11 +6788,11 @@ async function startElectronDev(inlineConfig = {}) {
|
|
|
5472
6788
|
await server.listen();
|
|
5473
6789
|
const devUrl = `http://localhost:${server.config.server.port}` + electronRendererDevPath(config.electron.renderer);
|
|
5474
6790
|
console.log(pc10.dim(` renderer: ${devUrl}`));
|
|
5475
|
-
const stageDir =
|
|
5476
|
-
|
|
5477
|
-
const mainEntry =
|
|
6791
|
+
const stageDir = path17.resolve(config.root, ".nasti");
|
|
6792
|
+
fs12.mkdirSync(stageDir, { recursive: true });
|
|
6793
|
+
const mainEntry = path17.resolve(config.root, config.electron.main);
|
|
5478
6794
|
const preloadEntries = normalizePreload(config.electron.preload, config.root);
|
|
5479
|
-
const builtMainFile =
|
|
6795
|
+
const builtMainFile = path17.join(stageDir, "main" + extFor(config.electron.mainFormat));
|
|
5480
6796
|
const builtPreloadFiles = [];
|
|
5481
6797
|
const compileAll = async () => {
|
|
5482
6798
|
await compileNode(config, mainEntry, {
|
|
@@ -5486,9 +6802,9 @@ async function startElectronDev(inlineConfig = {}) {
|
|
|
5486
6802
|
});
|
|
5487
6803
|
builtPreloadFiles.length = 0;
|
|
5488
6804
|
for (const entry of preloadEntries) {
|
|
5489
|
-
if (!
|
|
5490
|
-
const base =
|
|
5491
|
-
const out =
|
|
6805
|
+
if (!fs12.existsSync(entry)) continue;
|
|
6806
|
+
const base = path17.basename(entry).replace(/\.[^.]+$/, "");
|
|
6807
|
+
const out = path17.join(stageDir, base + extFor(config.electron.preloadFormat));
|
|
5492
6808
|
await compileNode(config, entry, {
|
|
5493
6809
|
outFile: out,
|
|
5494
6810
|
format: config.electron.preloadFormat,
|
|
@@ -5527,7 +6843,7 @@ async function startElectronDev(inlineConfig = {}) {
|
|
|
5527
6843
|
};
|
|
5528
6844
|
spawnElectron();
|
|
5529
6845
|
if (config.electron.autoRestart) {
|
|
5530
|
-
const watchTargets = [mainEntry, ...preloadEntries].filter(
|
|
6846
|
+
const watchTargets = [mainEntry, ...preloadEntries].filter(fs12.existsSync);
|
|
5531
6847
|
const watcher = chokidar.watch(watchTargets, { ignoreInitial: true });
|
|
5532
6848
|
let restarting = null;
|
|
5533
6849
|
let pending = false;
|
|
@@ -5607,7 +6923,7 @@ async function compileNode(config, entry, opts) {
|
|
|
5607
6923
|
platform: "node",
|
|
5608
6924
|
plugins: [oxcTransformPlugin, electronPlugin(config), resolvePlugin(config)]
|
|
5609
6925
|
});
|
|
5610
|
-
|
|
6926
|
+
fs12.mkdirSync(path17.dirname(opts.outFile), { recursive: true });
|
|
5611
6927
|
await bundle2.write({
|
|
5612
6928
|
file: opts.outFile,
|
|
5613
6929
|
format: opts.format === "cjs" ? "cjs" : "esm",
|
|
@@ -5620,18 +6936,18 @@ async function compileNode(config, entry, opts) {
|
|
|
5620
6936
|
await bundle2.close();
|
|
5621
6937
|
}
|
|
5622
6938
|
function electronRendererDevPath(renderer) {
|
|
5623
|
-
const normalized = renderer.split(
|
|
6939
|
+
const normalized = renderer.split(path17.sep).join("/").replace(/^\.?\//, "");
|
|
5624
6940
|
return normalized === "index.html" ? "/" : `/${normalized}`;
|
|
5625
6941
|
}
|
|
5626
6942
|
function resolveElectronBinary(config) {
|
|
5627
|
-
if (config.electron.electronPath &&
|
|
6943
|
+
if (config.electron.electronPath && fs12.existsSync(config.electron.electronPath)) {
|
|
5628
6944
|
return config.electron.electronPath;
|
|
5629
6945
|
}
|
|
5630
6946
|
try {
|
|
5631
|
-
const require2 = createRequire5(
|
|
6947
|
+
const require2 = createRequire5(path17.resolve(config.root, "package.json"));
|
|
5632
6948
|
const pathFile = require2.resolve("electron");
|
|
5633
6949
|
const electronModule = require2(pathFile);
|
|
5634
|
-
if (typeof electronModule === "string" &&
|
|
6950
|
+
if (typeof electronModule === "string" && fs12.existsSync(electronModule)) {
|
|
5635
6951
|
return electronModule;
|
|
5636
6952
|
}
|
|
5637
6953
|
} catch {
|
|
@@ -5658,8 +6974,8 @@ function warnElectronVersion(config) {
|
|
|
5658
6974
|
}
|
|
5659
6975
|
|
|
5660
6976
|
// src/plugins/monaco-editor.ts
|
|
5661
|
-
import
|
|
5662
|
-
import
|
|
6977
|
+
import path18 from "path";
|
|
6978
|
+
import fs13 from "fs";
|
|
5663
6979
|
import crypto4 from "crypto";
|
|
5664
6980
|
import { createRequire as createRequire6 } from "module";
|
|
5665
6981
|
var DEFAULT_WORKERS = {
|
|
@@ -5680,9 +6996,9 @@ function normalizePublicPath(p) {
|
|
|
5680
6996
|
}
|
|
5681
6997
|
function readMonacoVersion(root) {
|
|
5682
6998
|
try {
|
|
5683
|
-
const require2 = createRequire6(
|
|
6999
|
+
const require2 = createRequire6(path18.resolve(root, "package.json"));
|
|
5684
7000
|
const pkgJsonPath = require2.resolve("monaco-editor/package.json", { paths: [root] });
|
|
5685
|
-
const pkg = JSON.parse(
|
|
7001
|
+
const pkg = JSON.parse(fs13.readFileSync(pkgJsonPath, "utf-8"));
|
|
5686
7002
|
return typeof pkg.version === "string" ? pkg.version : "unknown";
|
|
5687
7003
|
} catch {
|
|
5688
7004
|
return "unknown";
|
|
@@ -5702,20 +7018,20 @@ function monacoEditorPlugin(options = {}) {
|
|
|
5702
7018
|
let cacheDir = "";
|
|
5703
7019
|
const building = /* @__PURE__ */ new Map();
|
|
5704
7020
|
async function buildWorker(worker) {
|
|
5705
|
-
const cacheFile =
|
|
5706
|
-
if (
|
|
7021
|
+
const cacheFile = path18.join(cacheDir, `${worker.label}.worker.js`);
|
|
7022
|
+
if (fs13.existsSync(cacheFile)) return cacheFile;
|
|
5707
7023
|
const existing = building.get(worker.label);
|
|
5708
7024
|
if (existing) return existing;
|
|
5709
7025
|
const task = (async () => {
|
|
5710
7026
|
const { rolldown: rolldown4 } = await import("rolldown");
|
|
5711
|
-
const require2 = createRequire6(
|
|
7027
|
+
const require2 = createRequire6(path18.resolve(resolvedConfig.root, "package.json"));
|
|
5712
7028
|
let entry;
|
|
5713
7029
|
try {
|
|
5714
7030
|
entry = require2.resolve(worker.entry, { paths: [resolvedConfig.root] });
|
|
5715
7031
|
} catch {
|
|
5716
7032
|
entry = require2.resolve(worker.entry + ".js", { paths: [resolvedConfig.root] });
|
|
5717
7033
|
}
|
|
5718
|
-
|
|
7034
|
+
fs13.mkdirSync(cacheDir, { recursive: true });
|
|
5719
7035
|
const bundle2 = await rolldown4({
|
|
5720
7036
|
input: entry,
|
|
5721
7037
|
platform: "browser"
|
|
@@ -5775,12 +7091,12 @@ function monacoEditorPlugin(options = {}) {
|
|
|
5775
7091
|
resolvedConfig = config;
|
|
5776
7092
|
const version = readMonacoVersion(config.root);
|
|
5777
7093
|
const key = crypto4.createHash("sha1").update(version + "|" + publicPath).digest("hex").slice(0, 8);
|
|
5778
|
-
cacheDir =
|
|
7094
|
+
cacheDir = path18.resolve(config.root, "node_modules/.nasti/monaco", key);
|
|
5779
7095
|
},
|
|
5780
7096
|
async configureServer(server) {
|
|
5781
7097
|
const shouldBuild = !isCDN(publicPath) || forceBuildCDN;
|
|
5782
7098
|
const watcher = server.watcher;
|
|
5783
|
-
const monacoDir =
|
|
7099
|
+
const monacoDir = path18.resolve(resolvedConfig.root, "node_modules/monaco-editor");
|
|
5784
7100
|
try {
|
|
5785
7101
|
watcher?.unwatch?.(monacoDir);
|
|
5786
7102
|
} catch {
|
|
@@ -5810,7 +7126,7 @@ function monacoEditorPlugin(options = {}) {
|
|
|
5810
7126
|
const file = await buildWorker(worker);
|
|
5811
7127
|
res.setHeader("Content-Type", "application/javascript; charset=utf-8");
|
|
5812
7128
|
res.setHeader("Cache-Control", "public, max-age=604800, immutable");
|
|
5813
|
-
|
|
7129
|
+
fs13.createReadStream(file).pipe(res);
|
|
5814
7130
|
} catch (e) {
|
|
5815
7131
|
res.statusCode = 500;
|
|
5816
7132
|
res.end(`Monaco worker build failed: ${e.message}`);
|
|
@@ -5845,16 +7161,16 @@ self.monaco = monaco;`,
|
|
|
5845
7161
|
resolvedConfig.root,
|
|
5846
7162
|
resolvedConfig.build.outDir,
|
|
5847
7163
|
resolvedConfig.base
|
|
5848
|
-
) : isCDN(publicPath) ?
|
|
7164
|
+
) : isCDN(publicPath) ? path18.resolve(resolvedConfig.root, resolvedConfig.build.outDir, "monaco") : path18.resolve(
|
|
5849
7165
|
resolvedConfig.root,
|
|
5850
7166
|
resolvedConfig.build.outDir,
|
|
5851
7167
|
publicPath.replace(/^\//, "")
|
|
5852
7168
|
);
|
|
5853
|
-
|
|
7169
|
+
fs13.mkdirSync(outDir, { recursive: true });
|
|
5854
7170
|
for (const worker of workers) {
|
|
5855
7171
|
try {
|
|
5856
7172
|
const cacheFile = await buildWorker(worker);
|
|
5857
|
-
|
|
7173
|
+
fs13.copyFileSync(cacheFile, path18.join(outDir, `${worker.label}.worker.js`));
|
|
5858
7174
|
} catch (e) {
|
|
5859
7175
|
throw new Error(
|
|
5860
7176
|
`[nasti:monaco-editor] worker build failed for "${worker.label}": ${e.message}
|