weapp-vite 6.20.4 → 6.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -47,7 +47,7 @@ export default defineConfig({
47
47
  })
48
48
  ```
49
49
 
50
- 未配置 `weapp.hmr.runtime` 时,`wv dev` 会在启动时读取 `project.private.config.json.setting.compileHotReLoad`:开启时使用 `stateful-experimental`,关闭或无法确认时使用 `classic`。启动日志会以 `HMR 模式` 和 `HMR 切换` 两行显示最终模式、选择来源和切换方法。显式设置 `classic` 或 `stateful-experimental` 会覆盖自动选择。修改 DevTools 设置后请重启 `wv dev`;CSS、资源、配置和不兼容更新会自动回退完整构建与当前路由重载。
50
+ 未配置 `weapp.hmr.runtime` 时,`wv dev` 会在启动时读取 `project.private.config.json.setting.compileHotReLoad`:开启时使用 `stateful-experimental`,关闭或无法确认时使用 `classic`。启动日志会以 `HMR 模式` 和 `HMR 切换` 两行显示最终模式、选择来源和切换方法。显式设置 `classic` 或 `stateful-experimental` 会覆盖自动选择,但 Skyline 例外:微信开发者工具暂不支持 Skyline 热重载,首次编译检测到任意应用或页面配置使用 `renderer: 'skyline'` 时,会显示兼容性警告、自动将项目私有配置中的 `compileHotReLoad` 设为 `false`,并强制降级到 `classic`。切回 WebView 后可按需手动重新开启热重载。修改 DevTools 设置后请重启 `wv dev`;CSS、资源、配置和不兼容更新会自动回退完整构建与当前路由重载。
51
51
 
52
52
  > 说明:CLI 同时支持完整命令 `weapp-vite` 与简写命令 `wv`,两者等价。下面的示例默认使用 `weapp-vite`,你也可以按个人习惯替换成 `wv`。
53
53
 
@@ -1,2 +1,2 @@
1
- import { a as TDesignResolver, i as UviewPlusResolver, n as WeuiResolver, r as VantResolver, t as WotUiResolver } from "../resolvers-w4g7O94W.mjs";
1
+ import { a as TDesignResolver, i as UviewPlusResolver, n as WeuiResolver, r as VantResolver, t as WotUiResolver } from "../resolvers-icNxkpcy.mjs";
2
2
  export { TDesignResolver, UviewPlusResolver, VantResolver, WeuiResolver, WotUiResolver };
@@ -1,4 +1,4 @@
1
- import { n as getCompilerContext, v as getRouteRuntimeGlobalKeys } from "./createContext-DoH-W4mj.mjs";
1
+ import { n as getCompilerContext, v as getRouteRuntimeGlobalKeys } from "./createContext-BE57_Xi7.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 { C as parseCommentJson, D as isPathInside, E as shouldPassPlatformArgToIdeOpen, S as loadViteConfigFile, T as getDefaultIdeProjectRoot, _ as resolveHmrProfileJsonPath, a as formatBytes, b as checkRuntime, d as getBackendForCapability, f as resolveBackendExecution, g as SHARED_CHUNK_VIRTUAL_PREFIX, h as createSharedBuildConfig, m as syncManagedTsconfigBootstrapFiles, p as syncProjectSupportFiles, t as createCompilerContext, w as createCjsConfigLoadError, x as getProjectConfigFileName, y as resolveWeappConfigFile } from "./createContext-DoH-W4mj.mjs";
1
+ import { A as shouldPassPlatformArgToIdeOpen, C as findPreloadRuleKey, D as parseCommentJson, E as loadViteConfigFile, O as createCjsConfigLoadError, S as collectPreloadPages, T as suggestPreloadRules, _ as resolveHmrProfileJsonPath, a as formatBytes, b as checkRuntime, d as getBackendForCapability, f as resolveBackendExecution, g as SHARED_CHUNK_VIRTUAL_PREFIX, h as createSharedBuildConfig, j as isPathInside, k as getDefaultIdeProjectRoot, m as syncManagedTsconfigBootstrapFiles, p as syncProjectSupportFiles, t as createCompilerContext, w as resolvePreloadPackageIdentifier, x as getProjectConfigFileName, y as resolveWeappConfigFile } from "./createContext-BE57_Xi7.mjs";
2
2
  import { r as logger_default, t as colors } from "./logger-mt4mSTqV.mjs";
3
- import { h as VERSION } from "./file-DnVj_L9_.mjs";
3
+ import { h as VERSION, i as findJsEntry, o as findTemplateEntry, s as findVueEntry } from "./file-Byldwig4.mjs";
4
4
  import { c as startWeappViteMcpServer, l as detectAiDevelopmentEnvironment, s as resolveWeappMcpConfig } from "./mcp-BG6TliEg.mjs";
5
5
  import { createRequire } from "node:module";
6
6
  import fs from "node:fs";
@@ -8,6 +8,7 @@ import path, { posix } from "pathe";
8
8
  import path$1 from "node:path";
9
9
  import { defu } from "@weapp-core/shared";
10
10
  import { fs as fs$1 } from "@weapp-core/shared/fs";
11
+ import { parse } from "vue/compiler-sfc";
11
12
  import process from "node:process";
12
13
  import fs$2, { mkdir, writeFile } from "node:fs/promises";
13
14
  import { build, createServer } from "vite";
@@ -15,7 +16,7 @@ import os from "node:os";
15
16
  import { execFile, spawn } from "node:child_process";
16
17
  import { Buffer } from "node:buffer";
17
18
  import { cac } from "cac";
18
- import { RETRY_CANCEL_KEYS, RETRY_CONFIRM_KEYS, bootstrapWechatDevtoolsSettings, buildWechatIdeNpm, clearWechatIdeCache, clearWechatIdeCacheByAutomator, closeSharedMiniProgram, closeWechatIdeProject, compileWechatIdeByAutomator, connectOpenedAutomator, createSharedInputSession, createWechatIdeLoginRequiredExitError, defaultCustomConfigFilePath, detectWechatDevtoolsServicePort, dispatchWechatCliCommand, formatAutomatorLoginError, getConfig, getWechatIdeTestAccounts, getWechatIdeTicket, getWechatIdeToolInfo, isAutomatorLoginError, isWeappIdeTopLevelCommand, isWechatIdeEngineBuildEndpointMissingError, isWechatIdeLoggedIn, isWechatIdeLoginRequiredError, isWechatIdeLoginRequiredExitError, launchAutomator, parse, promptRetryKeypress, promptWechatIdeLoginRetry, quitWechatIde, refreshWechatIdeTicket, resetWechatIdeFileUtilsByHttp, resolveCliPath, resolveProjectAutomatorPort, runRetryableCommand, runWechatIdeEngineBuild, runWithSuspendedSharedInput, setWechatIdeTicket, startForwardConsole, takeScreenshot } from "weapp-ide-cli";
19
+ import { RETRY_CANCEL_KEYS, RETRY_CONFIRM_KEYS, bootstrapWechatDevtoolsSettings, buildWechatIdeNpm, clearWechatIdeCache, clearWechatIdeCacheByAutomator, closeSharedMiniProgram, closeWechatIdeProject, compileWechatIdeByAutomator, connectOpenedAutomator, createSharedInputSession, createWechatIdeLoginRequiredExitError, defaultCustomConfigFilePath, detectWechatDevtoolsServicePort, dispatchWechatCliCommand, formatAutomatorLoginError, getConfig, getWechatIdeTestAccounts, getWechatIdeTicket, getWechatIdeToolInfo, isAutomatorLoginError, isWeappIdeTopLevelCommand, isWechatIdeEngineBuildEndpointMissingError, isWechatIdeLoggedIn, isWechatIdeLoginRequiredError, isWechatIdeLoginRequiredExitError, launchAutomator, parse as parse$1, promptRetryKeypress, promptWechatIdeLoginRetry, quitWechatIde, refreshWechatIdeTicket, resetWechatIdeFileUtilsByHttp, resolveCliPath, resolveProjectAutomatorPort, runRetryableCommand, runWechatIdeEngineBuild, runWithSuspendedSharedInput, setWechatIdeTicket, startForwardConsole, takeScreenshot } from "weapp-ide-cli";
19
20
  import { promisify } from "node:util";
20
21
  import { brotliCompressSync, gzipSync } from "node:zlib";
21
22
  import { resolveCommand } from "package-manager-detector/commands";
@@ -161,7 +162,7 @@ async function executeWechatIdeCliCommand(argv, options = {}) {
161
162
  createCancelError: (error) => createWechatIdeLoginRequiredExitError(error, "cancelled"),
162
163
  execute: async () => {
163
164
  try {
164
- await parse(argv);
165
+ await parse$1(argv);
165
166
  return null;
166
167
  } catch (error) {
167
168
  if (isWechatIdeLoginRequiredExitError(error)) throw error;
@@ -1069,6 +1070,177 @@ async function analyzeHmrProfile(options) {
1069
1070
  };
1070
1071
  }
1071
1072
  //#endregion
1073
+ //#region src/analyze/preload/budget.ts
1074
+ const PRELOAD_LIMIT_BYTES = 2097152;
1075
+ function createPackageSizeMap$1(result) {
1076
+ return new Map((result?.packages ?? []).map((pkg) => [pkg.id, pkg.files.reduce((total, file) => total + (file.size ?? 0), 0)]));
1077
+ }
1078
+ function getConfiguredPackages(rule, appJson) {
1079
+ if (!rule || typeof rule !== "object" || !("packages" in rule)) return [];
1080
+ const packages = rule.packages;
1081
+ if (!Array.isArray(packages)) return [];
1082
+ return packages.flatMap((item) => typeof item === "string" ? [resolvePreloadPackageIdentifier(item, appJson)] : []).filter((item) => Boolean(item));
1083
+ }
1084
+ function createPreloadBudgets(appJson, result, configuredRules, packageAnalysis) {
1085
+ const packageSizes = createPackageSizeMap$1(packageAnalysis);
1086
+ const bySourcePackage = /* @__PURE__ */ new Map();
1087
+ const ensureSourcePackage = (page) => {
1088
+ const sourcePackage = page.packageRoot ?? "__main__";
1089
+ let entry = bySourcePackage.get(sourcePackage);
1090
+ if (!entry) {
1091
+ entry = {
1092
+ sourceType: page.packageRoot ? page.independent ? "independent" : "subpackage" : "main",
1093
+ targets: /* @__PURE__ */ new Map()
1094
+ };
1095
+ bySourcePackage.set(sourcePackage, entry);
1096
+ }
1097
+ return entry;
1098
+ };
1099
+ for (const page of result.pages) {
1100
+ const configuredKey = findPreloadRuleKey(page.route, configuredRules);
1101
+ if (configuredKey === void 0) continue;
1102
+ const entry = ensureSourcePackage(page);
1103
+ for (const packageRoot of getConfiguredPackages(configuredRules[configuredKey], appJson)) {
1104
+ const target = entry.targets.get(packageRoot) ?? {
1105
+ configured: false,
1106
+ suggested: false
1107
+ };
1108
+ target.configured = true;
1109
+ entry.targets.set(packageRoot, target);
1110
+ }
1111
+ }
1112
+ const pageByRoute = new Map(result.pages.map((page) => [page.route, page]));
1113
+ for (const suggestion of result.suggestions) {
1114
+ const page = pageByRoute.get(suggestion.page);
1115
+ if (!page) continue;
1116
+ const entry = ensureSourcePackage(page);
1117
+ const target = entry.targets.get(suggestion.packageRoot) ?? {
1118
+ configured: false,
1119
+ suggested: false
1120
+ };
1121
+ target.suggested = true;
1122
+ entry.targets.set(suggestion.packageRoot, target);
1123
+ }
1124
+ return [...bySourcePackage.entries()].map(([sourcePackage, entry]) => {
1125
+ const targets = [...entry.targets.entries()].map(([packageRoot, state]) => {
1126
+ const packageId = packageRoot === "__APP__" ? "__main__" : packageRoot;
1127
+ return {
1128
+ packageRoot,
1129
+ bytes: packageSizes.get(packageId),
1130
+ ...state
1131
+ };
1132
+ }).sort((left, right) => left.packageRoot.localeCompare(right.packageRoot));
1133
+ const unknownPackages = targets.filter((target) => target.bytes === void 0).map((target) => target.packageRoot);
1134
+ const estimatedBytes = targets.reduce((total, target) => total + (target.bytes ?? 0), 0);
1135
+ const status = estimatedBytes > PRELOAD_LIMIT_BYTES ? "exceeded" : unknownPackages.length > 0 ? "unknown" : "ok";
1136
+ return {
1137
+ sourcePackage,
1138
+ sourceType: entry.sourceType,
1139
+ limitBytes: PRELOAD_LIMIT_BYTES,
1140
+ estimatedBytes,
1141
+ remainingBytes: unknownPackages.length === 0 ? Math.max(0, PRELOAD_LIMIT_BYTES - estimatedBytes) : void 0,
1142
+ status,
1143
+ targets,
1144
+ unknownPackages
1145
+ };
1146
+ }).sort((left, right) => left.sourcePackage.localeCompare(right.sourcePackage));
1147
+ }
1148
+ //#endregion
1149
+ //#region src/analyze/preload/index.ts
1150
+ async function readFileIfExists(filePath) {
1151
+ if (!filePath) return;
1152
+ try {
1153
+ return await fs$1.readFile(filePath, "utf8");
1154
+ } catch {
1155
+ return;
1156
+ }
1157
+ }
1158
+ function splitVueSource(source, filename) {
1159
+ try {
1160
+ const { descriptor } = parse(source, { filename });
1161
+ return {
1162
+ template: descriptor.template?.content,
1163
+ script: [descriptor.script?.content, descriptor.scriptSetup?.content].filter((content) => Boolean(content)).join("\n")
1164
+ };
1165
+ } catch {
1166
+ return {
1167
+ template: source,
1168
+ script: source
1169
+ };
1170
+ }
1171
+ }
1172
+ async function collectPageSources(ctx, route) {
1173
+ const base = path.resolve(ctx.configService.absoluteSrcRoot, route);
1174
+ const [templateEntry, scriptEntry, vueEntry] = await Promise.all([
1175
+ findTemplateEntry(base, ctx.configService.platform),
1176
+ findJsEntry(base),
1177
+ findVueEntry(base)
1178
+ ]);
1179
+ if (vueEntry) {
1180
+ const source = await readFileIfExists(vueEntry);
1181
+ return source ? splitVueSource(source, vueEntry) : {};
1182
+ }
1183
+ const [template, script] = await Promise.all([readFileIfExists(templateEntry.path), readFileIfExists(scriptEntry.path)]);
1184
+ return {
1185
+ template,
1186
+ script
1187
+ };
1188
+ }
1189
+ function aggregateSuggestions(result, configuredRules, appJson) {
1190
+ const byPage = /* @__PURE__ */ new Map();
1191
+ for (const suggestion of result.suggestions) {
1192
+ const current = byPage.get(suggestion.page) ?? {
1193
+ page: suggestion.page,
1194
+ packages: [],
1195
+ evidence: [],
1196
+ alreadyConfigured: []
1197
+ };
1198
+ if (!current.packages.includes(suggestion.packageRoot)) current.packages.push(suggestion.packageRoot);
1199
+ current.evidence.push({
1200
+ target: suggestion.target,
1201
+ packageRoot: suggestion.packageRoot,
1202
+ source: suggestion.source
1203
+ });
1204
+ const configuredKey = findPreloadRuleKey(suggestion.page, configuredRules);
1205
+ const existingRule = configuredKey === void 0 ? void 0 : configuredRules[configuredKey];
1206
+ const existingPackages = existingRule && typeof existingRule === "object" && "packages" in existingRule ? existingRule.packages : void 0;
1207
+ if ((Array.isArray(existingPackages) ? existingPackages.flatMap((item) => typeof item === "string" ? [resolvePreloadPackageIdentifier(item, appJson)] : []) : []).includes(suggestion.packageRoot)) current.alreadyConfigured.push(suggestion.packageRoot);
1208
+ byPage.set(suggestion.page, current);
1209
+ }
1210
+ return [...byPage.values()].map((suggestion) => ({
1211
+ ...suggestion,
1212
+ packages: suggestion.packages.sort(),
1213
+ alreadyConfigured: [...new Set(suggestion.alreadyConfigured)].sort(),
1214
+ evidence: suggestion.evidence.sort((left, right) => left.target.localeCompare(right.target))
1215
+ }));
1216
+ }
1217
+ async function analyzePreloadRules(ctx, options = {}) {
1218
+ const appJson = (await ctx.scanService.loadAppEntry()).json;
1219
+ const pages = collectPreloadPages(appJson);
1220
+ const pageSources = /* @__PURE__ */ new Map();
1221
+ const sourceEntries = await Promise.all(pages.map(async (page) => [page.route, await collectPageSources(ctx, page.route)]));
1222
+ for (const [route, source] of sourceEntries) pageSources.set(route, source);
1223
+ const configuredRules = appJson.preloadRule && typeof appJson.preloadRule === "object" ? appJson.preloadRule : {};
1224
+ const suggestions = suggestPreloadRules(appJson, pageSources);
1225
+ return {
1226
+ runtime: "mini",
1227
+ kind: "preload",
1228
+ generatedAt: (options.now ?? /* @__PURE__ */ new Date()).toISOString(),
1229
+ platform: ctx.configService.platform,
1230
+ pages: pages.map((page) => page.route),
1231
+ configuredRules,
1232
+ suggestions: aggregateSuggestions(suggestions, configuredRules, appJson),
1233
+ budgets: createPreloadBudgets(appJson, suggestions, configuredRules, options.packageAnalysis),
1234
+ uncoveredPages: suggestions.uncovered,
1235
+ limitations: [
1236
+ "仅分析静态路由字面量;动态路由、后端配置和运行时守卫不会被推断。",
1237
+ "建议使用分包 root 作为 packages 值;预算按触发页所属包聚合,未知体积目标仍需人工复核。",
1238
+ "静态跳转只能证明可达性,不能代表真实访问频率,正式启用前仍需结合业务数据确认。",
1239
+ "该命令只提供可审计建议,不会自动修改源码或覆盖手写的 app.json.preloadRule。"
1240
+ ]
1241
+ };
1242
+ }
1243
+ //#endregion
1072
1244
  //#region src/analyze/components/suggestions.ts
1073
1245
  function createComponentSuggestion(usage) {
1074
1246
  if (usage.componentPackage !== "__main__" || usage.crossPackageUsageCount === 0) return;
@@ -2469,6 +2641,23 @@ async function startAnalyzeDashboard(result, options) {
2469
2641
  await waitPromise;
2470
2642
  }
2471
2643
  //#endregion
2644
+ //#region src/cli/processCleanup.ts
2645
+ function isSassEmbeddedChild(handle) {
2646
+ if (!handle || typeof handle !== "object") return false;
2647
+ const child = handle;
2648
+ const spawnfile = typeof child.spawnfile === "string" ? child.spawnfile : "";
2649
+ const spawnargs = Array.isArray(child.spawnargs) ? child.spawnargs : [];
2650
+ return Boolean("kill" in handle && "spawnfile" in handle && (spawnfile.includes("sass-embedded") || spawnfile.includes("dart-sass") && spawnargs.includes("--embedded")));
2651
+ }
2652
+ function terminateStaleSassEmbeddedProcess() {
2653
+ const getHandles = process._getActiveHandles;
2654
+ const handles = typeof getHandles === "function" ? getHandles() : void 0;
2655
+ if (!Array.isArray(handles)) return;
2656
+ for (const handle of handles) if (isSassEmbeddedChild(handle)) try {
2657
+ handle.kill();
2658
+ } catch {}
2659
+ }
2660
+ //#endregion
2472
2661
  //#region src/cli/commands/analyze.ts
2473
2662
  function normalizeDisplayPath(value) {
2474
2663
  return value || ".";
@@ -2583,6 +2772,27 @@ function printWebAnalysisSummary(result) {
2583
2772
  logger_default.warn(`- 未支持范围:${result.unsupportedScopes.join(";")}`);
2584
2773
  for (const limitation of result.limitations) logger_default.warn(`- 限制:${limitation}`);
2585
2774
  }
2775
+ function printPreloadAnalysisSummary(result) {
2776
+ logger_default.success("preloadRule 静态分析完成");
2777
+ if (result.suggestions.length === 0) logger_default.info("未检测到可以证明的跨分包静态跳转。");
2778
+ for (const suggestion of result.suggestions) {
2779
+ const packages = suggestion.packages.join("、");
2780
+ const covered = suggestion.alreadyConfigured.length > 0 ? `,已配置:${suggestion.alreadyConfigured.join("、")}` : "";
2781
+ logger_default.info(`- ${suggestion.page} -> ${packages}${covered}`);
2782
+ for (const evidence of suggestion.evidence.slice(0, 5)) logger_default.info(` - ${evidence.source}:${evidence.target}`);
2783
+ }
2784
+ if (result.uncoveredPages.length > 0) logger_default.warn(`- 未找到可扫描源码的页面:${result.uncoveredPages.join("、")}`);
2785
+ if (result.budgets.length > 0) {
2786
+ logger_default.info("预下载额度:");
2787
+ for (const budget of result.budgets) {
2788
+ const size = `${formatAnalyzeBytes(budget.estimatedBytes)} / ${formatAnalyzeBytes(budget.limitBytes)}`;
2789
+ const unknown = budget.unknownPackages.length > 0 ? `,未知:${budget.unknownPackages.join("、")}` : "";
2790
+ const status = budget.status === "exceeded" ? "超限" : budget.status === "unknown" ? "待确认" : "正常";
2791
+ logger_default.info(`- ${budget.sourcePackage}:${size},${status}${unknown}`);
2792
+ }
2793
+ }
2794
+ for (const limitation of result.limitations) logger_default.warn(`- 限制:${limitation}`);
2795
+ }
2586
2796
  async function writeAnalyzeResult(result, outputOption, configService, format = "json", previousResult) {
2587
2797
  if (!outputOption) return;
2588
2798
  const baseDir = configService.cwd;
@@ -2703,7 +2913,7 @@ function printHmrProfileAnalysisSummary(result, configService) {
2703
2913
  }
2704
2914
  }
2705
2915
  function registerAnalyzeCommand(cli) {
2706
- cli.command("analyze [root]", "analyze 两端包体与源码映射").option("--hmr-profile [file]", `[string | boolean] 分析 HMR JSONL profile,省略值时优先读取配置,否则回退到默认路径`).option("--json", `[boolean] 输出 JSON 结果`).option("--markdown", `[boolean] 输出 Markdown 报告`).option("--report <type>", `[string] 输出指定报告类型(pr)`).option("--budget-check", `[boolean] 检查 analyze 预算,超过预算时返回非 0 退出码`).option("--output <file>", `[string] 将分析结果写入指定文件(JSON 或 Markdown)`).option("-p, --platform <platform>", `[string] target platform (weapp | web)`).option("--project-config <path>", `[string] project config path (miniprogram only)`).action(async (root, options) => {
2916
+ cli.command("analyze [root]", "analyze 两端包体与源码映射").option("--hmr-profile [file]", `[string | boolean] 分析 HMR JSONL profile,省略值时优先读取配置,否则回退到默认路径`).option("--json", `[boolean] 输出 JSON 结果`).option("--markdown", `[boolean] 输出 Markdown 报告`).option("--report <type>", `[string] 输出指定报告类型(pr)`).option("--budget-check", `[boolean] 检查 analyze 预算,超过预算时返回非 0 退出码`).option("--preload", `[boolean] 分析静态页面跳转、实际分包体积和 preloadRule 额度`).option("--output <file>", `[string] 将分析结果写入指定文件(JSON 或 Markdown)`).option("-p, --platform <platform>", `[string] target platform (weapp | web)`).option("--project-config <path>", `[string] project config path (miniprogram only)`).action(async (root, options) => {
2707
2917
  filterDuplicateOptions(options);
2708
2918
  const configFile = resolveConfigFile(options);
2709
2919
  const outputJson = coerceBooleanOption(options.json);
@@ -2714,8 +2924,9 @@ function registerAnalyzeCommand(cli) {
2714
2924
  const budgetCheck = coerceBooleanOption(options.budgetCheck);
2715
2925
  const targets = resolveRuntimeTargets(options);
2716
2926
  const inlineConfig = createInlineConfig(targets);
2927
+ let ctx;
2717
2928
  try {
2718
- const ctx = await createCompilerContext({
2929
+ ctx = await createCompilerContext({
2719
2930
  cwd: root,
2720
2931
  mode: options.mode ?? "production",
2721
2932
  configFile,
@@ -2743,6 +2954,15 @@ function registerAnalyzeCommand(cli) {
2743
2954
  } else printHmrProfileAnalysisSummary(hmrProfileResult, ctx.configService);
2744
2955
  return;
2745
2956
  }
2957
+ if (coerceBooleanOption(options.preload)) {
2958
+ if (targets.kind !== "miniprogram" || ctx.configService.platform !== "weapp") throw new Error("preloadRule 分析目前仅支持微信小程序平台。");
2959
+ const packageAnalysis = await analyzeSubpackages(ctx);
2960
+ const preloadResult = await analyzePreloadRules(ctx, { packageAnalysis });
2961
+ const writtenPath = await writeAnalyzeResult(preloadResult, outputOption, ctx.configService);
2962
+ if (outputJson && !writtenPath) process.stdout.write(`${JSON.stringify(preloadResult, null, 2)}\n`);
2963
+ if (!outputJson && !writtenPath) printPreloadAnalysisSummary(preloadResult);
2964
+ return;
2965
+ }
2746
2966
  if (getBackendForCapability(targets, "web", "analyze")) {
2747
2967
  const webResult = createWebAnalyzeResult(ctx.configService, { platform: "web" });
2748
2968
  const writtenPath = await writeAnalyzeResult(webResult, outputOption, ctx.configService);
@@ -2780,6 +3000,11 @@ function registerAnalyzeCommand(cli) {
2780
3000
  } catch (error) {
2781
3001
  logger_default.error(error);
2782
3002
  process.exitCode = 1;
3003
+ } finally {
3004
+ if (ctx) {
3005
+ for (const backend of [...targets.entries].reverse()) if (backend.descriptor.capabilities.analyze) await backend.driver?.close?.(ctx);
3006
+ }
3007
+ terminateStaleSassEmbeddedProcess();
2783
3008
  }
2784
3009
  });
2785
3010
  }
@@ -2881,17 +3106,6 @@ function setCommandNodeEnv(nodeEnv) {
2881
3106
  }
2882
3107
  //#endregion
2883
3108
  //#region src/cli/commands/build.ts
2884
- function isSassEmbeddedChild(handle) {
2885
- return Boolean(handle && typeof handle === "object" && "kill" in handle && "spawnfile" in handle && typeof handle.spawnfile === "string" && handle.spawnfile?.includes("sass-embedded"));
2886
- }
2887
- function terminateStaleSassEmbeddedProcess() {
2888
- const getHandles = process._getActiveHandles;
2889
- const handles = typeof getHandles === "function" ? getHandles() : void 0;
2890
- if (!Array.isArray(handles)) return;
2891
- for (const handle of handles) if (isSassEmbeddedChild(handle)) try {
2892
- handle.kill();
2893
- } catch {}
2894
- }
2895
3109
  function emitDashboardEvents$1(handle, events) {
2896
3110
  handle?.emitRuntimeEvents(events);
2897
3111
  }
@@ -4731,7 +4945,7 @@ function resolveRunnableHotkeyDefinition(input) {
4731
4945
  }
4732
4946
  //#endregion
4733
4947
  //#region package.json
4734
- var version = "6.20.4";
4948
+ var version = "6.21.0";
4735
4949
  //#endregion
4736
4950
  //#region src/cli/devHotkeys/format.ts
4737
4951
  const FULLWIDTH_ASCII_START = 65281;
@@ -151,29 +151,36 @@ interface SubPackage {
151
151
  */
152
152
  inlineConfig?: Partial<InlineConfig>;
153
153
  }
154
- type SubPackageStyleScope = 'all' | 'pages' | 'components';
155
- interface SubPackageStyleConfigObject {
156
- /** 样式文件路径,可以是相对分包 root、相对 `srcRoot` 或绝对路径 */
154
+ type StyleScope = 'all' | 'pages' | 'components';
155
+ interface StyleConfigObject {
156
+ /** 样式文件路径,可以是相对当前包 root、相对 `srcRoot` 或绝对路径 */
157
157
  source: string;
158
158
  /**
159
159
  * @description 作用范围快捷配置
160
160
  */
161
- scope?: SubPackageStyleScope;
162
- /** 自定义包含路径,支持传入单个 glob 或数组,默认覆盖分包内所有文件 */
161
+ scope?: StyleScope;
162
+ /** 自定义包含路径,支持传入单个 glob 或数组,默认覆盖当前包内所有文件 */
163
163
  include?: string | string[];
164
164
  /** 自定义排除路径,支持传入单个 glob 或数组 */
165
165
  exclude?: string | string[];
166
+ /** 是否自动向命中的页面或组件样式注入 `@import`,关闭后只生成独立样式文件 */
167
+ inject?: boolean;
166
168
  }
167
- type SubPackageStyleConfigEntry = string | SubPackageStyleConfigObject;
168
- interface SubPackageStyleEntry {
169
+ type StyleConfigEntry = string | StyleConfigObject;
170
+ interface StyleEntry {
169
171
  source: string;
170
172
  absolutePath: string;
171
173
  outputRelativePath: string;
172
174
  inputExtension: string;
173
- scope: SubPackageStyleScope;
175
+ scope: StyleScope;
174
176
  include: string[];
175
177
  exclude: string[];
178
+ inject?: boolean;
176
179
  }
180
+ type SubPackageStyleScope = StyleScope;
181
+ type SubPackageStyleConfigObject = StyleConfigObject;
182
+ type SubPackageStyleConfigEntry = StyleConfigEntry;
183
+ type SubPackageStyleEntry = StyleEntry;
177
184
  type GenerateExtensionsOptions = Partial<{
178
185
  js: 'js' | 'ts' | (string & {});
179
186
  json: 'js' | 'ts' | 'json' | (string & {});
@@ -342,6 +349,10 @@ interface ChunksConfig {
342
349
  sharedMode?: SharedChunkMode;
343
350
  sharedOverrides?: SharedChunkOverride[];
344
351
  sharedPathRoot?: string;
352
+ /**
353
+ * @description 按 srcRoot 相对路径保留匹配源码模块的独立输出边界
354
+ */
355
+ preserveModules?: (string | RegExp)[];
345
356
  dynamicImports?: SharedChunkDynamicImports;
346
357
  logOptimization?: boolean;
347
358
  forceDuplicatePatterns?: (string | RegExp)[];
@@ -562,7 +573,7 @@ interface WeappSubPackageConfig {
562
573
  inlineConfig?: Partial<InlineConfig>;
563
574
  autoImportComponents?: AutoImportComponentsOption;
564
575
  watchSharedStyles?: boolean;
565
- styles?: SubPackageStyleConfigEntry | SubPackageStyleConfigEntry[];
576
+ styles?: StyleConfigEntry | StyleConfigEntry[];
566
577
  }
567
578
  /**
568
579
  * @description HMR 配置
@@ -656,8 +667,17 @@ interface WeappReactConfig {
656
667
  renderMode?: 'auto' | 'dynamic' | 'static';
657
668
  devWarnings?: boolean;
658
669
  }
670
+ type WeappPreloadNetwork = 'all' | 'wifi';
671
+ /**
672
+ * @description 页面进入后的分包预下载规则。
673
+ */
674
+ interface WeappPreloadRule {
675
+ packages: string[];
676
+ network?: WeappPreloadNetwork;
677
+ }
659
678
  interface WeappRouteRule {
660
679
  appLayout?: PageLayoutMeta;
680
+ preload?: WeappPreloadRule;
661
681
  }
662
682
  type WeappRouteRules = Record<string, WeappRouteRule>;
663
683
  //#endregion
@@ -669,7 +689,7 @@ interface SubPackageMetaValue {
669
689
  entries: string[];
670
690
  subPackage: SubPackage;
671
691
  autoImportComponents?: AutoImportComponentsOption;
672
- styleEntries?: SubPackageStyleEntry[];
692
+ styleEntries?: StyleEntry[];
673
693
  watchSharedStyles?: boolean;
674
694
  }
675
695
  /**
@@ -812,6 +832,10 @@ interface WeappViteConfig {
812
832
  npm?: WeappNpmConfig;
813
833
  generate?: GenerateOptions;
814
834
  tsconfigPaths?: boolean | PluginOptions;
835
+ /**
836
+ * 主包共享样式入口。生成独立样式文件,并按配置注入主包与普通分包页面或组件。
837
+ */
838
+ styles?: StyleConfigEntry | StyleConfigEntry[];
815
839
  subPackages?: Record<string, WeappSubPackageConfig>;
816
840
  copy?: CopyOptions;
817
841
  web?: WeappWebConfig;
@@ -1817,6 +1841,7 @@ interface RuntimeState {
1817
1841
  emittedCode: Map<string, string>;
1818
1842
  };
1819
1843
  scan: {
1844
+ mainPackageStyleEntries?: StyleEntry[];
1820
1845
  subPackageMap: Map<string, SubPackageMetaValue>;
1821
1846
  independentSubPackageMap: Map<string, SubPackageMetaValue>;
1822
1847
  warnedMessages: Set<string>;
@@ -1844,6 +1869,7 @@ interface ScanService {
1844
1869
  appEntry?: AppEntry;
1845
1870
  pluginJson?: Plugin;
1846
1871
  pluginJsonPath?: string;
1872
+ readonly mainPackageStyleEntries: StyleEntry[] | undefined;
1847
1873
  subPackageMap: Map<string, SubPackageMetaValue>;
1848
1874
  independentSubPackageMap: Map<string, SubPackageMetaValue>;
1849
1875
  loadAppEntry: () => Promise<AppEntry>;
@@ -2033,4 +2059,4 @@ declare module 'vite' {
2033
2059
  */
2034
2060
  declare function defineConfig<T extends UserConfigExport>(config: T): T;
2035
2061
  //#endregion
2036
- export { WeappAnalyzeBudgetConfig as $, WeappViteRuntime as $n, GenerateTemplate as $t, Ref as A, WeappLibComponentJson as An, WeappRequestRuntimeConfig as At, BindingErrorLike as B, WeappManagedSharedTsconfigConfig as Bn, Alias as Bt, LoadConfigOptions as C, SharedChunkOverride as Cn, WeappInjectWeapiConfig as Ct, MethodDefinitions$1 as D, SubPackageStyleConfigObject as Dn, WeappNpmConfig as Dt, InlineConfig$1 as E, SubPackageStyleConfigEntry as En, WeappMcpConfig as Et, RolldownPlugin as F, WeappLibInternalDtsOptions as Fn, WeappVueConfig as Ft, EntryJsonFragment as G, applyWeappViteHostMeta as Gn, CopyGlobs as Gt, BaseEntry as H, WeappWebConfig as Hn, AlipayNpmMode as Ht, RolldownPluginOption as I, WeappLibVueTscOptions as In, WeappVueTemplateConfig as It, ScanComponentItem as J, resolveWeappViteHostMeta as Jn, GenerateDirsOptions as Jt, PageEntry as K, createWeappViteHostMeta as Kn, CopyOptions as Kt, RolldownWatchOptions as L, WeappManagedAppTsconfigConfig as Ln, WeappWebRuntimeConfig as Lt, RolldownBuild as M, WeappLibDtsOptions as Mn, WeappRouteRules as Mt, RolldownOptions as N, WeappLibEntryContext as Nn, WeappSubPackageConfig as Nt, Plugin$1 as O, SubPackageStyleEntry as On, WeappReactCompilerConfig as Ot, RolldownOutput$1 as P, WeappLibFileName as Pn, WeappUniAppConfig as Pt, UserConfig$2 as Q, WeappVitePlatform as Qn, GenerateOptions as Qt, RolldownWatcher$1 as R, WeappManagedNodeTsconfigConfig as Rn, WeappWevuConfig as Rt, CompilerContext as S, SharedChunkMode as Sn, WeappInjectRequestGlobalsTarget as St, ConfigEnv$1 as T, SubPackage as Tn, WeappInjectWebRuntimeGlobalsTarget as Tt, ComponentEntry as U, WEAPP_VITE_HOST_NAME as Un, BuildNpmPackageMeta as Ut, AppEntry as V, WeappManagedTypeScriptConfig as Vn, AliasOptions as Vt, Entry as W, WeappViteHostMeta as Wn, ChunksConfig as Wt, ProjectConfig as X, ResolvedWeappViteTarget as Xn, GenerateFileType as Xt, WxmlDep as Y, ResolveWeappViteTargetOptions as Yn, GenerateExtensionsOptions as Yt, SubPackageMetaValue as Z, WEB_PLATFORM_ALIASES as Zn, GenerateFilenamesOptions as Zt, definePageJson as _, NpmPluginPackageConfig as _n, WeappAutoRoutesIncludePattern as _t, UserConfigFnNoEnvPlain as a, GenerateTemplateScope as an, getSupportedWeappViteTargetDescriptors as ar, WeappViteConfig as at, ChangeEvent as b, ResolvedAlias as bn, WeappHmrConfig as bt, UserConfigFnPromise as c, JsonConfig as cn, EnhanceOptions as ct, Component$1 as d, JsonMergeStage as dn, MultiPlatformConfig as dt, GenerateTemplateContext as en, WeappViteTargetDescriptor as er, WeappAnalyzeConfig as et, Page$1 as f, JsonMergeStrategy as fn, ScanWxmlOptions as ft, defineComponentJson as g, NpmMainPackageConfig as gn, WeappAutoRoutesInclude as gt, defineAppJson as h, NpmDependencyPattern as hn, WeappAutoRoutesConfig as ht, UserConfigFnNoEnv as i, GenerateTemplateInlineSource as in, getSupportedWeappVitePlatforms as ir, WeappForwardConsoleLogLevel as it, ResolvedConfig as j, WeappLibConfig as jn, WeappRouteRule as jt, PluginOption as k, SubPackageStyleScope as kn, WeappReactConfig as kt, defineConfig as l, JsonMergeContext as ln, EnhanceWxmlOptions as lt, Theme$1 as m, NpmBuildOptions as mn, WeappAppPreludeMode as mt, UserConfigExport as n, GenerateTemplateFactory as nn, WeappViteTargetKind as nr, WeappDebugConfig as nt, UserConfigFnObject as o, GenerateTemplatesConfig as on, isWebPlatform as or, AutoImportComponents as ot, Sitemap$1 as p, MpPlatform$1 as pn, WeappAppPreludeConfig as pt, ComponentsMap as q, isWeappViteHost as qn, DeprecatedInlineDynamicImports as qt, UserConfigFn as r, GenerateTemplateFileSource as rn, WebPlatform as rr, WeappForwardConsoleConfig as rt, UserConfigFnObjectPlain as s, JsFormat as sn, resolveWeappViteTarget as sr, AutoImportComponentsOption as st, UserConfig$1 as t, GenerateTemplateEntry as tn, WeappViteTargetInput as tr, WeappAnalyzeHistoryConfig as tt, App$1 as u, JsonMergeFunction as un, HandleWxmlOptions as ut, defineSitemapJson as v, NpmStrategy as vn, WeappBuildScopeConfig as vt, ComputedDefinitions$1 as w, SharedChunkStrategy as wn, WeappInjectWebRuntimeGlobalsConfig as wt, WeappVitePluginApi as x, SharedChunkDynamicImports as xn, WeappInjectRequestGlobalsConfig as xt, defineThemeJson as y, NpmSubPackageConfig as yn, WeappBuildScopeObjectConfig as yt, ViteDevServer$1 as z, WeappManagedServerTsconfigConfig as zn, WeappWorkerConfig as zt };
2062
+ export { WeappAnalyzeBudgetConfig as $, isWeappViteHost as $n, GenerateFilenamesOptions as $t, Ref as A, StyleScope as An, WeappReactCompilerConfig as At, BindingErrorLike as B, WeappLibFileName as Bn, WeappWevuConfig as Bt, LoadConfigOptions as C, SharedChunkDynamicImports as Cn, WeappInjectWeapiConfig as Ct, MethodDefinitions$1 as D, StyleConfigEntry as Dn, WeappNpmConfig as Dt, InlineConfig$1 as E, SharedChunkStrategy as En, WeappMcpConfig as Et, RolldownPlugin as F, SubPackageStyleScope as Fn, WeappSubPackageConfig as Ft, EntryJsonFragment as G, WeappManagedServerTsconfigConfig as Gn, BuildNpmPackageMeta as Gt, BaseEntry as H, WeappLibVueTscOptions as Hn, Alias as Ht, RolldownPluginOption as I, WeappLibComponentJson as In, WeappUniAppConfig as It, ScanComponentItem as J, WeappWebConfig as Jn, CopyOptions as Jt, PageEntry as K, WeappManagedSharedTsconfigConfig as Kn, ChunksConfig as Kt, RolldownWatchOptions as L, WeappLibConfig as Ln, WeappVueConfig as Lt, RolldownBuild as M, SubPackageStyleConfigEntry as Mn, WeappRequestRuntimeConfig as Mt, RolldownOptions as N, SubPackageStyleConfigObject as Nn, WeappRouteRule as Nt, Plugin$1 as O, StyleConfigObject as On, WeappPreloadNetwork as Ot, RolldownOutput$1 as P, SubPackageStyleEntry as Pn, WeappRouteRules as Pt, UserConfig$2 as Q, createWeappViteHostMeta as Qn, GenerateFileType as Qt, RolldownWatcher$1 as R, WeappLibDtsOptions as Rn, WeappVueTemplateConfig as Rt, CompilerContext as S, ResolvedAlias as Sn, WeappInjectRequestGlobalsTarget as St, ConfigEnv$1 as T, SharedChunkOverride as Tn, WeappInjectWebRuntimeGlobalsTarget as Tt, ComponentEntry as U, WeappManagedAppTsconfigConfig as Un, AliasOptions as Ut, AppEntry as V, WeappLibInternalDtsOptions as Vn, WeappWorkerConfig as Vt, Entry as W, WeappManagedNodeTsconfigConfig as Wn, AlipayNpmMode as Wt, ProjectConfig as X, WeappViteHostMeta as Xn, GenerateDirsOptions as Xt, WxmlDep as Y, WEAPP_VITE_HOST_NAME as Yn, DeprecatedInlineDynamicImports as Yt, SubPackageMetaValue as Z, applyWeappViteHostMeta as Zn, GenerateExtensionsOptions as Zt, definePageJson as _, NpmDependencyPattern as _n, WeappAutoRoutesIncludePattern as _t, UserConfigFnNoEnvPlain as a, GenerateTemplateFileSource as an, WeappViteRuntime as ar, WeappViteConfig as at, ChangeEvent as b, NpmStrategy as bn, WeappHmrConfig as bt, UserConfigFnPromise as c, GenerateTemplatesConfig as cn, WeappViteTargetKind as cr, EnhanceOptions as ct, Component$1 as d, JsonMergeContext as dn, getSupportedWeappViteTargetDescriptors as dr, MultiPlatformConfig as dt, GenerateOptions as en, resolveWeappViteHostMeta as er, WeappAnalyzeConfig as et, Page$1 as f, JsonMergeFunction as fn, isWebPlatform as fr, ScanWxmlOptions as ft, defineComponentJson as g, NpmBuildOptions as gn, WeappAutoRoutesInclude as gt, defineAppJson as h, MpPlatform$1 as hn, WeappAutoRoutesConfig as ht, UserConfigFnNoEnv as i, GenerateTemplateFactory as in, WeappVitePlatform as ir, WeappForwardConsoleLogLevel as it, ResolvedConfig as j, SubPackage as jn, WeappReactConfig as jt, PluginOption as k, StyleEntry as kn, WeappPreloadRule as kt, defineConfig as l, JsFormat as ln, WebPlatform as lr, EnhanceWxmlOptions as lt, Theme$1 as m, JsonMergeStrategy as mn, WeappAppPreludeMode as mt, UserConfigExport as n, GenerateTemplateContext as nn, ResolvedWeappViteTarget as nr, WeappDebugConfig as nt, UserConfigFnObject as o, GenerateTemplateInlineSource as on, WeappViteTargetDescriptor as or, AutoImportComponents as ot, Sitemap$1 as p, JsonMergeStage as pn, resolveWeappViteTarget as pr, WeappAppPreludeConfig as pt, ComponentsMap as q, WeappManagedTypeScriptConfig as qn, CopyGlobs as qt, UserConfigFn as r, GenerateTemplateEntry as rn, WEB_PLATFORM_ALIASES as rr, WeappForwardConsoleConfig as rt, UserConfigFnObjectPlain as s, GenerateTemplateScope as sn, WeappViteTargetInput as sr, AutoImportComponentsOption as st, UserConfig$1 as t, GenerateTemplate as tn, ResolveWeappViteTargetOptions as tr, WeappAnalyzeHistoryConfig as tt, App$1 as u, JsonConfig as un, getSupportedWeappVitePlatforms as ur, HandleWxmlOptions as ut, defineSitemapJson as v, NpmMainPackageConfig as vn, WeappBuildScopeConfig as vt, ComputedDefinitions$1 as w, SharedChunkMode as wn, WeappInjectWebRuntimeGlobalsConfig as wt, WeappVitePluginApi as x, NpmSubPackageConfig as xn, WeappInjectRequestGlobalsConfig as xt, defineThemeJson as y, NpmPluginPackageConfig as yn, WeappBuildScopeObjectConfig as yt, ViteDevServer$1 as z, WeappLibEntryContext as zn, WeappWebRuntimeConfig as zt };
package/dist/config.d.mts CHANGED
@@ -1,2 +1,2 @@
1
- import { $n as WeappViteRuntime, Gn as applyWeappViteHostMeta, Jn as resolveWeappViteHostMeta, Kn as createWeappViteHostMeta, Un as WEAPP_VITE_HOST_NAME, Wn as WeappViteHostMeta, _ as definePageJson, a as UserConfigFnNoEnvPlain, at as WeappViteConfig, 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, o as UserConfigFnObject, p as Sitemap, qn as isWeappViteHost, r as UserConfigFn, s as UserConfigFnObjectPlain, t as UserConfig, u as App, v as defineSitemapJson, y as defineThemeJson } from "./config-C810aRQQ.mjs";
1
+ import { $n as isWeappViteHost, Qn as createWeappViteHostMeta, Xn as WeappViteHostMeta, Yn as WEAPP_VITE_HOST_NAME, Zn as applyWeappViteHostMeta, _ as definePageJson, a as UserConfigFnNoEnvPlain, ar as WeappViteRuntime, at as WeappViteConfig, c as UserConfigFnPromise, d as Component, er as resolveWeappViteHostMeta, f as Page, g as defineComponentJson, h as defineAppJson, i as UserConfigFnNoEnv, l as defineConfig, m as Theme, n as UserConfigExport, o as UserConfigFnObject, p as Sitemap, r as UserConfigFn, s as UserConfigFnObjectPlain, t as UserConfig, u as App, v as defineSitemapJson, y as defineThemeJson } from "./config-Pi3hdn_g.mjs";
2
2
  export { type App, type Component, type Page, type Sitemap, type Theme, UserConfig, UserConfigExport, UserConfigFn, UserConfigFnNoEnv, UserConfigFnNoEnvPlain, UserConfigFnObject, UserConfigFnObjectPlain, UserConfigFnPromise, WEAPP_VITE_HOST_NAME, type WeappViteConfig, WeappViteHostMeta, type WeappViteRuntime, applyWeappViteHostMeta, createWeappViteHostMeta, defineAppJson, defineComponentJson, defineConfig, definePageJson, defineSitemapJson, defineThemeJson, isWeappViteHost, resolveWeappViteHostMeta };