weapp-vite 6.18.3 → 6.18.5

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.
@@ -1,4 +1,4 @@
1
- import { g as getRouteRuntimeGlobalKeys, n as getCompilerContext } from "./createContext-D0jhm5Nj.mjs";
1
+ import { n as getCompilerContext, v as getRouteRuntimeGlobalKeys } from "./createContext-C3XuGjnq.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.d.mts CHANGED
@@ -1 +1 @@
1
- export { };
1
+ export {}
package/dist/cli.mjs CHANGED
@@ -1,13 +1,13 @@
1
- import { C as createCjsConfigLoadError, E as isPathInside, S as parseCommentJson, T as shouldPassPlatformArgToIdeOpen, _ as createBuildScopeConfigFromCli, a as formatBytes, b as getProjectConfigFileName, d as syncProjectSupportFiles, f as syncManagedTsconfigBootstrapFiles, h as resolveHmrProfileJsonPath, m as SHARED_CHUNK_VIRTUAL_PREFIX, p as createSharedBuildConfig, t as createCompilerContext, u as resolveWeappViteTarget, v as resolveWeappConfigFile, w as getDefaultIdeProjectRoot, x as loadViteConfigFile, y as checkRuntime } from "./createContext-D0jhm5Nj.mjs";
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-C3XuGjnq.mjs";
2
2
  import { r as logger_default, t as colors } from "./logger-mt4mSTqV.mjs";
3
- import { h as VERSION } from "./file-BFzjMcYM.mjs";
3
+ import { h as VERSION } from "./file-DjQkG6ce.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
+ import fs from "node:fs";
6
7
  import path, { posix } from "pathe";
7
8
  import path$1 from "node:path";
8
9
  import { defu } from "@weapp-core/shared";
9
- import { fs } from "@weapp-core/shared/fs";
10
- import fs$1 from "node:fs";
10
+ import { fs as fs$1 } from "@weapp-core/shared/fs";
11
11
  import process from "node:process";
12
12
  import fs$2, { mkdir, writeFile } from "node:fs/promises";
13
13
  import { build, createServer } from "vite";
@@ -41,22 +41,23 @@ function logRuntimeTarget(targets, options = {}) {
41
41
  }
42
42
  function resolveRuntimeTargets(options) {
43
43
  const rawPlatform = typeof options.platform === "string" ? options.platform : typeof options.p === "string" ? options.p : void 0;
44
- const target = resolveWeappViteTarget(rawPlatform, { warn: (message) => logger_default.warn(message) });
44
+ const execution = resolveBackendExecution(rawPlatform, { warn: (message) => logger_default.warn(message) });
45
+ const miniBackend = execution.get("miniprogram");
45
46
  return {
46
- runMini: target.runMini,
47
- runWeb: target.runWeb,
48
- platform: target.kind === "miniprogram" ? target.platform : void 0,
49
- label: target.label,
47
+ ...execution,
48
+ platform: miniBackend?.platform,
50
49
  rawPlatform
51
50
  };
52
51
  }
53
- function createInlineConfig(platform, scope) {
54
- const buildScope = createBuildScopeConfigFromCli(scope);
55
- if (!platform && !buildScope) return;
56
- return { weapp: {
57
- ...platform ? { platform } : {},
58
- ...buildScope ? { buildScope } : {}
59
- } };
52
+ function createInlineConfig(execution, options = {}) {
53
+ const configs = execution.entries.map((entry) => entry.driver.createInlineConfig({
54
+ execution,
55
+ platform: entry.platform,
56
+ scope: options.scope,
57
+ host: options.host
58
+ })).filter((config) => Boolean(config));
59
+ if (configs.length === 0) return;
60
+ return configs.slice(1).reduce((merged, config) => defu(merged, config), configs[0]);
60
61
  }
61
62
  //#endregion
62
63
  //#region src/cli/openIde/execute.ts
@@ -629,11 +630,12 @@ async function resolveIdeCommandContext(options) {
629
630
  let platform = options.platform;
630
631
  let projectPath = options.projectPath;
631
632
  if (!platform || !projectPath) try {
633
+ const targets = resolveRuntimeTargets({ platform });
632
634
  const ctx = await createCompilerContext({
633
635
  cwd,
634
636
  mode: options.mode ?? "development",
635
637
  configFile: options.configFile,
636
- inlineConfig: createInlineConfig(platform),
638
+ inlineConfig: createInlineConfig(targets),
637
639
  cliPlatform: options.cliPlatform
638
640
  });
639
641
  platform ??= ctx.configService.platform;
@@ -809,7 +811,7 @@ function isFiniteNumber$1(value) {
809
811
  * @description 聚合 HMR JSONL profile,为命令行与后续仪表盘复用。
810
812
  */
811
813
  async function analyzeHmrProfile(options) {
812
- const lines = (await fs.readFile(options.profilePath, "utf8")).split(/\r?\n/);
814
+ const lines = (await fs$1.readFile(options.profilePath, "utf8")).split(/\r?\n/);
813
815
  const samples = [];
814
816
  let skippedLineCount = 0;
815
817
  for (const line of lines) {
@@ -2016,7 +2018,7 @@ function createDashboardRuntimeEvent(input) {
2016
2018
  }
2017
2019
  function readDashboardManifest(packageJsonPath) {
2018
2020
  try {
2019
- return parseCommentJson(fs$1.readFileSync(packageJsonPath, "utf8"));
2021
+ return parseCommentJson(fs.readFileSync(packageJsonPath, "utf8"));
2020
2022
  } catch {
2021
2023
  return;
2022
2024
  }
@@ -2024,7 +2026,7 @@ function readDashboardManifest(packageJsonPath) {
2024
2026
  function resolveDashboardDistRoot(packageRoot, manifest) {
2025
2027
  const distDir = manifest?.weappViteDashboard?.distDir ?? "dist";
2026
2028
  const distRoot = path.resolve(packageRoot, distDir);
2027
- if (!fs$1.existsSync(distRoot)) return;
2029
+ if (!fs.existsSync(distRoot)) return;
2028
2030
  return { root: distRoot };
2029
2031
  }
2030
2032
  function resolveDashboardDevRoot(packageRoot, manifest) {
@@ -2033,7 +2035,7 @@ function resolveDashboardDevRoot(packageRoot, manifest) {
2033
2035
  if (!devRoot || !devConfigFile) return;
2034
2036
  const root = path.resolve(packageRoot, devRoot);
2035
2037
  const configFile = path.resolve(root, devConfigFile);
2036
- if (!fs$1.existsSync(root) || !fs$1.existsSync(configFile)) return;
2038
+ if (!fs.existsSync(root) || !fs.existsSync(configFile)) return;
2037
2039
  return {
2038
2040
  root,
2039
2041
  configFile
@@ -2128,7 +2130,7 @@ async function sendDashboardFileContent(res, roots, allowlist, kind, requestPath
2128
2130
  return;
2129
2131
  }
2130
2132
  try {
2131
- const stat = await fs$1.promises.stat(resolved.absolutePath);
2133
+ const stat = await fs.promises.stat(resolved.absolutePath);
2132
2134
  if (!stat.isFile()) {
2133
2135
  sendDashboardJson(res, 400, {
2134
2136
  error: "not_file",
@@ -2148,7 +2150,7 @@ async function sendDashboardFileContent(res, roots, allowlist, kind, requestPath
2148
2150
  path: resolved.relativePath,
2149
2151
  language: resolveDashboardFileLanguage(resolved.relativePath),
2150
2152
  size: stat.size,
2151
- content: await fs$1.promises.readFile(resolved.absolutePath, "utf8")
2153
+ content: await fs.promises.readFile(resolved.absolutePath, "utf8")
2152
2154
  });
2153
2155
  } catch (error) {
2154
2156
  const code = typeof error === "object" && error && "code" in error ? String(error.code) : "";
@@ -2522,9 +2524,9 @@ async function writeAnalyzeResult(result, outputOption, configService, format =
2522
2524
  if (!outputOption) return;
2523
2525
  const baseDir = configService.cwd;
2524
2526
  const resolvedOutputPath = path.isAbsolute(outputOption) ? outputOption : path.resolve(baseDir, outputOption);
2525
- await fs.ensureDir(path.dirname(resolvedOutputPath));
2527
+ await fs$1.ensureDir(path.dirname(resolvedOutputPath));
2526
2528
  const content = format === "markdown" && "packages" in result ? createAnalyzeMarkdownReport(result, previousResult) : format === "pr" && "packages" in result ? createAnalyzePrMarkdownReport(result, previousResult) : JSON.stringify(result, null, 2);
2527
- await fs.writeFile(resolvedOutputPath, `${content}\n`, "utf8");
2529
+ await fs$1.writeFile(resolvedOutputPath, `${content}\n`, "utf8");
2528
2530
  const relativeOutput = configService.relativeCwd(resolvedOutputPath);
2529
2531
  logger_default.success(`分析结果已写入 ${colors.green(relativeOutput)}`);
2530
2532
  return resolvedOutputPath;
@@ -2648,7 +2650,7 @@ function registerAnalyzeCommand(cli) {
2648
2650
  if (reportType && !outputPrReport) throw new Error(`不支持的 analyze report 类型:${reportType}`);
2649
2651
  const budgetCheck = coerceBooleanOption(options.budgetCheck);
2650
2652
  const targets = resolveRuntimeTargets(options);
2651
- const inlineConfig = createInlineConfig(targets.platform);
2653
+ const inlineConfig = createInlineConfig(targets);
2652
2654
  try {
2653
2655
  const ctx = await createCompilerContext({
2654
2656
  cwd: root,
@@ -2678,7 +2680,7 @@ function registerAnalyzeCommand(cli) {
2678
2680
  } else printHmrProfileAnalysisSummary(hmrProfileResult, ctx.configService);
2679
2681
  return;
2680
2682
  }
2681
- if (targets.runWeb) {
2683
+ if (getBackendForCapability(targets, "web", "analyze")) {
2682
2684
  const webResult = createWebAnalyzeResult(ctx.configService, { platform: "web" });
2683
2685
  const writtenPath = await writeAnalyzeResult(webResult, outputOption, ctx.configService);
2684
2686
  if (outputJson) {
@@ -2686,7 +2688,7 @@ function registerAnalyzeCommand(cli) {
2686
2688
  } else printWebAnalysisSummary(webResult);
2687
2689
  return;
2688
2690
  }
2689
- if (!targets.runMini) {
2691
+ if (!getBackendForCapability(targets, "miniprogram", "analyze")) {
2690
2692
  logger_default.warn("当前命令不支持该平台,请通过 --platform weapp 或 --platform web 指定目标。");
2691
2693
  return;
2692
2694
  }
@@ -2838,13 +2840,14 @@ function registerBuildCommand(cli) {
2838
2840
  cli.command("build [root]", "build for production").option("--target <target>", `[string] transpile target (default: 'modules')`).option("--outDir <dir>", `[string] output directory (default: dist)`).option("-p, --platform <platform>", `[string] target platform (weapp | web | all)`).option("--project-config <path>", `[string] project config path (miniprogram only)`).option("--sourcemap [output]", `[boolean | "inline" | "hidden"] output source maps for build (default: false)`).option("--minify [minifier]", "[boolean | \"terser\" | \"esbuild\"] enable/disable minification, or specify minifier to use (default: esbuild)").option("--emptyOutDir", `[boolean] force empty outDir when it's outside of root`).option("-w, --watch", `[boolean] rebuilds when modules have changed on disk`).option("--skipNpm", `[boolean] if skip npm build`).option("-o, --open", `[boolean] open ide`).option("--trust-project", "[boolean] auto trust Wechat DevTools project on open", { default: true }).option("--no-open-recovery", "[boolean] disable automatic Wechat DevTools close-and-reopen recovery").option("--ui", `[boolean] 启动调试 UI(当前提供分析视图)`, { default: false }).option("--analyze", `[boolean] 输出分包分析仪表盘`, { default: false }).option("--scope <scope>", `[string] 局部构建范围,例如 main,packages/order`).action(async (root, options) => {
2839
2841
  let analyzeHandle;
2840
2842
  let ctx;
2843
+ let targets;
2841
2844
  let buildCompleted = false;
2842
2845
  try {
2843
2846
  filterDuplicateOptions(options);
2844
2847
  const cwd = root ?? process.cwd();
2845
2848
  const configFile = resolveConfigFile(options);
2846
- const targets = resolveRuntimeTargets(options);
2847
- const inlineConfig = createInlineConfig(targets.platform, options.scope);
2849
+ targets = resolveRuntimeTargets(options);
2850
+ const inlineConfig = createInlineConfig(targets, { scope: options.scope });
2848
2851
  ctx = await createCompilerContext({
2849
2852
  cwd,
2850
2853
  mode: options.mode ?? "production",
@@ -2855,54 +2858,58 @@ function registerBuildCommand(cli) {
2855
2858
  emitDefaultAutoImportOutputs: false,
2856
2859
  preloadAppEntry: false
2857
2860
  });
2858
- const { buildService, configService, webService } = ctx;
2861
+ const { configService } = ctx;
2862
+ const miniBackend = getBackendForCapability(targets, "miniprogram", "build");
2863
+ const webBackend = getBackendForCapability(targets, "web", "build");
2859
2864
  logRuntimeTarget(targets, { resolvedConfigPlatform: configService.platform });
2860
- const enableAnalyze = Boolean(isUiEnabled(options) && targets.runMini);
2861
- if (targets.runMini) {
2862
- const miniBuildStartedAt = Date.now();
2863
- const output = await buildService.build(options);
2864
- const miniBuildDurationMs = Date.now() - miniBuildStartedAt;
2865
- logger_default.success(`小程序构建完成,耗时:${colors.green(formatDuration(miniBuildDurationMs))}`);
2866
- if (!Array.isArray(output) && "output" in output) logBuildPackageSizeReport({
2867
- output,
2868
- subPackageMap: ctx.scanService?.subPackageMap,
2869
- warningBytes: configService.weappViteConfig.packageSizeWarningBytes
2870
- });
2871
- if (enableAnalyze) {
2872
- const analyzeStartedAt = Date.now();
2873
- const previousAnalyzeResult = await readLatestAnalyzeHistorySnapshot(configService);
2874
- const analyzeResult = await analyzeSubpackages(ctx);
2875
- await writeAnalyzeHistorySnapshot(analyzeResult, configService);
2876
- const analyzeDurationMs = Date.now() - analyzeStartedAt;
2877
- analyzeHandle = await startAnalyzeDashboard(analyzeResult, {
2878
- watch: true,
2879
- artifactRoot: configService.outDir,
2880
- cwd: configService.cwd,
2881
- packageManagerAgent: configService.packageManager.agent,
2882
- previousResult: previousAnalyzeResult,
2883
- initialEvents: [{
2884
- kind: "build",
2885
- level: "success",
2886
- title: "mini build completed",
2887
- detail: `生产构建已完成,当前 analyze 结果包含 ${analyzeResult.packages.length} 个包。`,
2888
- durationMs: miniBuildDurationMs,
2889
- tags: ["build", "mini"]
2890
- }, {
2891
- kind: "build",
2892
- level: "success",
2893
- title: "analyze completed",
2894
- detail: `分析已完成,当前包含 ${analyzeResult.packages.length} 个包与 ${analyzeResult.modules.length} 个模块。`,
2895
- durationMs: analyzeDurationMs,
2896
- tags: ["build", "analyze"]
2897
- }]
2898
- }) ?? void 0;
2865
+ const enableAnalyze = Boolean(isUiEnabled(options) && miniBackend);
2866
+ for (const backend of targets.select("build")) {
2867
+ if (backend.descriptor.id === "miniprogram") {
2868
+ const miniBuildStartedAt = Date.now();
2869
+ const output = await backend.driver.build(ctx, options);
2870
+ const miniBuildDurationMs = Date.now() - miniBuildStartedAt;
2871
+ logger_default.success(`小程序构建完成,耗时:${colors.green(formatDuration(miniBuildDurationMs))}`);
2872
+ if (!Array.isArray(output) && "output" in output) logBuildPackageSizeReport({
2873
+ output,
2874
+ subPackageMap: ctx.scanService?.subPackageMap,
2875
+ warningBytes: configService.weappViteConfig.packageSizeWarningBytes
2876
+ });
2877
+ if (enableAnalyze) {
2878
+ const analyzeStartedAt = Date.now();
2879
+ const previousAnalyzeResult = await readLatestAnalyzeHistorySnapshot(configService);
2880
+ const analyzeResult = await analyzeSubpackages(ctx);
2881
+ await writeAnalyzeHistorySnapshot(analyzeResult, configService);
2882
+ const analyzeDurationMs = Date.now() - analyzeStartedAt;
2883
+ analyzeHandle = await startAnalyzeDashboard(analyzeResult, {
2884
+ watch: true,
2885
+ artifactRoot: configService.outDir,
2886
+ cwd: configService.cwd,
2887
+ packageManagerAgent: configService.packageManager.agent,
2888
+ previousResult: previousAnalyzeResult,
2889
+ initialEvents: [{
2890
+ kind: "build",
2891
+ level: "success",
2892
+ title: "mini build completed",
2893
+ detail: `生产构建已完成,当前 analyze 结果包含 ${analyzeResult.packages.length} 个包。`,
2894
+ durationMs: miniBuildDurationMs,
2895
+ tags: ["build", "mini"]
2896
+ }, {
2897
+ kind: "build",
2898
+ level: "success",
2899
+ title: "analyze completed",
2900
+ detail: `分析已完成,当前包含 ${analyzeResult.packages.length} 个包与 ${analyzeResult.modules.length} 个模块。`,
2901
+ durationMs: analyzeDurationMs,
2902
+ tags: ["build", "analyze"]
2903
+ }]
2904
+ }) ?? void 0;
2905
+ }
2906
+ continue;
2899
2907
  }
2900
- }
2901
- const webConfig = configService.weappWebConfig;
2902
- if (targets.runWeb && webConfig?.enabled) {
2908
+ const webConfig = configService.weappWebConfig;
2909
+ if (backend.descriptor.id !== "web" || !webConfig?.enabled) continue;
2903
2910
  const webBuildStartedAt = Date.now();
2904
2911
  try {
2905
- await webService?.build();
2912
+ await backend.driver.build(ctx, options);
2906
2913
  const webBuildDurationMs = Date.now() - webBuildStartedAt;
2907
2914
  logger_default.success(`Web 构建完成,输出目录:${colors.green(configService.relativeCwd(webConfig.outDir))},耗时:${colors.green(formatDuration(webBuildDurationMs))}`);
2908
2915
  emitDashboardEvents$1(analyzeHandle, [{
@@ -2926,8 +2933,8 @@ function registerBuildCommand(cli) {
2926
2933
  throw error;
2927
2934
  }
2928
2935
  }
2929
- if (targets.runMini) logBuildAppFinish(configService, void 0, { skipWeb: !targets.runWeb });
2930
- if (options.open && targets.runMini) {
2936
+ if (miniBackend) logBuildAppFinish(configService, void 0, { skipWeb: !webBackend });
2937
+ if (options.open && getBackendForCapability(targets, "miniprogram", "ide")) {
2931
2938
  emitDashboardEvents$1(analyzeHandle, [{
2932
2939
  kind: "command",
2933
2940
  level: "info",
@@ -2943,7 +2950,7 @@ function registerBuildCommand(cli) {
2943
2950
  if (analyzeHandle) await analyzeHandle.waitForExit();
2944
2951
  buildCompleted = true;
2945
2952
  } finally {
2946
- ctx?.watcherService?.closeAll();
2953
+ if (ctx && targets) for (const backend of [...targets.select("build")].reverse()) await backend.driver.close(ctx);
2947
2954
  terminateStaleSassEmbeddedProcess();
2948
2955
  if (buildCompleted) scheduleCompletedProductionBuildExit(options, analyzeHandle);
2949
2956
  }
@@ -2972,7 +2979,7 @@ function resolveExtension(extension) {
2972
2979
  }
2973
2980
  async function readTemplateFile(templatePath, context) {
2974
2981
  const absolutePath = path.isAbsolute(templatePath) ? templatePath : path.resolve(context.cwd, templatePath);
2975
- return fs.readFile(absolutePath, "utf8");
2982
+ return fs$1.readFile(absolutePath, "utf8");
2976
2983
  }
2977
2984
  async function loadTemplate(template, context) {
2978
2985
  if (template === void 0) return;
@@ -3036,7 +3043,7 @@ async function generate(options) {
3036
3043
  });
3037
3044
  }
3038
3045
  for (const { code, fileName } of files) if (code !== void 0) {
3039
- await fs.outputFile(path.resolve(basepath, fileName), code, "utf8");
3046
+ await fs$1.outputFile(path.resolve(basepath, fileName), code, "utf8");
3040
3047
  logger_default.success(`${composePath(outDir, fileName)} 创建成功!`);
3041
3048
  }
3042
3049
  }
@@ -3529,7 +3536,7 @@ async function readLatestHmrProfileSummary(options) {
3529
3536
  option: options.weappViteConfig?.hmr?.profileJson
3530
3537
  });
3531
3538
  if (!profilePath) return;
3532
- const content = await fs.readFile(profilePath, "utf8").catch(() => void 0);
3539
+ const content = await fs$1.readFile(profilePath, "utf8").catch(() => void 0);
3533
3540
  if (!content) return;
3534
3541
  const sample = parseLatestHmrProfileSample(content);
3535
3542
  if (!sample || !isFiniteNumber(sample.totalMs)) return;
@@ -3581,10 +3588,12 @@ async function runIdeCommand(action, root, options) {
3581
3588
  filterDuplicateOptions(options);
3582
3589
  const configFile = resolveConfigFile(options);
3583
3590
  const targets = resolveRuntimeTargets(options);
3591
+ const ideBackend = getBackendForCapability(targets, "miniprogram", "ide");
3592
+ if (!ideBackend) throw new Error("`weapp-vite ide` 当前仅支持小程序平台。");
3584
3593
  const resolved = await resolveIdeCommandContext({
3585
3594
  configFile,
3586
3595
  mode: options.mode ?? "development",
3587
- platform: targets.platform,
3596
+ platform: ideBackend.platform,
3588
3597
  projectPath: root,
3589
3598
  cliPlatform: targets.rawPlatform
3590
3599
  });
@@ -3824,14 +3833,14 @@ async function probeHttpEndpoint(url) {
3824
3833
  }
3825
3834
  }
3826
3835
  async function inspectJsonConfig(target) {
3827
- if (!await fs.pathExists(target.configPath)) return {
3836
+ if (!await fs$1.pathExists(target.configPath)) return {
3828
3837
  configExists: false,
3829
3838
  configPath: target.configPath,
3830
3839
  displayName: target.displayName,
3831
3840
  issues: [`未找到配置文件:${target.configPath}`],
3832
3841
  serverName: target.serverName
3833
3842
  };
3834
- const entry = parseJsonConfig(await fs.readFile(target.configPath, "utf8"), target.configPath).mcpServers?.[target.serverName];
3843
+ const entry = parseJsonConfig(await fs$1.readFile(target.configPath, "utf8"), target.configPath).mcpServers?.[target.serverName];
3835
3844
  if (!entry) return {
3836
3845
  configExists: true,
3837
3846
  configPath: target.configPath,
@@ -3844,7 +3853,7 @@ async function inspectJsonConfig(target) {
3844
3853
  let httpReachable;
3845
3854
  if (transport === "command") {
3846
3855
  const normalizedBin = (entry.args?.[0])?.replaceAll(WORKSPACE_FOLDER_TOKEN, resolveTargetWorkspaceRoot(target));
3847
- if (!normalizedBin || !await fs.pathExists(normalizedBin)) issues.push(`未找到本地 CLI 入口:${normalizedBin ?? "缺少 args[0]"}`);
3856
+ if (!normalizedBin || !await fs$1.pathExists(normalizedBin)) issues.push(`未找到本地 CLI 入口:${normalizedBin ?? "缺少 args[0]"}`);
3848
3857
  } else if (entry.url) {
3849
3858
  httpReachable = await probeHttpEndpoint(entry.url);
3850
3859
  if (!httpReachable) issues.push(`HTTP MCP 地址不可达:${entry.url}`);
@@ -3860,14 +3869,14 @@ async function inspectJsonConfig(target) {
3860
3869
  };
3861
3870
  }
3862
3871
  async function inspectCodexConfig(target) {
3863
- if (!await fs.pathExists(target.configPath)) return {
3872
+ if (!await fs$1.pathExists(target.configPath)) return {
3864
3873
  configExists: false,
3865
3874
  configPath: target.configPath,
3866
3875
  displayName: target.displayName,
3867
3876
  issues: [`未找到配置文件:${target.configPath}`],
3868
3877
  serverName: target.serverName
3869
3878
  };
3870
- const blockMatch = (await fs.readFile(target.configPath, "utf8")).match(resolveCodexBlockPattern(target.serverName));
3879
+ const blockMatch = (await fs$1.readFile(target.configPath, "utf8")).match(resolveCodexBlockPattern(target.serverName));
3871
3880
  if (!blockMatch?.[0]) return {
3872
3881
  configExists: true,
3873
3882
  configPath: target.configPath,
@@ -3895,7 +3904,7 @@ async function inspectCodexConfig(target) {
3895
3904
  }
3896
3905
  const binPath = (argsMatch?.[1]?.match(REG_FirstTomlString))?.[1];
3897
3906
  if (!commandMatch?.[1]) issues.push("Codex 配置区块缺少 command 字段");
3898
- if (!binPath || !await fs.pathExists(binPath)) issues.push(`未找到本地 CLI 入口:${binPath ?? "缺少 args[0]"}`);
3907
+ if (!binPath || !await fs$1.pathExists(binPath)) issues.push(`未找到本地 CLI 入口:${binPath ?? "缺少 args[0]"}`);
3899
3908
  return {
3900
3909
  configExists: true,
3901
3910
  configPath: target.configPath,
@@ -3940,11 +3949,11 @@ function formatMcpQuickStart(options) {
3940
3949
  //#endregion
3941
3950
  //#region src/cli/mcpClient/index.ts
3942
3951
  async function writeMcpClientConfig(plan) {
3943
- await fs.ensureDir(path.dirname(plan.target.configPath));
3944
- const existing = await fs.readFile(plan.target.configPath, "utf8").catch(() => "");
3952
+ await fs$1.ensureDir(path.dirname(plan.target.configPath));
3953
+ const existing = await fs$1.readFile(plan.target.configPath, "utf8").catch(() => "");
3945
3954
  if (plan.target.client === "codex") {
3946
3955
  const nextContent = upsertCodexManagedBlock(existing, plan.target.serverName, plan.preview);
3947
- await fs.writeFile(plan.target.configPath, nextContent, "utf8");
3956
+ await fs$1.writeFile(plan.target.configPath, nextContent, "utf8");
3948
3957
  return;
3949
3958
  }
3950
3959
  const parsed = parseJsonConfig(existing, plan.target.configPath);
@@ -3955,7 +3964,7 @@ async function writeMcpClientConfig(plan) {
3955
3964
  [plan.target.serverName]: plan.entry
3956
3965
  }
3957
3966
  };
3958
- await fs.writeFile(plan.target.configPath, `${JSON.stringify(nextConfig, null, 2)}\n`, "utf8");
3967
+ await fs$1.writeFile(plan.target.configPath, `${JSON.stringify(nextConfig, null, 2)}\n`, "utf8");
3959
3968
  }
3960
3969
  //#endregion
3961
3970
  //#region src/cli/commands/mcp.ts
@@ -4200,10 +4209,12 @@ function registerOpenCommand(cli) {
4200
4209
  filterDuplicateOptions(options);
4201
4210
  const configFile = resolveConfigFile(options);
4202
4211
  const targets = resolveRuntimeTargets(options);
4212
+ const ideBackend = getBackendForCapability(targets, "miniprogram", "ide");
4213
+ if (!ideBackend) throw new Error("`weapp-vite open` 当前仅支持小程序平台。");
4203
4214
  const { cwd, platform, projectPath, mpDistRoot, weappViteConfig } = await resolveIdeCommandContext({
4204
4215
  configFile,
4205
4216
  mode: options.mode ?? "development",
4206
- platform: targets.platform,
4217
+ platform: ideBackend.platform,
4207
4218
  projectPath: root,
4208
4219
  cliPlatform: targets.rawPlatform
4209
4220
  });
@@ -4496,7 +4507,7 @@ function resolveRunnableHotkeyDefinition(input) {
4496
4507
  }
4497
4508
  //#endregion
4498
4509
  //#region package.json
4499
- var version = "6.18.3";
4510
+ var version = "6.18.5";
4500
4511
  //#endregion
4501
4512
  //#region src/cli/devHotkeys/format.ts
4502
4513
  const FULLWIDTH_ASCII_START = 65281;
@@ -4971,7 +4982,7 @@ function createAnalyzeController(options) {
4971
4982
  mode: configService.mode,
4972
4983
  isDev: false,
4973
4984
  configFile,
4974
- inlineConfig: createInlineConfig(targets.platform),
4985
+ inlineConfig: createInlineConfig(targets),
4975
4986
  cliPlatform: targets.rawPlatform,
4976
4987
  projectConfigPath: cliOptions.projectConfig,
4977
4988
  syncSupportFiles: false
@@ -5165,36 +5176,12 @@ function registerServeCommand(cli) {
5165
5176
  const cwd = root ?? process.cwd();
5166
5177
  const configFile = resolveConfigFile(options);
5167
5178
  const targets = resolveRuntimeTargets(options);
5168
- let inlineConfig = createInlineConfig(targets.platform, options.scope);
5169
- if (targets.runWeb) {
5170
- const host = resolveWebHost(options.host);
5171
- if (host !== void 0) inlineConfig = {
5172
- ...inlineConfig,
5173
- server: {
5174
- ...inlineConfig?.server ?? {},
5175
- host
5176
- }
5177
- };
5178
- if (targets.runMini) {
5179
- const existingServer = inlineConfig?.server ?? {};
5180
- inlineConfig = {
5181
- ...inlineConfig,
5182
- build: {
5183
- ...inlineConfig?.build ?? {},
5184
- watch: typeof inlineConfig?.build?.watch === "object" && inlineConfig.build.watch ? { ...inlineConfig.build.watch } : {}
5185
- },
5186
- server: {
5187
- ...existingServer,
5188
- ...existingServer.port === void 0 ? { port: 0 } : {},
5189
- watch: {
5190
- ...existingServer.watch ?? {},
5191
- usePolling: true,
5192
- interval: 100
5193
- }
5194
- }
5195
- };
5196
- }
5197
- }
5179
+ const webBackend = getBackendForCapability(targets, "web", "dev");
5180
+ const host = webBackend ? resolveWebHost(options.host) : void 0;
5181
+ const inlineConfig = createInlineConfig(targets, {
5182
+ scope: options.scope,
5183
+ host
5184
+ });
5198
5185
  const ctx = await createCompilerContext({
5199
5186
  cwd,
5200
5187
  mode: options.mode ?? "development",
@@ -5206,15 +5193,16 @@ function registerServeCommand(cli) {
5206
5193
  syncAutoImportSupportFiles: false,
5207
5194
  projectConfigPath: options.projectConfig
5208
5195
  });
5209
- const { buildService, configService, webService } = ctx;
5196
+ const { configService } = ctx;
5197
+ const miniBackend = getBackendForCapability(targets, "miniprogram", "dev");
5210
5198
  const aiEnvironment = await detectAiDevelopmentEnvironment();
5211
5199
  const mcpConfig = applyMcpCliOptions(configService.weappViteConfig?.mcp, options);
5212
5200
  logRuntimeTarget(targets, { resolvedConfigPlatform: configService.platform });
5213
- const enableAnalyze = Boolean(isUiEnabled(options) && targets.runMini);
5201
+ const enableAnalyze = Boolean(isUiEnabled(options) && miniBackend);
5214
5202
  let analyzeHandle;
5215
5203
  const miniProgramDevActions = createServeMiniProgramDevActions({
5216
5204
  build: async () => {
5217
- await buildService.build(options);
5205
+ await miniBackend?.driver.dev(ctx, options);
5218
5206
  },
5219
5207
  fallbackProjectPath: configService.cwd,
5220
5208
  openIde: async (projectPath, openOptions) => {
@@ -5243,7 +5231,7 @@ function registerServeCommand(cli) {
5243
5231
  });
5244
5232
  }
5245
5233
  });
5246
- const devHotkeysSession = targets.runMini ? startDevHotkeys({
5234
+ const devHotkeysSession = miniBackend ? startDevHotkeys({
5247
5235
  cwd: configService.cwd,
5248
5236
  agentName: aiEnvironment.agentName,
5249
5237
  isAgent: aiEnvironment.isAgent,
@@ -5265,38 +5253,40 @@ function registerServeCommand(cli) {
5265
5253
  options,
5266
5254
  targets
5267
5255
  });
5268
- if (targets.runMini) {
5269
- const miniBuildStartedAt = Date.now();
5270
- const buildResult = await buildService.build(options);
5271
- const miniBuildDurationMs = Date.now() - miniBuildStartedAt;
5272
- logger_default.success(`小程序初次构建完成,耗时:${formatDuration(miniBuildDurationMs)}`);
5273
- ctx.autoImportService?.syncSupportFileResolverComponents().catch((error) => {
5274
- const message = error instanceof Error ? error.message : String(error);
5275
- logger_default.warn(`[prepare] 后台同步 .weapp-vite 支持文件失败:${message}`);
5276
- });
5277
- if (enableAnalyze) {
5278
- await analyzeController.startDashboard(startAnalyzeDashboard);
5279
- analyzeHandle = analyzeController.getHandle();
5280
- analyzeController.emitRuntimeEvents([{
5281
- kind: "build",
5282
- level: "success",
5283
- title: "mini initial build completed",
5284
- detail: "小程序开发态初次构建已完成,dashboard 可继续监听后续刷新。",
5285
- durationMs: miniBuildDurationMs,
5286
- tags: [
5287
- "dev",
5288
- "mini",
5289
- "initial"
5290
- ]
5291
- }]);
5292
- await analyzeController.bindWatcher(buildResult).runInitialUpdate();
5293
- }
5294
- }
5295
5256
  let webServer;
5296
- if (targets.runWeb) {
5257
+ for (const backend of targets.select("dev")) {
5258
+ if (backend.descriptor.id === "miniprogram") {
5259
+ const miniBuildStartedAt = Date.now();
5260
+ const buildResult = await backend.driver.dev(ctx, options);
5261
+ const miniBuildDurationMs = Date.now() - miniBuildStartedAt;
5262
+ logger_default.success(`小程序初次构建完成,耗时:${formatDuration(miniBuildDurationMs)}`);
5263
+ ctx.autoImportService?.syncSupportFileResolverComponents().catch((error) => {
5264
+ const message = error instanceof Error ? error.message : String(error);
5265
+ logger_default.warn(`[prepare] 后台同步 .weapp-vite 支持文件失败:${message}`);
5266
+ });
5267
+ if (enableAnalyze) {
5268
+ await analyzeController.startDashboard(startAnalyzeDashboard);
5269
+ analyzeHandle = analyzeController.getHandle();
5270
+ analyzeController.emitRuntimeEvents([{
5271
+ kind: "build",
5272
+ level: "success",
5273
+ title: "mini initial build completed",
5274
+ detail: "小程序开发态初次构建已完成,dashboard 可继续监听后续刷新。",
5275
+ durationMs: miniBuildDurationMs,
5276
+ tags: [
5277
+ "dev",
5278
+ "mini",
5279
+ "initial"
5280
+ ]
5281
+ }]);
5282
+ await analyzeController.bindWatcher(buildResult).runInitialUpdate();
5283
+ }
5284
+ continue;
5285
+ }
5286
+ if (backend.descriptor.id !== "web") continue;
5297
5287
  const webServerStartedAt = Date.now();
5298
5288
  try {
5299
- webServer = await webService?.startDevServer();
5289
+ webServer = await backend.driver.dev(ctx, options);
5300
5290
  logger_default.success(`Web 开发服务启动完成,耗时:${formatDuration(Date.now() - webServerStartedAt)}`);
5301
5291
  analyzeController.emitRuntimeEvents([{
5302
5292
  kind: "system",
@@ -5319,14 +5309,14 @@ function registerServeCommand(cli) {
5319
5309
  throw error;
5320
5310
  }
5321
5311
  }
5322
- if (targets.runMini) {
5312
+ if (miniBackend) {
5323
5313
  logBuildAppFinish(configService, webServer, {
5324
- skipWeb: !targets.runWeb,
5314
+ skipWeb: !webBackend,
5325
5315
  uiUrls: analyzeHandle?.urls
5326
5316
  });
5327
5317
  devHotkeysSession?.restore();
5328
- } else if (targets.runWeb) logBuildAppFinish(configService, webServer, { skipMini: true });
5329
- if (options.open && targets.runMini) {
5318
+ } else if (webBackend) logBuildAppFinish(configService, webServer, { skipMini: true });
5319
+ if (options.open && getBackendForCapability(targets, "miniprogram", "ide")) {
5330
5320
  analyzeController.emitRuntimeEvents([{
5331
5321
  kind: "command",
5332
5322
  level: "info",
@@ -5345,10 +5335,10 @@ function registerServeCommand(cli) {
5345
5335
  }
5346
5336
  }
5347
5337
  if (analyzeHandle) await analyzeController.waitForExit();
5348
- else if (targets.runMini || targets.runWeb) await waitForServeShutdownSignal();
5338
+ else if (targets.has("dev")) await waitForServeShutdownSignal();
5349
5339
  } finally {
5350
5340
  devHotkeysSession?.close();
5351
- ctx.watcherService?.closeAll();
5341
+ for (const backend of [...targets.select("dev")].reverse()) await backend.driver.close(ctx);
5352
5342
  }
5353
5343
  });
5354
5344
  }