weapp-vite 6.15.14 → 6.15.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/bootstrap.js +34 -0
- package/bin/bootstrap.test.ts +31 -2
- package/dist/auto-routes.mjs +1 -1
- package/dist/cli.mjs +306 -12
- package/dist/{config-DdiGMnVs.d.mts → config-BEJTp6sp.d.mts} +46 -2
- package/dist/config.d.mts +1 -1
- package/dist/{createContext-BcX4FNt9.mjs → createContext-xOVHRF1m.mjs} +1084 -322
- package/dist/file-CNC4V9ax.mjs +2 -0
- package/dist/{file-BR4Z0ErL.mjs → file-DEHK6p9s.mjs} +1 -1
- package/dist/getInstance-DP821mDU.mjs +2 -0
- package/dist/index.d.mts +1 -1
- package/dist/index.mjs +1 -1
- package/dist/json.d.mts +1 -1
- package/dist/mcp.d.mts +1 -1
- package/dist/types.d.mts +1 -1
- package/package.json +4 -4
- package/dist/file-DzNGraHL.mjs +0 -2
- package/dist/getInstance-CyAuPueV.mjs +0 -2
package/bin/bootstrap.js
CHANGED
|
@@ -6,6 +6,38 @@ function getGlobalProcess() {
|
|
|
6
6
|
return Reflect.get(globalThis, 'process')
|
|
7
7
|
}
|
|
8
8
|
|
|
9
|
+
function isKnownLocalPkgResolveNoise(args) {
|
|
10
|
+
const message = args
|
|
11
|
+
.map((value) => {
|
|
12
|
+
if (value instanceof Error) {
|
|
13
|
+
return `${value.message}\n${value.stack ?? ''}`
|
|
14
|
+
}
|
|
15
|
+
return String(value)
|
|
16
|
+
})
|
|
17
|
+
.join('\n')
|
|
18
|
+
|
|
19
|
+
return message.includes('ERR_INVALID_FILE_URL_HOST')
|
|
20
|
+
&& (message.includes('local-pkg') || message.includes('mlly'))
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function guardKnownLocalPkgResolveNoise() {
|
|
24
|
+
// eslint-disable-next-line no-console -- CLI 启动阶段需要定向过滤已知三方解析噪音
|
|
25
|
+
const originalConsoleError = console.error
|
|
26
|
+
|
|
27
|
+
// eslint-disable-next-line no-console -- CLI 启动阶段需要定向过滤已知三方解析噪音
|
|
28
|
+
console.error = (...args) => {
|
|
29
|
+
if (isKnownLocalPkgResolveNoise(args)) {
|
|
30
|
+
return
|
|
31
|
+
}
|
|
32
|
+
originalConsoleError(...args)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return () => {
|
|
36
|
+
// eslint-disable-next-line no-console -- 恢复原始 console.error
|
|
37
|
+
console.error = originalConsoleError
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
9
41
|
export function formatPrepareSkipMessage(error) {
|
|
10
42
|
const message = error instanceof Error ? error.message : String(error)
|
|
11
43
|
return `[prepare] 跳过 .weapp-vite 支持文件预生成:${message}`
|
|
@@ -77,6 +109,7 @@ export async function runWeappViteCLI(options = {}) {
|
|
|
77
109
|
write = message => getGlobalProcess().stderr.write(`\n WARN ${message}\n\n`),
|
|
78
110
|
} = options
|
|
79
111
|
const restorePrepareGuard = guardPrepareProcessExit(argv)
|
|
112
|
+
const restoreKnownNoiseGuard = guardKnownLocalPkgResolveNoise()
|
|
80
113
|
|
|
81
114
|
try {
|
|
82
115
|
await importer()
|
|
@@ -90,6 +123,7 @@ export async function runWeappViteCLI(options = {}) {
|
|
|
90
123
|
throw error
|
|
91
124
|
}
|
|
92
125
|
finally {
|
|
126
|
+
restoreKnownNoiseGuard()
|
|
93
127
|
if (!isPrepareCommand(argv)) {
|
|
94
128
|
restorePrepareGuard()
|
|
95
129
|
}
|
package/bin/bootstrap.test.ts
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
|
-
import { describe, expect, it, vi } from 'vitest'
|
|
2
|
-
import { formatPrepareSkipMessage, guardPrepareProcessExit, runWeappViteCLI } from './bootstrap.js'
|
|
1
|
+
import { afterEach, describe, expect, it, vi } from 'vitest'
|
|
2
|
+
import { formatPrepareSkipMessage, guardKnownLocalPkgResolveNoise, guardPrepareProcessExit, runWeappViteCLI } from './bootstrap.js'
|
|
3
3
|
|
|
4
4
|
describe('bin bootstrap', () => {
|
|
5
|
+
afterEach(() => {
|
|
6
|
+
vi.restoreAllMocks()
|
|
7
|
+
})
|
|
8
|
+
|
|
5
9
|
it('guards process exit state for prepare at bin level', () => {
|
|
6
10
|
process.exitCode = 1
|
|
7
11
|
const restore = guardPrepareProcessExit(['prepare'])
|
|
@@ -60,4 +64,29 @@ describe('bin bootstrap', () => {
|
|
|
60
64
|
|
|
61
65
|
expect(process.exitCode).toBe(0)
|
|
62
66
|
})
|
|
67
|
+
|
|
68
|
+
it('suppresses known local-pkg resolve noise during bootstrap', () => {
|
|
69
|
+
const consoleErrorSpy = vi.fn()
|
|
70
|
+
// eslint-disable-next-line no-console -- 测试里需要替换 console.error
|
|
71
|
+
const originalConsoleError = console.error
|
|
72
|
+
// eslint-disable-next-line no-console -- 测试里需要观察过滤后的 console.error
|
|
73
|
+
console.error = consoleErrorSpy
|
|
74
|
+
|
|
75
|
+
const restore = guardKnownLocalPkgResolveNoise()
|
|
76
|
+
try {
|
|
77
|
+
// eslint-disable-next-line no-console -- 触发已知噪音分支
|
|
78
|
+
console.error(new Error('TypeError [ERR_INVALID_FILE_URL_HOST]: File URL host must be "localhost" or empty on darwin\n at _resolve (/tmp/local-pkg/dist/index.mjs:1:1)\n at resolveSync (/tmp/mlly/dist/index.mjs:1:1)'))
|
|
79
|
+
// eslint-disable-next-line no-console -- 触发普通错误透传分支
|
|
80
|
+
console.error(new Error('boom'))
|
|
81
|
+
}
|
|
82
|
+
finally {
|
|
83
|
+
restore()
|
|
84
|
+
// eslint-disable-next-line no-console -- 恢复测试前的 console.error
|
|
85
|
+
console.error = originalConsoleError
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
expect(consoleErrorSpy).toHaveBeenCalledTimes(1)
|
|
89
|
+
expect(consoleErrorSpy.mock.calls[0]?.[0]).toBeInstanceOf(Error)
|
|
90
|
+
expect(consoleErrorSpy.mock.calls[0]?.[0]?.message).toBe('boom')
|
|
91
|
+
})
|
|
63
92
|
})
|
package/dist/auto-routes.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { d as getRouteRuntimeGlobalKeys, i as getCompilerContext } from "./createContext-xOVHRF1m.mjs";
|
|
2
2
|
//#region src/auto-routes.ts
|
|
3
3
|
const ROUTE_RUNTIME_OVERRIDE_KEY = Symbol.for("weapp-vite.route-runtime");
|
|
4
4
|
function createGetter(resolver) {
|
package/dist/cli.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { C as isPathInside, S as shouldPassPlatformArgToIdeOpen, _ as createCjsConfigLoadError, b as normalizeMiniPlatform, c as createSharedBuildConfig, f as resolveWeappConfigFile, g as parseCommentJson, h as loadViteConfigFile, l as SHARED_CHUNK_VIRTUAL_PREFIX, m as getProjectConfigFileName, n as syncProjectSupportFiles, p as checkRuntime, r as syncManagedTsconfigBootstrapFiles, s as formatBytes, t as createCompilerContext, u as resolveHmrProfileJsonPath, v as DEFAULT_MP_PLATFORM, x as resolveMiniPlatform, y as getDefaultIdeProjectRoot } from "./createContext-xOVHRF1m.mjs";
|
|
2
2
|
import { r as logger_default, t as colors } from "./logger-CgxdNjvb.mjs";
|
|
3
|
-
import { h as VERSION } from "./file-
|
|
3
|
+
import { h as VERSION } from "./file-DEHK6p9s.mjs";
|
|
4
4
|
import { a as resolveWeappMcpConfig, o as startWeappViteMcpServer } from "./mcp-DRlj32v4.mjs";
|
|
5
5
|
import { createRequire } from "node:module";
|
|
6
6
|
import path, { posix } from "pathe";
|
|
@@ -22,6 +22,106 @@ import { determineAgent } from "@vercel/detect-agent";
|
|
|
22
22
|
import { initConfig } from "@weapp-core/init";
|
|
23
23
|
import { createInterface } from "node:readline/promises";
|
|
24
24
|
import { clearTimeout, setTimeout as setTimeout$1 } from "node:timers";
|
|
25
|
+
//#region src/analyze/hmr.ts
|
|
26
|
+
function createMetricSummary(values) {
|
|
27
|
+
if (!values.length) return { count: 0 };
|
|
28
|
+
const total = values.reduce((sum, value) => sum + value, 0);
|
|
29
|
+
return {
|
|
30
|
+
count: values.length,
|
|
31
|
+
averageMs: total / values.length,
|
|
32
|
+
maxMs: Math.max(...values)
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
function sortCountEntries(map) {
|
|
36
|
+
return [...map.entries()].sort((left, right) => right[1] - left[1] || left[0].localeCompare(right[0])).map(([name, count]) => ({
|
|
37
|
+
name,
|
|
38
|
+
count
|
|
39
|
+
}));
|
|
40
|
+
}
|
|
41
|
+
function collectCounts(target, values) {
|
|
42
|
+
for (const value of values ?? []) {
|
|
43
|
+
if (!value) continue;
|
|
44
|
+
target.set(value, (target.get(value) ?? 0) + 1);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
function isFiniteNumber$1(value) {
|
|
48
|
+
return typeof value === "number" && Number.isFinite(value);
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* @description 聚合 HMR JSONL profile,为命令行与后续仪表盘复用。
|
|
52
|
+
*/
|
|
53
|
+
async function analyzeHmrProfile(options) {
|
|
54
|
+
const lines = (await fs.readFile(options.profilePath, "utf8")).split(/\r?\n/);
|
|
55
|
+
const samples = [];
|
|
56
|
+
let skippedLineCount = 0;
|
|
57
|
+
for (const line of lines) {
|
|
58
|
+
const trimmed = line.trim();
|
|
59
|
+
if (!trimmed) continue;
|
|
60
|
+
try {
|
|
61
|
+
const parsed = JSON.parse(trimmed);
|
|
62
|
+
if (!isFiniteNumber$1(parsed.totalMs)) {
|
|
63
|
+
skippedLineCount += 1;
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
samples.push(parsed);
|
|
67
|
+
} catch {
|
|
68
|
+
skippedLineCount += 1;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
const eventCounts = /* @__PURE__ */ new Map();
|
|
72
|
+
const dirtyReasonCounts = /* @__PURE__ */ new Map();
|
|
73
|
+
const pendingReasonCounts = /* @__PURE__ */ new Map();
|
|
74
|
+
const totalValues = [];
|
|
75
|
+
const buildCoreValues = [];
|
|
76
|
+
const transformValues = [];
|
|
77
|
+
const writeValues = [];
|
|
78
|
+
const watchToDirtyValues = [];
|
|
79
|
+
const emitValues = [];
|
|
80
|
+
const sharedChunkValues = [];
|
|
81
|
+
for (const sample of samples) {
|
|
82
|
+
totalValues.push(sample.totalMs);
|
|
83
|
+
if (sample.event) eventCounts.set(sample.event, (eventCounts.get(sample.event) ?? 0) + 1);
|
|
84
|
+
if (isFiniteNumber$1(sample.buildCoreMs)) buildCoreValues.push(sample.buildCoreMs);
|
|
85
|
+
if (isFiniteNumber$1(sample.transformMs)) transformValues.push(sample.transformMs);
|
|
86
|
+
if (isFiniteNumber$1(sample.writeMs)) writeValues.push(sample.writeMs);
|
|
87
|
+
if (isFiniteNumber$1(sample.watchToDirtyMs)) watchToDirtyValues.push(sample.watchToDirtyMs);
|
|
88
|
+
if (isFiniteNumber$1(sample.emitMs)) emitValues.push(sample.emitMs);
|
|
89
|
+
if (isFiniteNumber$1(sample.sharedChunkResolveMs)) sharedChunkValues.push(sample.sharedChunkResolveMs);
|
|
90
|
+
collectCounts(dirtyReasonCounts, sample.dirtyReasonSummary);
|
|
91
|
+
collectCounts(pendingReasonCounts, sample.pendingReasonSummary);
|
|
92
|
+
}
|
|
93
|
+
const orderedByTime = [...samples].sort((left, right) => {
|
|
94
|
+
const leftTime = typeof left.timestamp === "string" ? Date.parse(left.timestamp) : NaN;
|
|
95
|
+
const rightTime = typeof right.timestamp === "string" ? Date.parse(right.timestamp) : NaN;
|
|
96
|
+
if (Number.isFinite(leftTime) && Number.isFinite(rightTime)) return leftTime - rightTime;
|
|
97
|
+
return 0;
|
|
98
|
+
});
|
|
99
|
+
const slowestSamples = [...samples].sort((left, right) => (right.totalMs ?? 0) - (left.totalMs ?? 0)).slice(0, options.topSlowest ?? 5);
|
|
100
|
+
return {
|
|
101
|
+
runtime: "mini",
|
|
102
|
+
kind: "hmr-profile",
|
|
103
|
+
generatedAt: (options.now ?? /* @__PURE__ */ new Date()).toISOString(),
|
|
104
|
+
profilePath: options.profilePath,
|
|
105
|
+
sampleCount: samples.length,
|
|
106
|
+
skippedLineCount,
|
|
107
|
+
firstTimestamp: orderedByTime[0]?.timestamp,
|
|
108
|
+
lastTimestamp: orderedByTime.at(-1)?.timestamp,
|
|
109
|
+
metrics: {
|
|
110
|
+
totalMs: createMetricSummary(totalValues),
|
|
111
|
+
buildCoreMs: createMetricSummary(buildCoreValues),
|
|
112
|
+
transformMs: createMetricSummary(transformValues),
|
|
113
|
+
writeMs: createMetricSummary(writeValues),
|
|
114
|
+
watchToDirtyMs: createMetricSummary(watchToDirtyValues),
|
|
115
|
+
emitMs: createMetricSummary(emitValues),
|
|
116
|
+
sharedChunkResolveMs: createMetricSummary(sharedChunkValues)
|
|
117
|
+
},
|
|
118
|
+
events: sortCountEntries(eventCounts),
|
|
119
|
+
dirtyReasons: sortCountEntries(dirtyReasonCounts),
|
|
120
|
+
pendingReasons: sortCountEntries(pendingReasonCounts),
|
|
121
|
+
slowestSamples
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
//#endregion
|
|
25
125
|
//#region src/analyze/subpackages/classifier.ts
|
|
26
126
|
const VIRTUAL_MODULE_INDICATOR = "\0";
|
|
27
127
|
const VIRTUAL_PREFIX = `${SHARED_CHUNK_VIRTUAL_PREFIX}/`;
|
|
@@ -809,8 +909,42 @@ async function writeAnalyzeResult(result, outputOption, configService) {
|
|
|
809
909
|
logger_default.success(`分析结果已写入 ${colors.green(relativeOutput)}`);
|
|
810
910
|
return resolvedOutputPath;
|
|
811
911
|
}
|
|
912
|
+
function formatMetricSummary(label, metric) {
|
|
913
|
+
if (!metric.count || metric.averageMs === void 0 || metric.maxMs === void 0) return;
|
|
914
|
+
return `${label} avg ${metric.averageMs.toFixed(2)} ms,max ${metric.maxMs.toFixed(2)} ms`;
|
|
915
|
+
}
|
|
916
|
+
function formatCountItems(items, limit = 5) {
|
|
917
|
+
return items.slice(0, limit).map((item) => `${item.name} x${item.count}`).join(",");
|
|
918
|
+
}
|
|
919
|
+
function printHmrProfileAnalysisSummary(result, configService) {
|
|
920
|
+
logger_default.success("HMR profile 分析完成");
|
|
921
|
+
logger_default.info(`- profile:${colors.green(configService.relativeCwd(result.profilePath))}`);
|
|
922
|
+
logger_default.info(`- 样本:${result.sampleCount} 条`);
|
|
923
|
+
if (result.firstTimestamp && result.lastTimestamp) logger_default.info(`- 时间范围:${result.firstTimestamp} -> ${result.lastTimestamp}`);
|
|
924
|
+
const totalSummary = formatMetricSummary("total", result.metrics.totalMs);
|
|
925
|
+
const watchSummary = formatMetricSummary("watch->dirty", result.metrics.watchToDirtyMs);
|
|
926
|
+
const emitSummary = formatMetricSummary("emit", result.metrics.emitMs);
|
|
927
|
+
const sharedSummary = formatMetricSummary("shared", result.metrics.sharedChunkResolveMs);
|
|
928
|
+
for (const summary of [
|
|
929
|
+
totalSummary,
|
|
930
|
+
watchSummary,
|
|
931
|
+
emitSummary,
|
|
932
|
+
sharedSummary
|
|
933
|
+
]) if (summary) logger_default.info(`- ${summary}`);
|
|
934
|
+
if (result.events.length) logger_default.info(`- 事件分布:${formatCountItems(result.events)}`);
|
|
935
|
+
if (result.dirtyReasons.length) logger_default.info(`- 主要 dirty 原因:${formatCountItems(result.dirtyReasons)}`);
|
|
936
|
+
if (result.pendingReasons.length) logger_default.info(`- 主要 pending 原因:${formatCountItems(result.pendingReasons)}`);
|
|
937
|
+
if (result.skippedLineCount > 0) logger_default.warn(`- 跳过 ${result.skippedLineCount} 条无法解析的 profile 记录`);
|
|
938
|
+
if (result.slowestSamples.length) {
|
|
939
|
+
logger_default.info("- 最慢样本:");
|
|
940
|
+
for (const sample of result.slowestSamples.slice(0, 3)) {
|
|
941
|
+
const fileLabel = sample.file ? configService.relativeCwd(sample.file) : "(unknown)";
|
|
942
|
+
logger_default.info(` - ${sample.totalMs?.toFixed(2) ?? "0.00"} ms,${sample.event ?? "unknown"},${fileLabel}`);
|
|
943
|
+
}
|
|
944
|
+
}
|
|
945
|
+
}
|
|
812
946
|
function registerAnalyzeCommand(cli) {
|
|
813
|
-
cli.command("analyze [root]", "analyze 两端包体与源码映射").option("--json", `[boolean] 输出 JSON 结果`).option("--output <file>", `[string] 将分析结果写入指定文件(JSON)`).option("-p, --platform <platform>", `[string] target platform (weapp | h5)`).option("--project-config <path>", `[string] project config path (miniprogram only)`).action(async (root, options) => {
|
|
947
|
+
cli.command("analyze [root]", "analyze 两端包体与源码映射").option("--hmr-profile [file]", `[string | boolean] 分析 HMR JSONL profile,省略值时优先读取配置,否则回退到默认路径`).option("--json", `[boolean] 输出 JSON 结果`).option("--output <file>", `[string] 将分析结果写入指定文件(JSON)`).option("-p, --platform <platform>", `[string] target platform (weapp | h5)`).option("--project-config <path>", `[string] project config path (miniprogram only)`).action(async (root, options) => {
|
|
814
948
|
filterDuplicateOptions(options);
|
|
815
949
|
const configFile = resolveConfigFile(options);
|
|
816
950
|
const outputJson = coerceBooleanOption(options.json);
|
|
@@ -830,6 +964,21 @@ function registerAnalyzeCommand(cli) {
|
|
|
830
964
|
resolvedConfigPlatform: ctx.configService.platform
|
|
831
965
|
});
|
|
832
966
|
const outputOption = typeof options.output === "string" ? options.output.trim() : "";
|
|
967
|
+
if (options.hmrProfile !== void 0 && options.hmrProfile !== false) {
|
|
968
|
+
const profileOption = typeof options.hmrProfile === "string" && options.hmrProfile.trim() ? options.hmrProfile.trim() : ctx.configService.weappViteConfig.hmr?.profileJson;
|
|
969
|
+
const profilePath = resolveHmrProfileJsonPath({
|
|
970
|
+
cwd: ctx.configService.cwd,
|
|
971
|
+
option: profileOption,
|
|
972
|
+
fallbackToDefault: true
|
|
973
|
+
});
|
|
974
|
+
if (!profilePath) throw new Error("未找到可用的 HMR profile 文件路径");
|
|
975
|
+
const hmrProfileResult = await analyzeHmrProfile({ profilePath });
|
|
976
|
+
const writtenPath = await writeAnalyzeResult(hmrProfileResult, outputOption, ctx.configService);
|
|
977
|
+
if (outputJson) {
|
|
978
|
+
if (!writtenPath) process.stdout.write(`${JSON.stringify(hmrProfileResult, null, 2)}\n`);
|
|
979
|
+
} else printHmrProfileAnalysisSummary(hmrProfileResult, ctx.configService);
|
|
980
|
+
return;
|
|
981
|
+
}
|
|
833
982
|
if (targets.runWeb) {
|
|
834
983
|
const webResult = createWebAnalyzeResult(ctx.configService, { platform: targets.label === "web" ? "web" : "h5" });
|
|
835
984
|
const writtenPath = await writeAnalyzeResult(webResult, outputOption, ctx.configService);
|
|
@@ -1025,7 +1174,7 @@ async function tryExecuteWechatIdeCliCommandByHelper(argv) {
|
|
|
1025
1174
|
async function executeWechatIdeCliCommand(argv, options = {}) {
|
|
1026
1175
|
const { automatorMode = "prefer", cancelLevel = "warn", httpMode = "prefer", onNonLoginError, onRetry, projectPath } = options;
|
|
1027
1176
|
await runWithSuspendedSharedInput(async () => {
|
|
1028
|
-
try {
|
|
1177
|
+
if (httpMode !== "skip") try {
|
|
1029
1178
|
if (await tryExecuteWechatIdeCliCommandByHttp(argv, projectPath)) return;
|
|
1030
1179
|
} catch (error) {
|
|
1031
1180
|
if (httpMode === "require") throw error;
|
|
@@ -1231,6 +1380,49 @@ async function tryOpenWechatIdeByAutomator(projectPath, options) {
|
|
|
1231
1380
|
await openWechatIdeByAutomator(projectPath);
|
|
1232
1381
|
return true;
|
|
1233
1382
|
}
|
|
1383
|
+
/**
|
|
1384
|
+
* @description 打开后主动刷新微信开发者工具的项目索引,避免模拟器沿用过期 app 配置。
|
|
1385
|
+
*/
|
|
1386
|
+
async function stabilizeOpenedWechatIdeProject(projectPath, servicePortEnabled) {
|
|
1387
|
+
if (servicePortEnabled === false) return;
|
|
1388
|
+
try {
|
|
1389
|
+
await executeWechatIdeCliCommand(["compile"], {
|
|
1390
|
+
httpMode: "prefer",
|
|
1391
|
+
onNonLoginError: (error) => logger_default.error(error),
|
|
1392
|
+
projectPath
|
|
1393
|
+
});
|
|
1394
|
+
await executeWechatIdeCliCommand([
|
|
1395
|
+
"reset-fileutils",
|
|
1396
|
+
"-p",
|
|
1397
|
+
projectPath
|
|
1398
|
+
], {
|
|
1399
|
+
httpMode: "prefer",
|
|
1400
|
+
onNonLoginError: (error) => logger_default.error(error),
|
|
1401
|
+
projectPath
|
|
1402
|
+
});
|
|
1403
|
+
await executeWechatIdeCliCommand([
|
|
1404
|
+
"engine",
|
|
1405
|
+
"build",
|
|
1406
|
+
projectPath
|
|
1407
|
+
], {
|
|
1408
|
+
httpMode: "prefer",
|
|
1409
|
+
onNonLoginError: (error) => logger_default.error(error),
|
|
1410
|
+
projectPath
|
|
1411
|
+
});
|
|
1412
|
+
try {
|
|
1413
|
+
await executeWechatIdeCliCommand(["compile"], {
|
|
1414
|
+
automatorMode: "require",
|
|
1415
|
+
httpMode: "skip",
|
|
1416
|
+
projectPath
|
|
1417
|
+
});
|
|
1418
|
+
} catch (error) {
|
|
1419
|
+
if (shouldLogAutomatorFallbackError()) logger_default.error(error);
|
|
1420
|
+
}
|
|
1421
|
+
} catch (error) {
|
|
1422
|
+
logger_default.warn("刷新微信开发者工具项目索引失败,已保留当前打开状态;如模拟器仍显示旧状态,可手动刷新一次。");
|
|
1423
|
+
if (shouldLogAutomatorFallbackError()) logger_default.error(error);
|
|
1424
|
+
}
|
|
1425
|
+
}
|
|
1234
1426
|
function createIdeOpenArgv(platform, projectPath, options = {}) {
|
|
1235
1427
|
const argv = ["open", "-p"];
|
|
1236
1428
|
if (projectPath) argv.push(projectPath);
|
|
@@ -1251,7 +1443,10 @@ async function openIde(platform, projectPath, options = {}) {
|
|
|
1251
1443
|
}
|
|
1252
1444
|
if (platform === "weapp" && projectPath && bootstrapResult?.servicePortEnabled === false) logger_default.warn("检测到微信开发者工具服务端口当前处于关闭状态,已保留用户设置并回退到普通 open 流程。");
|
|
1253
1445
|
if (platform === "weapp" && projectPath && options.trustProject !== false && bootstrapResult?.servicePortEnabled !== false) try {
|
|
1254
|
-
if (await tryOpenWechatIdeByAutomator(projectPath, options))
|
|
1446
|
+
if (await tryOpenWechatIdeByAutomator(projectPath, options)) {
|
|
1447
|
+
await stabilizeOpenedWechatIdeProject(projectPath, bootstrapResult?.servicePortEnabled);
|
|
1448
|
+
return;
|
|
1449
|
+
}
|
|
1255
1450
|
} catch (error) {
|
|
1256
1451
|
if (isAutomatorLoginError(error)) {
|
|
1257
1452
|
logger_default.error("检测到微信开发者工具登录状态失效,请先登录后重试。");
|
|
@@ -1261,6 +1456,7 @@ async function openIde(platform, projectPath, options = {}) {
|
|
|
1261
1456
|
if (shouldLogAutomatorFallbackError()) logger_default.error(error);
|
|
1262
1457
|
}
|
|
1263
1458
|
await runWechatIdeOpenWithRetry(createIdeOpenArgv(platform, projectPath, options));
|
|
1459
|
+
if (platform === "weapp" && projectPath) await stabilizeOpenedWechatIdeProject(projectPath, bootstrapResult?.servicePortEnabled);
|
|
1264
1460
|
}
|
|
1265
1461
|
/**
|
|
1266
1462
|
* @description 解析 IDE 相关命令所需的平台、项目目录与配置上下文。
|
|
@@ -1280,6 +1476,7 @@ async function resolveIdeCommandContext(options) {
|
|
|
1280
1476
|
platform ??= ctx.configService.platform;
|
|
1281
1477
|
if (!projectPath) projectPath = resolveIdeProjectRoot(ctx.configService.mpDistRoot, ctx.configService.cwd);
|
|
1282
1478
|
return {
|
|
1479
|
+
cwd: ctx.configService.cwd,
|
|
1283
1480
|
platform,
|
|
1284
1481
|
projectPath,
|
|
1285
1482
|
weappViteConfig: ctx.configService.weappViteConfig,
|
|
@@ -1291,6 +1488,7 @@ async function resolveIdeCommandContext(options) {
|
|
|
1291
1488
|
if (defaultProjectRoot) projectPath = resolveIdeProjectRoot(defaultProjectRoot, cwd);
|
|
1292
1489
|
}
|
|
1293
1490
|
return {
|
|
1491
|
+
cwd,
|
|
1294
1492
|
platform,
|
|
1295
1493
|
projectPath
|
|
1296
1494
|
};
|
|
@@ -1717,6 +1915,79 @@ function sleep(ms) {
|
|
|
1717
1915
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
1718
1916
|
}
|
|
1719
1917
|
//#endregion
|
|
1918
|
+
//#region src/cli/hmrProfileSummary.ts
|
|
1919
|
+
function isFiniteNumber(value) {
|
|
1920
|
+
return typeof value === "number" && Number.isFinite(value);
|
|
1921
|
+
}
|
|
1922
|
+
function parseLatestHmrProfileSample(content) {
|
|
1923
|
+
const lines = content.split(/\r?\n/);
|
|
1924
|
+
for (let index = lines.length - 1; index >= 0; index -= 1) {
|
|
1925
|
+
const trimmed = lines[index]?.trim();
|
|
1926
|
+
if (!trimmed) continue;
|
|
1927
|
+
try {
|
|
1928
|
+
const parsed = JSON.parse(trimmed);
|
|
1929
|
+
if (isFiniteNumber(parsed.totalMs)) return parsed;
|
|
1930
|
+
} catch {
|
|
1931
|
+
continue;
|
|
1932
|
+
}
|
|
1933
|
+
}
|
|
1934
|
+
}
|
|
1935
|
+
function formatPhaseHint(sample) {
|
|
1936
|
+
const topPhase = [
|
|
1937
|
+
{
|
|
1938
|
+
label: "build-core",
|
|
1939
|
+
value: sample.buildCoreMs
|
|
1940
|
+
},
|
|
1941
|
+
{
|
|
1942
|
+
label: "transform",
|
|
1943
|
+
value: sample.transformMs
|
|
1944
|
+
},
|
|
1945
|
+
{
|
|
1946
|
+
label: "watch->dirty",
|
|
1947
|
+
value: sample.watchToDirtyMs
|
|
1948
|
+
},
|
|
1949
|
+
{
|
|
1950
|
+
label: "emit",
|
|
1951
|
+
value: sample.emitMs
|
|
1952
|
+
},
|
|
1953
|
+
{
|
|
1954
|
+
label: "shared",
|
|
1955
|
+
value: sample.sharedChunkResolveMs
|
|
1956
|
+
},
|
|
1957
|
+
{
|
|
1958
|
+
label: "write",
|
|
1959
|
+
value: sample.writeMs
|
|
1960
|
+
}
|
|
1961
|
+
].filter((phase) => isFiniteNumber(phase.value)).sort((left, right) => (right.value ?? 0) - (left.value ?? 0))[0];
|
|
1962
|
+
if (!topPhase || (topPhase.value ?? 0) < 5) return;
|
|
1963
|
+
return `${topPhase.label} ${topPhase.value.toFixed(2)} ms`;
|
|
1964
|
+
}
|
|
1965
|
+
/**
|
|
1966
|
+
* @description 读取最近一次 HMR profile,并格式化为 IDE 日志启动前的单行摘要。
|
|
1967
|
+
*/
|
|
1968
|
+
async function readLatestHmrProfileSummary(options) {
|
|
1969
|
+
const profilePath = resolveHmrProfileJsonPath({
|
|
1970
|
+
cwd: options.cwd,
|
|
1971
|
+
option: options.weappViteConfig?.hmr?.profileJson
|
|
1972
|
+
});
|
|
1973
|
+
if (!profilePath) return;
|
|
1974
|
+
const content = await fs.readFile(profilePath, "utf8").catch(() => void 0);
|
|
1975
|
+
if (!content) return;
|
|
1976
|
+
const sample = parseLatestHmrProfileSample(content);
|
|
1977
|
+
if (!sample || !isFiniteNumber(sample.totalMs)) return;
|
|
1978
|
+
const relativeCwd = options.relativeCwd ?? ((value) => value);
|
|
1979
|
+
const segments = [`[hmr] 最近一次热更新 ${sample.totalMs.toFixed(2)} ms`];
|
|
1980
|
+
if (sample.event) segments.push(sample.event);
|
|
1981
|
+
if (sample.file) segments.push(relativeCwd(sample.file));
|
|
1982
|
+
const phaseHint = formatPhaseHint(sample);
|
|
1983
|
+
if (phaseHint) segments.push(`主耗时 ${phaseHint}`);
|
|
1984
|
+
return {
|
|
1985
|
+
file: sample.file,
|
|
1986
|
+
profilePath,
|
|
1987
|
+
line: segments.join(",")
|
|
1988
|
+
};
|
|
1989
|
+
}
|
|
1990
|
+
//#endregion
|
|
1720
1991
|
//#region src/cli/commands/ide.ts
|
|
1721
1992
|
async function waitForTermination(cleanup) {
|
|
1722
1993
|
await new Promise((resolve) => {
|
|
@@ -1805,6 +2076,12 @@ async function runIdeCommand(action, root, options) {
|
|
|
1805
2076
|
enabled: true
|
|
1806
2077
|
}
|
|
1807
2078
|
});
|
|
2079
|
+
const latestHmrSummary = await readLatestHmrProfileSummary({
|
|
2080
|
+
cwd: resolved.cwd ?? process.cwd(),
|
|
2081
|
+
relativeCwd: (value) => resolved.cwd ? value.replace(`${resolved.cwd}/`, "") : value,
|
|
2082
|
+
weappViteConfig: resolved.weappViteConfig
|
|
2083
|
+
});
|
|
2084
|
+
if (latestHmrSummary) logger_default.info(latestHmrSummary.line);
|
|
1808
2085
|
const session = await startForwardConsoleBridge({
|
|
1809
2086
|
projectPath: resolved.projectPath,
|
|
1810
2087
|
agentName: void 0,
|
|
@@ -2251,13 +2528,19 @@ function registerOpenCommand(cli) {
|
|
|
2251
2528
|
filterDuplicateOptions(options);
|
|
2252
2529
|
const configFile = resolveConfigFile(options);
|
|
2253
2530
|
const targets = resolveRuntimeTargets(options);
|
|
2254
|
-
const { platform, projectPath, mpDistRoot } = await resolveIdeCommandContext({
|
|
2531
|
+
const { cwd, platform, projectPath, mpDistRoot, weappViteConfig } = await resolveIdeCommandContext({
|
|
2255
2532
|
configFile,
|
|
2256
2533
|
mode: options.mode ?? "development",
|
|
2257
2534
|
platform: targets.mpPlatform,
|
|
2258
2535
|
projectPath: root,
|
|
2259
2536
|
cliPlatform: targets.rawPlatform
|
|
2260
2537
|
});
|
|
2538
|
+
const latestHmrSummary = await readLatestHmrProfileSummary({
|
|
2539
|
+
cwd: cwd ?? process.cwd(),
|
|
2540
|
+
relativeCwd: (value) => cwd ? value.replace(`${cwd}/`, "") : value,
|
|
2541
|
+
weappViteConfig
|
|
2542
|
+
});
|
|
2543
|
+
if (latestHmrSummary) logger_default.info(latestHmrSummary.line);
|
|
2261
2544
|
await openIde(platform, projectPath ?? resolveIdeProjectRoot(mpDistRoot, process.cwd()), { trustProject: options.trustProject });
|
|
2262
2545
|
});
|
|
2263
2546
|
}
|
|
@@ -2292,6 +2575,15 @@ function registerPrepareCommand(cli) {
|
|
|
2292
2575
|
}
|
|
2293
2576
|
//#endregion
|
|
2294
2577
|
//#region src/cli/devHotkeys/devtools.ts
|
|
2578
|
+
async function appendLatestHmrSummary(baseSummary, options) {
|
|
2579
|
+
const summary = await readLatestHmrProfileSummary({
|
|
2580
|
+
cwd: options.cwd,
|
|
2581
|
+
relativeCwd: (value) => value.replace(`${options.cwd}/`, ""),
|
|
2582
|
+
weappViteConfig: options.weappViteConfig
|
|
2583
|
+
});
|
|
2584
|
+
if (!summary) return baseSummary;
|
|
2585
|
+
return `${baseSummary};${summary.line}`;
|
|
2586
|
+
}
|
|
2295
2587
|
/**
|
|
2296
2588
|
* @description 重置当前 DevTools automator 共享会话。
|
|
2297
2589
|
*/
|
|
@@ -2313,7 +2605,7 @@ async function runResetAndReopenDevtoolsAction(options) {
|
|
|
2313
2605
|
await closeSharedMiniProgram(options.projectPath);
|
|
2314
2606
|
const summary = await options.openIde();
|
|
2315
2607
|
logger_default.success("[dev action] 当前 DevTools 会话已重置,并已重新打开项目。");
|
|
2316
|
-
return summary ?? "已重置当前 DevTools 会话并重新打开项目";
|
|
2608
|
+
return await appendLatestHmrSummary(summary ?? "已重置当前 DevTools 会话并重新打开项目", options);
|
|
2317
2609
|
}
|
|
2318
2610
|
/**
|
|
2319
2611
|
* @description 手动触发一次当前小程序 dev 重新构建。
|
|
@@ -2340,7 +2632,7 @@ async function runOpenIdeAction(options) {
|
|
|
2340
2632
|
await closeSharedMiniProgram(options.projectPath);
|
|
2341
2633
|
const summary = await options.openIde();
|
|
2342
2634
|
logger_default.success("[dev action] 微信开发者工具项目已重新打开。");
|
|
2343
|
-
return summary ?? "已重新打开微信开发者工具项目";
|
|
2635
|
+
return await appendLatestHmrSummary(summary ?? "已重新打开微信开发者工具项目", options);
|
|
2344
2636
|
}
|
|
2345
2637
|
//#endregion
|
|
2346
2638
|
//#region src/cli/devHotkeys/screenshot.ts
|
|
@@ -2492,7 +2784,7 @@ function resolveRunnableHotkeyDefinition(input) {
|
|
|
2492
2784
|
}
|
|
2493
2785
|
//#endregion
|
|
2494
2786
|
//#region package.json
|
|
2495
|
-
var version = "6.15.
|
|
2787
|
+
var version = "6.15.16";
|
|
2496
2788
|
//#endregion
|
|
2497
2789
|
//#region src/cli/devHotkeys/format.ts
|
|
2498
2790
|
const FULLWIDTH_ASCII_START = 65281;
|
|
@@ -2735,8 +3027,9 @@ function startDevHotkeys(options) {
|
|
|
2735
3027
|
return;
|
|
2736
3028
|
}
|
|
2737
3029
|
const action = resolveRunnableHotkeyDefinition(normalizedInput) ?? resolveRunnableHotkeyDefinition(normalized);
|
|
2738
|
-
|
|
2739
|
-
|
|
3030
|
+
const run = action?.run;
|
|
3031
|
+
if (run) runAction(action.label ?? action.description, resolvePendingLabel(normalized) ?? action.pendingLabel ?? `正在执行 ${action.description}`, async () => {
|
|
3032
|
+
return await run({
|
|
2740
3033
|
options,
|
|
2741
3034
|
toggleMcp
|
|
2742
3035
|
});
|
|
@@ -3107,7 +3400,8 @@ function registerServeCommand(cli) {
|
|
|
3107
3400
|
platform: configService.platform,
|
|
3108
3401
|
projectPath: miniProgramDevActions.projectPath ?? configService.cwd,
|
|
3109
3402
|
rebuild: miniProgramDevActions.rebuild,
|
|
3110
|
-
silentStartupHint: true
|
|
3403
|
+
silentStartupHint: true,
|
|
3404
|
+
weappViteConfig: configService.weappViteConfig
|
|
3111
3405
|
}) : void 0;
|
|
3112
3406
|
try {
|
|
3113
3407
|
const analyzeController = createAnalyzeController({
|
|
@@ -6,7 +6,7 @@ import { LoggerConfig } from "@weapp-core/logger";
|
|
|
6
6
|
import { ConfigEnv, ConfigEnv as ConfigEnv$1, InlineConfig, InlineConfig as InlineConfig$1, Plugin as Plugin$1, PluginOption, ResolvedConfig, UserConfig, ViteDevServer, ViteDevServer as ViteDevServer$1, build } from "vite";
|
|
7
7
|
import { LRUCache } from "lru-cache";
|
|
8
8
|
import { fdir } from "fdir";
|
|
9
|
-
import { InputOption, RolldownBuild, RolldownOptions, RolldownOutput, RolldownOutput as RolldownOutput$1, RolldownPlugin, RolldownPluginOption, RolldownWatcher, RolldownWatcher as RolldownWatcher$1, WatchOptions as RolldownWatchOptions } from "rolldown";
|
|
9
|
+
import { InputOption, ResolvedId, RolldownBuild, RolldownOptions, RolldownOutput, RolldownOutput as RolldownOutput$1, RolldownPlugin, RolldownPluginOption, RolldownWatcher, RolldownWatcher as RolldownWatcher$1, WatchOptions as RolldownWatchOptions } from "rolldown";
|
|
10
10
|
import { Options } from "rolldown-plugin-dts";
|
|
11
11
|
import { Buffer } from "node:buffer";
|
|
12
12
|
import { PluginOptions } from "vite-tsconfig-paths";
|
|
@@ -504,6 +504,14 @@ interface WeappSubPackageConfig {
|
|
|
504
504
|
interface WeappHmrConfig {
|
|
505
505
|
sharedChunks?: 'full' | 'auto' | 'off';
|
|
506
506
|
touchAppWxss?: boolean | 'auto';
|
|
507
|
+
/**
|
|
508
|
+
* @description HMR 终端日志档位:默认仅输出总耗时,显式开启 concise/verbose 后再展示阶段诊断。
|
|
509
|
+
*/
|
|
510
|
+
logLevel?: 'default' | 'concise' | 'verbose';
|
|
511
|
+
/**
|
|
512
|
+
* @description 是否输出 HMR 结构化 profile,或指定自定义 JSONL 输出路径
|
|
513
|
+
*/
|
|
514
|
+
profileJson?: boolean | string;
|
|
507
515
|
}
|
|
508
516
|
/**
|
|
509
517
|
* @description worker 构建配置
|
|
@@ -1369,6 +1377,42 @@ interface RuntimeState {
|
|
|
1369
1377
|
independent: {
|
|
1370
1378
|
outputs: Map<string, RolldownOutput>;
|
|
1371
1379
|
};
|
|
1380
|
+
hmr: {
|
|
1381
|
+
loadedEntrySet: Set<string>;
|
|
1382
|
+
dirtyEntrySet: Set<string>;
|
|
1383
|
+
dirtyEntryReasons: Map<string, 'direct' | 'dependency'>;
|
|
1384
|
+
resolvedEntryMap: Map<string, ResolvedId>;
|
|
1385
|
+
entriesMap: Map<string, Entry | undefined>;
|
|
1386
|
+
layoutEntryDependents: Map<string, Set<string>>;
|
|
1387
|
+
entryLayoutDependencies: Map<string, Set<string>>;
|
|
1388
|
+
recentProfiles: Array<{
|
|
1389
|
+
totalMs: number;
|
|
1390
|
+
buildCoreMs?: number;
|
|
1391
|
+
transformMs?: number;
|
|
1392
|
+
writeMs?: number;
|
|
1393
|
+
watchToDirtyMs?: number;
|
|
1394
|
+
emitMs?: number;
|
|
1395
|
+
sharedChunkResolveMs?: number;
|
|
1396
|
+
dirtyCount?: number;
|
|
1397
|
+
pendingCount?: number;
|
|
1398
|
+
emittedCount?: number;
|
|
1399
|
+
}>;
|
|
1400
|
+
profile: {
|
|
1401
|
+
event?: ChangeEvent;
|
|
1402
|
+
file?: string;
|
|
1403
|
+
buildCoreMs?: number;
|
|
1404
|
+
transformMs?: number;
|
|
1405
|
+
writeMs?: number;
|
|
1406
|
+
watchToDirtyMs?: number;
|
|
1407
|
+
emitMs?: number;
|
|
1408
|
+
sharedChunkResolveMs?: number;
|
|
1409
|
+
dirtyCount?: number;
|
|
1410
|
+
pendingCount?: number;
|
|
1411
|
+
emittedCount?: number;
|
|
1412
|
+
dirtyReasonSummary?: string[];
|
|
1413
|
+
pendingReasonSummary?: string[];
|
|
1414
|
+
};
|
|
1415
|
+
};
|
|
1372
1416
|
};
|
|
1373
1417
|
json: {
|
|
1374
1418
|
cache: FileCache<any>;
|
|
@@ -1521,7 +1565,7 @@ interface AutoRoutesService {
|
|
|
1521
1565
|
getWatchFiles: () => Iterable<string>;
|
|
1522
1566
|
getWatchDirectories: () => Iterable<string>;
|
|
1523
1567
|
isRouteFile: (filePath: string) => boolean;
|
|
1524
|
-
handleFileChange: (filePath: string, event?: AutoRoutesFileEvent) => Promise<
|
|
1568
|
+
handleFileChange: (filePath: string, event?: AutoRoutesFileEvent) => Promise<boolean>;
|
|
1525
1569
|
isInitialized: () => boolean;
|
|
1526
1570
|
isEnabled: () => boolean;
|
|
1527
1571
|
}
|
package/dist/config.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { Bn as resolveWeappViteHostMeta, Fn as WeappViteHostMeta, In as WeappViteRuntime, Ln as applyWeappViteHostMeta, Pn as WEAPP_VITE_HOST_NAME, Rn as createWeappViteHostMeta, _ as definePageJson, a as UserConfigFnNoEnvPlain, c as UserConfigFnPromise, d as Component, f as Page, g as defineComponentJson, h as defineAppJson, i as UserConfigFnNoEnv, l as defineConfig, m as Theme, n as UserConfigExport, nt as WeappViteConfig, o as UserConfigFnObject, p as Sitemap, r as UserConfigFn, s as UserConfigFnObjectPlain, t as UserConfig, u as App, v as defineSitemapJson, y as defineThemeJson, zn as isWeappViteHost } from "./config-
|
|
1
|
+
import { Bn as resolveWeappViteHostMeta, Fn as WeappViteHostMeta, In as WeappViteRuntime, Ln as applyWeappViteHostMeta, Pn as WEAPP_VITE_HOST_NAME, Rn as createWeappViteHostMeta, _ as definePageJson, a as UserConfigFnNoEnvPlain, c as UserConfigFnPromise, d as Component, f as Page, g as defineComponentJson, h as defineAppJson, i as UserConfigFnNoEnv, l as defineConfig, m as Theme, n as UserConfigExport, nt as WeappViteConfig, o as UserConfigFnObject, p as Sitemap, r as UserConfigFn, s as UserConfigFnObjectPlain, t as UserConfig, u as App, v as defineSitemapJson, y as defineThemeJson, zn as isWeappViteHost } from "./config-BEJTp6sp.mjs";
|
|
2
2
|
export { App, Component, Page, Sitemap, Theme, UserConfig, UserConfigExport, UserConfigFn, UserConfigFnNoEnv, UserConfigFnNoEnvPlain, UserConfigFnObject, UserConfigFnObjectPlain, UserConfigFnPromise, WEAPP_VITE_HOST_NAME, WeappViteConfig, WeappViteHostMeta, WeappViteRuntime, applyWeappViteHostMeta, createWeappViteHostMeta, defineAppJson, defineComponentJson, defineConfig, definePageJson, defineSitemapJson, defineThemeJson, isWeappViteHost, resolveWeappViteHostMeta };
|