weapp-vite 7.1.4 → 7.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,10 +1,10 @@
1
1
  import { n as applyWeappViteHostMeta } from "./pluginHost--CaeyWpA.mjs";
2
- import { E as MINI_PROGRAM_PLATFORM_ADAPTERS, _ as templateExtensions, a as findJsonEntry, b as isNativeTemplateSource, c as isJsOrTs, d as touch, g as supportedCssLangs, h as scriptExtensions, i as findJsEntry, l as isTemplate, m as jsExtensions, n as changeFileExtension, o as findTemplateEntry, p as configExtensions, r as findCssEntry, s as findVueEntry, t as extractConfigFromVue, v as vueExtensions, w as inlineAutoRoutesImports, x as isSourceStyleExtension, y as ALL_NATIVE_STYLE_RESOLVER_EXTENSIONS } from "./file-CHisoC18.mjs";
2
+ import { E as MINI_PROGRAM_PLATFORM_ADAPTERS, _ as templateExtensions, a as findJsonEntry, b as isNativeTemplateSource, c as isJsOrTs, d as touch, g as supportedCssLangs, h as scriptExtensions, i as findJsEntry, l as isTemplate, m as jsExtensions, n as changeFileExtension, o as findTemplateEntry, p as configExtensions, r as findCssEntry, s as findVueEntry, t as extractConfigFromVue, v as vueExtensions, w as inlineAutoRoutesImports, x as isSourceStyleExtension, y as ALL_NATIVE_STYLE_RESOLVER_EXTENSIONS } from "./file-CfgcKGLR.mjs";
3
3
  import { n as configureLogger, r as logger_default } from "./logger-mt4mSTqV.mjs";
4
4
  import { createRequire, isBuiltin } from "node:module";
5
5
  import { createDebug } from "obug";
6
6
  import fs, { existsSync, readFileSync, realpathSync, statSync } from "node:fs";
7
- import { APP_PRELUDE_CHUNK_MARKER, APP_PRELUDE_GUARD_KEY, APP_PRELUDE_REQUIRE_MARKER, REQUEST_GLOBAL_ACTUALS_KEY, REQUEST_GLOBAL_BUNDLE_HOST_REF, REQUEST_GLOBAL_BUNDLE_MARKER, REQUEST_GLOBAL_BUNDLE_MARKER as REQUEST_GLOBAL_BUNDLE_MARKER$1, REQUEST_GLOBAL_CHUNK_HOST_REF, REQUEST_GLOBAL_CHUNK_MODULE_REF, REQUEST_GLOBAL_EXPOSE_HELPER, REQUEST_GLOBAL_INSTALLER_HOST_REF, REQUEST_GLOBAL_LAZY_CONSTRUCTOR_HELPER, REQUEST_GLOBAL_LAZY_FUNCTION_HELPER, REQUEST_GLOBAL_LOCAL_BINDINGS_MARKER, REQUEST_GLOBAL_LOCAL_BINDINGS_MARKER as REQUEST_GLOBAL_LOCAL_BINDINGS_MARKER$1, REQUEST_GLOBAL_MARK_PLACEHOLDER_HELPER, REQUEST_GLOBAL_PASSIVE_BINDINGS_MARKER, REQUEST_GLOBAL_PASSIVE_BINDINGS_MARKER as REQUEST_GLOBAL_PASSIVE_BINDINGS_MARKER$1, REQUEST_GLOBAL_PLACEHOLDER_KEY, REQUEST_GLOBAL_PRELUDE_GUARD_KEY, REQUEST_GLOBAL_PRELUDE_MARKER, REQUEST_GLOBAL_SYNTHETIC_EXPORT_NAME, REQUEST_GLOBAL_USABLE_CONSTRUCTOR_HELPER, WEAPP_I18N_JS_FILE, WEAPP_I18N_LOCALE_DATA_KEY, WEAPP_I18N_PUBLIC_MODULE_ID, WEAPP_I18N_RUNTIME_MARKER, WEAPP_I18N_VIRTUAL_MODULE_ID, WEAPP_I18N_WXS_FILE, WEAPP_REACT_EVENT_METHOD_NAME, WEAPP_VITE_EXTERNAL_OUTPUT_DIRECTORY, WEAPP_VITE_IMPORT_META_ENV_KEY, WEAPP_VITE_INJECTED_API_IDENTIFIER, WEAPP_VITE_LOGICAL_ENTRY_RESOLVED_PREFIX, WEAPP_VITE_LOGICAL_ENTRY_VIRTUAL_PREFIX, WEAPP_VITE_RUNTIME_CONTRACT_VERSION, WEAPP_VITE_RUNTIME_REACTIVITY_VIRTUAL_ID, WEAPP_VITE_RUNTIME_TEMPLATE_VIRTUAL_ID, WEAPP_VITE_RUNTIME_VIRTUAL_ID, WEAPP_VITE_RUNTIME_VIRTUAL_IDS, WEAPP_VITE_SIDECAR_OWNER_QUERY_MARKER, WEAPP_VITE_SIDECAR_QUERY_MARKER, WEAPP_VITE_SIDECAR_RESOLVED_PREFIX, WEAPP_VITE_SIDECAR_VIRTUAL_PREFIX, WEAPP_VITE_STATEFUL_HMR_BRIDGE_KEY, WEAPP_VITE_STATEFUL_HMR_CLIENT_KEY, WEAPP_VITE_STATEFUL_HMR_CONTROL_FILE, WEAPP_VITE_STATEFUL_HMR_CONTROL_KEY, WEAPP_VITE_STATEFUL_HMR_GLOBAL_STYLE_BASENAME, WEAPP_VITE_STATEFUL_HMR_PRELOAD_FILE, WEAPP_VITE_STATEFUL_HMR_UPDATE_FILE, WEVU_APP_SHELL_COMPONENT_BASE, WEVU_APP_SHELL_TAG_NAME, WEVU_INTERNAL_KEY_IDENTIFIER, WEVU_LAYOUT_BIND_PREFIX, WEVU_PAGE_LAYOUT_CURRENT_NAME_IDENTIFIER, WEVU_PAGE_LAYOUT_CURRENT_PROPS_IDENTIFIER, WEVU_PAGE_LAYOUT_NAME_KEY, WEVU_PAGE_LAYOUT_NEXT_NAME_IDENTIFIER, WEVU_PAGE_LAYOUT_NEXT_PROPS_IDENTIFIER, WEVU_PAGE_LAYOUT_NONE, WEVU_PAGE_LAYOUT_PROPS_KEY, WEVU_PAGE_LAYOUT_SETTER_KEY, WEVU_SLOT_FALLBACK_VIRTUAL_HOST_BASE, WEVU_SLOT_FALLBACK_VIRTUAL_HOST_GLOBAL_PATH, WEVU_SLOT_FALLBACK_VIRTUAL_HOST_TAG_NAME, WEVU_SLOT_NAMES_PROP, WEVU_SLOT_OWNER_ID_ATTR, WEVU_SLOT_OWNER_ID_KEY, WEVU_SLOT_OWNER_ID_PROP, WEVU_SLOT_PROPS_ATTR, WEVU_SLOT_SCOPE_ATTR, WEVU_SLOT_SCOPE_KEY } from "@weapp-core/constants";
7
+ import { APP_PRELUDE_CHUNK_MARKER, APP_PRELUDE_GUARD_KEY, APP_PRELUDE_REQUIRE_MARKER, REQUEST_GLOBAL_ACTUALS_KEY, REQUEST_GLOBAL_BUNDLE_HOST_REF, REQUEST_GLOBAL_BUNDLE_MARKER, REQUEST_GLOBAL_BUNDLE_MARKER as REQUEST_GLOBAL_BUNDLE_MARKER$1, REQUEST_GLOBAL_CHUNK_HOST_REF, REQUEST_GLOBAL_CHUNK_MODULE_REF, REQUEST_GLOBAL_EXPOSE_HELPER, REQUEST_GLOBAL_INSTALLER_HOST_REF, REQUEST_GLOBAL_LAZY_CONSTRUCTOR_HELPER, REQUEST_GLOBAL_LAZY_FUNCTION_HELPER, REQUEST_GLOBAL_LOCAL_BINDINGS_MARKER, REQUEST_GLOBAL_LOCAL_BINDINGS_MARKER as REQUEST_GLOBAL_LOCAL_BINDINGS_MARKER$1, REQUEST_GLOBAL_MARK_PLACEHOLDER_HELPER, REQUEST_GLOBAL_PASSIVE_BINDINGS_MARKER, REQUEST_GLOBAL_PASSIVE_BINDINGS_MARKER as REQUEST_GLOBAL_PASSIVE_BINDINGS_MARKER$1, REQUEST_GLOBAL_PLACEHOLDER_KEY, REQUEST_GLOBAL_PRELUDE_GUARD_KEY, REQUEST_GLOBAL_PRELUDE_MARKER, REQUEST_GLOBAL_SYNTHETIC_EXPORT_NAME, REQUEST_GLOBAL_USABLE_CONSTRUCTOR_HELPER, WEAPP_I18N_JS_FILE, WEAPP_I18N_LOCALE_DATA_KEY, WEAPP_I18N_PUBLIC_MODULE_ID, WEAPP_I18N_RUNTIME_MARKER, WEAPP_I18N_VIRTUAL_MODULE_ID, WEAPP_I18N_WXS_FILE, WEAPP_REACT_EVENT_METHOD_NAME, WEAPP_VITE_EXTERNAL_OUTPUT_DIRECTORY, WEAPP_VITE_IMPORT_META_ENV_KEY, WEAPP_VITE_INJECTED_API_IDENTIFIER, WEAPP_VITE_LOGICAL_ENTRY_RESOLVED_PREFIX, WEAPP_VITE_LOGICAL_ENTRY_VIRTUAL_PREFIX, WEAPP_VITE_RUNTIME_CONTRACT_VERSION, WEAPP_VITE_RUNTIME_REACTIVITY_VIRTUAL_ID, WEAPP_VITE_RUNTIME_TEMPLATE_VIRTUAL_ID, WEAPP_VITE_RUNTIME_VIRTUAL_ID, WEAPP_VITE_RUNTIME_VIRTUAL_IDS, WEAPP_VITE_SIDECAR_OWNER_QUERY_MARKER, WEAPP_VITE_SIDECAR_QUERY_MARKER, WEAPP_VITE_SIDECAR_RESOLVED_PREFIX, WEAPP_VITE_SIDECAR_VIRTUAL_PREFIX, WEAPP_VITE_STATEFUL_HMR_BRIDGE_KEY, WEAPP_VITE_STATEFUL_HMR_CLIENT_KEY, WEAPP_VITE_STATEFUL_HMR_CONTROL_FILE, WEAPP_VITE_STATEFUL_HMR_CONTROL_KEY, WEAPP_VITE_STATEFUL_HMR_GLOBAL_STYLE_BASENAME, WEAPP_VITE_STATEFUL_HMR_PRELOAD_FILE, WEAPP_VITE_STATEFUL_HMR_UPDATE_FILE, WEVU_APP_SHELL_COMPONENT_BASE, WEVU_APP_SHELL_TAG_NAME, WEVU_AUTO_ROUTES_MODULE_ID, WEVU_AUTO_ROUTES_MODULE_ID as WEVU_AUTO_ROUTES_MODULE_ID$1, WEVU_AUTO_ROUTES_RESOLVED_MODULE_ID, WEVU_AUTO_ROUTES_RESOLVED_MODULE_ID as WEVU_AUTO_ROUTES_RESOLVED_MODULE_ID$1, WEVU_AUTO_ROUTES_VIRTUAL_MODULE_ID, WEVU_AUTO_ROUTES_VIRTUAL_MODULE_ID as WEVU_AUTO_ROUTES_VIRTUAL_MODULE_ID$1, WEVU_DEFINE_PAGE_META_MACRO, WEVU_INTERNAL_KEY_IDENTIFIER, WEVU_LAYOUT_BIND_PREFIX, WEVU_PAGE_LAYOUT_CURRENT_NAME_IDENTIFIER, WEVU_PAGE_LAYOUT_CURRENT_PROPS_IDENTIFIER, WEVU_PAGE_LAYOUT_NAME_KEY, WEVU_PAGE_LAYOUT_NEXT_NAME_IDENTIFIER, WEVU_PAGE_LAYOUT_NEXT_PROPS_IDENTIFIER, WEVU_PAGE_LAYOUT_NONE, WEVU_PAGE_LAYOUT_PROPS_KEY, WEVU_PAGE_LAYOUT_SETTER_KEY, WEVU_ROUTER_MODULE_ID, WEVU_SLOT_FALLBACK_VIRTUAL_HOST_BASE, WEVU_SLOT_FALLBACK_VIRTUAL_HOST_GLOBAL_PATH, WEVU_SLOT_FALLBACK_VIRTUAL_HOST_TAG_NAME, WEVU_SLOT_NAMES_PROP, WEVU_SLOT_OWNER_ID_ATTR, WEVU_SLOT_OWNER_ID_KEY, WEVU_SLOT_OWNER_ID_PROP, WEVU_SLOT_PROPS_ATTR, WEVU_SLOT_SCOPE_ATTR, WEVU_SLOT_SCOPE_KEY } from "@weapp-core/constants";
8
8
  import path, { posix } from "pathe";
9
9
  import { fileURLToPath, pathToFileURL } from "node:url";
10
10
  import path$1, { normalize, posix as posix$1, relative, win32 } from "node:path";
@@ -18,15 +18,16 @@ import { collectOnPageScrollPerformanceWarnings } from "@weapp-vite/ast/operatio
18
18
  import { BABEL_TS_MODULE_PARSER_OPTIONS as BABEL_TS_MODULE_PARSER_OPTIONS$1, generate as generate$1, parse as parse$3, parseJsLike, traverse } from "@weapp-vite/ast/babel";
19
19
  import * as t from "@weapp-vite/ast/babelTypes";
20
20
  import picomatch from "picomatch";
21
- import { VUE_COMPONENT_TAG_RE, classifyVueSfcBlockChanges, collectVueTemplateTags, compileJsxFile, compileVueFile, compileVueStyleToWxss, createJsonMerger, createPageEntryMatcher, createPageEntryMatcher as createPageEntryMatcher$1, generateScopedId, getClassStyleWxsSource, getMiniProgramTemplatePlatform, getSfcCheckMtime, injectWevuPageFeaturesInJsWithResolver, invalidateFileCache, isAutoImportCandidateTag, isBuiltinComponent, isUniAppCompatibilityFile, pathExists, readAndParseSfc, readFile as readFile$1, refreshVueFileJsonConfig, resolveClassStyleWxsLocation, resolveVueSfcHmrSignatures, resolveVueSfcStyleIndependentSignature, transformNestedWxssVars, transformUniAppSource, transformVueDeepSelectors } from "wevu/compiler";
21
+ import { VUE_COMPONENT_TAG_RE, classifyVueSfcBlockChanges, collectPageMetaCallsFromPrograms, collectVueTemplateTags, compileJsxFile, compileVueFile, compileVueStyleToWxss, createJsonMerger, createPageEntryMatcher, createPageEntryMatcher as createPageEntryMatcher$1, extractPageDeclarationWithDependencies, generateScopedId, getClassStyleWxsSource, getMiniProgramTemplatePlatform, getSfcCheckMtime, injectWevuPageFeaturesInJsWithResolver, invalidateFileCache, isAutoImportCandidateTag, isBuiltinComponent, isUniAppCompatibilityFile, mayContainPageDeclaration, mayContainPageMeta, pathExists, readAndParseSfc, readAndParseSfc as readAndParseSfc$1, readFile as readFile$1, refreshVueFileJsonConfig, resolveClassStyleWxsLocation, resolveVueSfcHmrSignatures, resolveVueSfcStyleIndependentSignature, stripPageDeclaration, transformNestedWxssVars, transformUniAppSource, transformVueDeepSelectors } from "wevu/compiler";
22
22
  import fs$2, { appendFile, copyFile, mkdir, readFile, readdir, rm } from "node:fs/promises";
23
- import { build, createLogger, createServer, loadConfigFromFile, preprocessCSS, transformWithOxc } from "vite";
23
+ import { BuildEnvironment, build, createIdResolver, createLogger, createServer, loadConfigFromFile, preprocessCSS, resolveConfig, transformWithOxc } from "vite";
24
24
  import { createHash, randomBytes, randomUUID } from "node:crypto";
25
25
  import semverGte from "semver/functions/gte.js";
26
26
  import semverSatisfies from "semver/functions/satisfies.js";
27
27
  import semverValid from "semver/functions/valid.js";
28
28
  import { LRUCache } from "lru-cache";
29
29
  import { fdir } from "fdir";
30
+ import { isDeepStrictEqual } from "node:util";
30
31
  import chokidar from "chokidar";
31
32
  import { getPackageInfo, getPackageInfoSync, resolveModule } from "local-pkg";
32
33
  import { build as build$1 } from "rolldown";
@@ -50,6 +51,7 @@ import tsconfigPaths from "vite-tsconfig-paths";
50
51
  import { wrapPlugin } from "vite-plugin-performance";
51
52
  import { performance as performance$1 } from "node:perf_hooks";
52
53
  import { compileI18nCatalog, generateI18nCatalogModuleSource, generateI18nRuntimeSource, generateI18nWxsSource } from "@weapp-vite/i18n/compiler";
54
+ import selectorParser from "postcss-selector-parser";
53
55
  import { weappWebPlugin } from "@weapp-vite/web";
54
56
  import { bundleRequire } from "rolldown-require";
55
57
  //#region src/debugger.ts
@@ -355,8 +357,9 @@ function createModuleGraphService() {
355
357
  const queue = [id];
356
358
  const visited = /* @__PURE__ */ new Set();
357
359
  for (let index = 0; index < queue.length; index += 1) {
358
- const request = queue[index];
359
- if (visited.has(request)) continue;
360
+ const target = queue[index];
361
+ const request = typeof target === "string" ? target : target.url ?? target.id;
362
+ if (!request || visited.has(request)) continue;
360
363
  visited.add(request);
361
364
  try {
362
365
  await devServer.transformRequest(request);
@@ -364,10 +367,10 @@ function createModuleGraphService() {
364
367
  debug$3?.(`dev graph 预热跳过无法展开的 external 终点 ${request}: ${String(error)}`);
365
368
  continue;
366
369
  }
367
- const module = devServer.moduleGraph.getModuleById(request);
370
+ const module = typeof target === "string" ? devServer.moduleGraph.getModuleById(request) : target;
368
371
  for (const dependency of module?.importedModules ?? []) {
369
372
  const dependencyRequest = dependency.url ?? dependency.id;
370
- if (dependencyRequest && !visited.has(dependencyRequest)) queue.push(dependencyRequest);
373
+ if (dependencyRequest && !visited.has(dependencyRequest)) queue.push(dependency);
371
374
  }
372
375
  }
373
376
  };
@@ -8990,17 +8993,46 @@ function formatSubPackagesTuple(subPackages, baseIndent = "") {
8990
8993
  lines.push(`${baseIndent}]`);
8991
8994
  return lines.join("\n");
8992
8995
  }
8993
- function createTypedRouterDefinition(routes) {
8996
+ function formatStaticRouteType(value, baseIndent) {
8997
+ if (value === null) return "null";
8998
+ if (typeof value === "string") return "string";
8999
+ if (typeof value === "number") return "number";
9000
+ if (typeof value === "boolean") return "boolean";
9001
+ if (Array.isArray(value)) {
9002
+ if (value.length === 0) return "unknown[]";
9003
+ return `Array<${[...new Set(value.map((item) => formatStaticRouteType(item, baseIndent)))].join(" | ")}>`;
9004
+ }
9005
+ const entries = Object.entries(value);
9006
+ if (entries.length === 0) return "{}";
9007
+ const propertyIndent = `${baseIndent}${INDENT}`;
9008
+ return `{\n${entries.map(([key, propertyValue]) => {
9009
+ return `${propertyIndent}${JSON.stringify(key)}: ${formatStaticRouteType(propertyValue, propertyIndent)};`;
9010
+ }).join("\n")}\n${baseIndent}}`;
9011
+ }
9012
+ function formatNamedRouteMapEntries(routes) {
9013
+ const routeIndent = `${INDENT}${INDENT}`;
9014
+ const fieldIndent = `${routeIndent}${INDENT}`;
9015
+ return routes.map((route) => {
9016
+ return [
9017
+ `${routeIndent}${JSON.stringify(route.name)}: {`,
9018
+ `${fieldIndent}path: ${JSON.stringify(route.path)};`,
9019
+ `${fieldIndent}meta: ${formatStaticRouteType(route.meta, fieldIndent)};`,
9020
+ `${routeIndent}};`
9021
+ ].join("\n");
9022
+ });
9023
+ }
9024
+ function createTypedRouterDefinition(routes, namedRoutes = []) {
8994
9025
  const pagesType = formatTuple(routes.pages, INDENT);
8995
9026
  const entriesType = formatTuple(routes.entries, INDENT);
8996
9027
  const subPackagesType = formatSubPackagesTuple(routes.subPackages, INDENT);
9028
+ const namedRouteMapEntries = formatNamedRouteMapEntries(namedRoutes);
8997
9029
  return [
8998
9030
  "/* eslint-disable */",
8999
9031
  "// biome-ignore lint: disable",
9000
9032
  "// oxlint-disable",
9001
9033
  "// ------",
9002
9034
  "// 由 weapp-vite 自动生成,请勿编辑。",
9003
- "import 'wevu/router';",
9035
+ `import '${WEVU_ROUTER_MODULE_ID}';`,
9004
9036
  "",
9005
9037
  "declare module 'weapp-vite/auto-routes' {",
9006
9038
  ` export type AutoRoutesPages = ${pagesType};`,
@@ -9036,10 +9068,13 @@ function createTypedRouterDefinition(routes) {
9036
9068
  " export default routes;",
9037
9069
  "}",
9038
9070
  "",
9039
- "declare module 'wevu/router' {",
9071
+ `declare module '${WEVU_ROUTER_MODULE_ID}' {`,
9040
9072
  " interface WevuTypedRouterRouteMap {",
9041
9073
  " entries: import('weapp-vite/auto-routes').AutoRoutesEntries[number];",
9042
9074
  " }",
9075
+ " interface WevuNamedRouteMap {",
9076
+ ...namedRouteMapEntries,
9077
+ " }",
9043
9078
  "}",
9044
9079
  ""
9045
9080
  ].join("\n");
@@ -9225,6 +9260,34 @@ function applyBuildScopeToAutoRoutes(routes, scope) {
9225
9260
  };
9226
9261
  }
9227
9262
  //#endregion
9263
+ //#region src/runtime/config/internal/alias.ts
9264
+ function normalizeAliasOptions(alias) {
9265
+ if (!alias) return [];
9266
+ if (Array.isArray(alias)) return alias.filter((entry) => {
9267
+ return Boolean(entry && typeof entry === "object" && "find" in entry && "replacement" in entry);
9268
+ });
9269
+ return Object.entries(alias).map(([find, replacement]) => {
9270
+ return {
9271
+ find,
9272
+ replacement
9273
+ };
9274
+ });
9275
+ }
9276
+ function createAliasManager(oxcAlias, defaultBuiltinAliases) {
9277
+ function injectBuiltinAliases(config, builtinAliases = defaultBuiltinAliases) {
9278
+ const resolve = config.resolve ?? (config.resolve = {});
9279
+ const aliasArray = normalizeAliasOptions(resolve.alias);
9280
+ if (!aliasArray.some((entry) => {
9281
+ return entry.find instanceof RegExp && entry.find.source === oxcAlias.find.source;
9282
+ })) aliasArray.unshift(oxcAlias);
9283
+ for (const builtin of builtinAliases) if (!aliasArray.some((entry) => {
9284
+ return typeof entry.find === "string" && entry.find === builtin.find;
9285
+ })) aliasArray.unshift(builtin);
9286
+ resolve.alias = aliasArray;
9287
+ }
9288
+ return { injectBuiltinAliases };
9289
+ }
9290
+ //#endregion
9228
9291
  //#region src/utils/miniProgramGlobals.ts
9229
9292
  function getMiniProgramGlobalKeys() {
9230
9293
  return [...getMiniProgramRuntimeGlobalKeysByResolvePriority()];
@@ -9261,6 +9324,13 @@ function updateWatchTargets(target, next) {
9261
9324
  target.clear();
9262
9325
  for (const item of next) target.add(item);
9263
9326
  }
9327
+ function updatePageDeclarationDependencies(target, next) {
9328
+ target.clear();
9329
+ for (const [dependency, owners] of next) target.set(dependency, new Set(owners));
9330
+ }
9331
+ function createAutoRoutesSourceFingerprint(source) {
9332
+ return createHash("sha256").update(source).digest("hex");
9333
+ }
9264
9334
  function createEmptyAutoRoutesSnapshot() {
9265
9335
  return {
9266
9336
  pages: [],
@@ -9305,21 +9375,39 @@ function createAutoRoutesModuleCode(serialized) {
9305
9375
  ...createAutoRoutesRuntimeLines()
9306
9376
  ].join("\n");
9307
9377
  }
9308
- function createAutoRoutesArtifacts(snapshot) {
9378
+ function createNamedAutoRoutesModuleCode(serialized) {
9379
+ return `export const routes = JSON.parse(${JSON.stringify(serialized)});\n`;
9380
+ }
9381
+ function createAutoRoutesArtifacts(snapshot, namedRoutes = []) {
9309
9382
  const serialized = JSON.stringify(snapshot, null, 2);
9383
+ const namedRoutesSerialized = JSON.stringify(namedRoutes, null, 2);
9310
9384
  return {
9311
9385
  serialized,
9312
9386
  moduleCode: createAutoRoutesModuleCode(serialized),
9313
- typedDefinition: createTypedRouterDefinition(snapshot)
9387
+ namedModuleCode: createNamedAutoRoutesModuleCode(namedRoutesSerialized),
9388
+ signature: JSON.stringify({
9389
+ routes: snapshot,
9390
+ namedRoutes
9391
+ }),
9392
+ typedDefinition: createTypedRouterDefinition(snapshot, namedRoutes)
9314
9393
  };
9315
9394
  }
9316
9395
  function resetAutoRoutesState(state) {
9317
9396
  const emptySnapshot = createEmptyAutoRoutesSnapshot();
9318
9397
  const artifacts = createAutoRoutesArtifacts(emptySnapshot);
9319
9398
  updateRoutesReference(state.routes, emptySnapshot);
9399
+ state.namedRoutes = [];
9320
9400
  state.serialized = artifacts.serialized;
9321
9401
  state.typedDefinition = artifacts.typedDefinition;
9322
9402
  state.moduleCode = artifacts.moduleCode;
9403
+ state.namedModuleCode = artifacts.namedModuleCode;
9404
+ state.signature = artifacts.signature;
9405
+ state.topologyKey = "";
9406
+ state.pageDeclarationDependencies.clear();
9407
+ state.pageDeclarationFingerprints.clear();
9408
+ state.usesOpaquePageDeclarationResolver = false;
9409
+ updateWatchTargets(state.pageSourceFiles, /* @__PURE__ */ new Set());
9410
+ updateWatchTargets(state.namedRouteSourceFiles, /* @__PURE__ */ new Set());
9323
9411
  updateWatchTargets(state.watchFiles, /* @__PURE__ */ new Set());
9324
9412
  updateWatchTargets(state.watchDirs, /* @__PURE__ */ new Set());
9325
9413
  state.dirty = false;
@@ -9335,24 +9423,38 @@ function resolvePersistentCacheBaseDir(configService) {
9335
9423
  return (typeof configService.configFilePath === "string" ? path.dirname(configService.configFilePath) : configService.cwd) || void 0;
9336
9424
  }
9337
9425
  function applyPersistentCache(state, cache) {
9338
- const watchFiles = Array.isArray(cache.watchFiles) ? cache.watchFiles : [];
9426
+ const artifacts = createAutoRoutesArtifacts(cache.snapshot, cache.namedRoutes);
9339
9427
  updateRoutesReference(state.routes, cache.snapshot);
9340
- state.serialized = cache.serialized;
9341
- state.moduleCode = cache.moduleCode;
9342
- state.typedDefinition = cache.typedDefinition;
9343
- updateWatchTargets(state.watchFiles, new Set(watchFiles));
9344
- updateWatchTargets(state.watchDirs, new Set(Array.isArray(cache.watchDirs) ? cache.watchDirs : []));
9428
+ state.namedRoutes = cache.namedRoutes;
9429
+ state.serialized = artifacts.serialized;
9430
+ state.moduleCode = artifacts.moduleCode;
9431
+ state.namedModuleCode = artifacts.namedModuleCode;
9432
+ state.signature = `${artifacts.signature}\n${cache.topologyKey}`;
9433
+ state.typedDefinition = artifacts.typedDefinition;
9434
+ state.topologyKey = cache.topologyKey;
9435
+ updatePageDeclarationDependencies(state.pageDeclarationDependencies, new Map(Object.entries(cache.pageDeclarationDependencies).map(([dependency, owners]) => [dependency, new Set(owners)])));
9436
+ state.pageDeclarationFingerprints.clear();
9437
+ for (const [sourceFile, fingerprint] of Object.entries(cache.pageDeclarationFingerprints)) state.pageDeclarationFingerprints.set(sourceFile, fingerprint);
9438
+ state.usesOpaquePageDeclarationResolver = cache.usesOpaquePageDeclarationResolver;
9439
+ updateWatchTargets(state.pageSourceFiles, new Set(cache.pageSourceFiles));
9440
+ updateWatchTargets(state.namedRouteSourceFiles, new Set(cache.namedRouteSourceFiles));
9441
+ updateWatchTargets(state.watchFiles, new Set(cache.watchFiles));
9442
+ updateWatchTargets(state.watchDirs, new Set(cache.watchDirs));
9345
9443
  state.dirty = false;
9346
9444
  state.initialized = true;
9347
- state.needsFullRescan = true;
9445
+ state.needsFullRescan = false;
9348
9446
  }
9349
9447
  function createPersistentCachePayload(state, fileMtims) {
9350
9448
  return {
9351
- version: 1,
9449
+ version: 6,
9352
9450
  snapshot: cloneRoutes(state.routes),
9353
- serialized: state.serialized,
9354
- moduleCode: state.moduleCode,
9355
- typedDefinition: state.typedDefinition,
9451
+ namedRoutes: state.namedRoutes,
9452
+ topologyKey: state.topologyKey,
9453
+ pageDeclarationDependencies: Object.fromEntries([...state.pageDeclarationDependencies].map(([dependency, owners]) => [dependency, [...owners]])),
9454
+ pageDeclarationFingerprints: Object.fromEntries(state.pageDeclarationFingerprints),
9455
+ usesOpaquePageDeclarationResolver: state.usesOpaquePageDeclarationResolver,
9456
+ pageSourceFiles: [...state.pageSourceFiles],
9457
+ namedRouteSourceFiles: [...state.namedRouteSourceFiles],
9356
9458
  watchFiles: [...state.watchFiles],
9357
9459
  watchDirs: [...state.watchDirs],
9358
9460
  fileMtims
@@ -9460,6 +9562,7 @@ function isAutoRoutesCandidateUnchanged(previous, candidate) {
9460
9562
  }
9461
9563
  //#endregion
9462
9564
  //#region src/runtime/autoRoutesPlugin/routes/scan.ts
9565
+ const PAGE_SOURCE_EXTENSIONS = [...scriptExtensions, ...vueExtensions];
9463
9566
  function sortAutoRoutesEntries(values) {
9464
9567
  values.sort((a, b) => {
9465
9568
  if (a === "pages/index/index") return -1;
@@ -9488,7 +9591,136 @@ function shouldIncludeScanCandidate(candidate, json, route) {
9488
9591
  }
9489
9592
  return candidate.hasScript || candidate.hasTemplate || Boolean(candidate.jsonPath);
9490
9593
  }
9491
- async function scanRoutes(ctx, candidatesMap) {
9594
+ function resolvePageDeclarationAliases(ctx) {
9595
+ const configService = ctx.configService;
9596
+ if (!configService) return [];
9597
+ return [...normalizeAliasOptions(configService.inlineConfig?.resolve?.alias), ...configService.aliasEntries ?? []];
9598
+ }
9599
+ function resolveCandidatePageSources(ctx, candidate) {
9600
+ const sourceFiles = PAGE_SOURCE_EXTENSIONS.map((extension) => `${candidate.base}.${extension}`).filter((sourceFile) => candidate.files.has(sourceFile));
9601
+ const nativeSource = sourceFiles[0];
9602
+ if (!nativeSource) return [];
9603
+ if (ctx.configService?.weappWebConfig?.enabled !== true) return [nativeSource];
9604
+ return [nativeSource, ...sourceFiles.filter((sourceFile) => sourceFile !== nativeSource)];
9605
+ }
9606
+ async function collectNamedRoutes(ctx, candidates, scopedEntries, options) {
9607
+ const pageDeclarationAliases = resolvePageDeclarationAliases(ctx);
9608
+ const configService = ctx.configService;
9609
+ const scopedCandidates = candidates.filter((candidate) => scopedEntries.has(candidate.entry)).sort((a, b) => a.entry.localeCompare(b.entry));
9610
+ const sourceCache = /* @__PURE__ */ new Map();
9611
+ const readSource = (sourceFile) => {
9612
+ let pending = sourceCache.get(sourceFile);
9613
+ if (!pending) {
9614
+ pending = fs$1.readFile(sourceFile, "utf8");
9615
+ sourceCache.set(sourceFile, pending);
9616
+ }
9617
+ return pending;
9618
+ };
9619
+ const resolveSource = async (source, importer) => {
9620
+ const resolved = await options.resolvePageDeclarationSource?.(source, importer);
9621
+ if (resolved) return resolved;
9622
+ if (!importer) return;
9623
+ const aliased = resolveImportee$1(source, importer, pageDeclarationAliases);
9624
+ return aliased === source ? void 0 : aliased;
9625
+ };
9626
+ const declarations = await Promise.all(scopedCandidates.map(async ({ candidate, entry }) => {
9627
+ const sourceFiles = resolveCandidatePageSources(ctx, candidate);
9628
+ const sources = await Promise.all(sourceFiles.map(async (sourceFile) => {
9629
+ const source = await readSource(sourceFile);
9630
+ return {
9631
+ ...await extractPageDeclarationWithDependencies(source, sourceFile, {
9632
+ readFile: readSource,
9633
+ resolveId: resolveSource
9634
+ }),
9635
+ sourceFile
9636
+ };
9637
+ }));
9638
+ const primary = sources[0];
9639
+ for (const alternate of sources.slice(1)) if (!isDeepStrictEqual(primary?.declaration, alternate.declaration)) {
9640
+ const first = toPosixPath(path.relative(configService.cwd, primary.sourceFile));
9641
+ const second = toPosixPath(path.relative(configService.cwd, alternate.sourceFile));
9642
+ throw new Error(`[auto-routes] 页面 ${entry} 的候选源文件页面声明不一致:${first} 与 ${second}`);
9643
+ }
9644
+ return {
9645
+ entry,
9646
+ primary,
9647
+ sources
9648
+ };
9649
+ }));
9650
+ const namedRoutes = [];
9651
+ const pageSourceFiles = /* @__PURE__ */ new Set();
9652
+ const namedRouteSourceFiles = /* @__PURE__ */ new Set();
9653
+ const pageDeclarationDependencies = /* @__PURE__ */ new Map();
9654
+ const sourceByName = /* @__PURE__ */ new Map();
9655
+ for (const { entry, primary, sources } of declarations) {
9656
+ for (const source of sources) {
9657
+ pageSourceFiles.add(source.sourceFile);
9658
+ for (const dependency of source.dependencies) {
9659
+ let owners = pageDeclarationDependencies.get(dependency);
9660
+ if (!owners) {
9661
+ owners = /* @__PURE__ */ new Set();
9662
+ pageDeclarationDependencies.set(dependency, owners);
9663
+ }
9664
+ owners.add(source.sourceFile);
9665
+ }
9666
+ }
9667
+ const declaration = primary?.declaration;
9668
+ if (!declaration || !primary) continue;
9669
+ const routeSourceFile = primary.declarationSourceFile ?? primary.sourceFile;
9670
+ const duplicateSource = sourceByName.get(declaration.name);
9671
+ if (duplicateSource) {
9672
+ const first = toPosixPath(path.relative(configService.cwd, duplicateSource));
9673
+ const second = toPosixPath(path.relative(configService.cwd, routeSourceFile));
9674
+ throw new Error(`[auto-routes] 页面路由名称 ${JSON.stringify(declaration.name)} 重复:${first} 与 ${second}`);
9675
+ }
9676
+ sourceByName.set(declaration.name, routeSourceFile);
9677
+ for (const source of sources) namedRouteSourceFiles.add(source.sourceFile);
9678
+ namedRoutes.push({
9679
+ name: declaration.name,
9680
+ path: `/${entry}`,
9681
+ meta: declaration.meta ?? {}
9682
+ });
9683
+ }
9684
+ const pageDeclarationFingerprints = /* @__PURE__ */ new Map();
9685
+ await Promise.all([...sourceCache].map(async ([sourceFile, pendingSource]) => {
9686
+ pageDeclarationFingerprints.set(sourceFile, createAutoRoutesSourceFingerprint(await pendingSource));
9687
+ }));
9688
+ return {
9689
+ namedRoutes,
9690
+ namedRouteSourceFiles,
9691
+ pageDeclarationDependencies,
9692
+ pageDeclarationFingerprints,
9693
+ pageSourceFiles
9694
+ };
9695
+ }
9696
+ function createAutoRoutesTopologyKey(ctx, candidatesMap) {
9697
+ const configService = ctx.configService;
9698
+ if (!configService) return "";
9699
+ const candidates = [...candidatesMap.values()].map((candidate) => ({
9700
+ base: toPosixPath(path.relative(configService.absoluteSrcRoot, candidate.base)),
9701
+ files: [...candidate.files].map((filePath) => toPosixPath(path.relative(configService.absoluteSrcRoot, filePath))).sort((a, b) => a.localeCompare(b))
9702
+ })).sort((a, b) => a.base.localeCompare(b.base));
9703
+ const { subPackageRoots } = resolveAutoRoutesMatcherContext(ctx);
9704
+ const pageDeclarationAliases = resolvePageDeclarationAliases(ctx).map((alias) => ({
9705
+ find: typeof alias.find === "string" ? {
9706
+ kind: "string",
9707
+ value: alias.find
9708
+ } : {
9709
+ flags: alias.find.flags,
9710
+ kind: "regexp",
9711
+ value: alias.find.source
9712
+ },
9713
+ replacement: alias.replacement
9714
+ }));
9715
+ return JSON.stringify({
9716
+ buildScope: resolveBuildScope(configService.weappViteConfig.buildScope),
9717
+ webSiblingValidation: configService.weappWebConfig?.enabled === true,
9718
+ pageDeclarationAliases,
9719
+ candidates,
9720
+ subPackageRoots: [...subPackageRoots].sort((a, b) => a.localeCompare(b))
9721
+ });
9722
+ }
9723
+ async function scanRoutes(ctx, candidatesMap, options = {}) {
9492
9724
  const configService = ctx.configService;
9493
9725
  const jsonService = ctx.jsonService;
9494
9726
  if (!configService || !jsonService) throw new Error("扫描路由前必须初始化 configService/jsonService。");
@@ -9499,7 +9731,12 @@ async function scanRoutes(ctx, candidatesMap) {
9499
9731
  const subPackages = /* @__PURE__ */ new Map();
9500
9732
  const watchFiles = /* @__PURE__ */ new Set();
9501
9733
  const watchDirs = /* @__PURE__ */ new Set();
9502
- const candidateList = [...candidatesMap.values()];
9734
+ const includedCandidates = [];
9735
+ const candidatesSnapshot = new Map([...candidatesMap].map(([base, candidate]) => [base, {
9736
+ ...candidate,
9737
+ files: new Set(candidate.files)
9738
+ }]));
9739
+ const candidateList = [...candidatesSnapshot.values()];
9503
9740
  const jsonEntries = await Promise.all(candidateList.map(async (candidate) => {
9504
9741
  if (!candidate.jsonPath) return {
9505
9742
  candidate,
@@ -9523,6 +9760,10 @@ async function scanRoutes(ctx, candidatesMap) {
9523
9760
  entriesSet.add(route.entry);
9524
9761
  if (route.root) ensureSubPackage(subPackages, route.root).add(route.pagePath);
9525
9762
  else pagesSet.add(route.pagePath);
9763
+ includedCandidates.push({
9764
+ candidate,
9765
+ entry: route.entry
9766
+ });
9526
9767
  }
9527
9768
  for (const dir of matcher.getWatchRoots(absoluteSrcRoot)) watchDirs.add(dir);
9528
9769
  const pages = [...pagesSet];
@@ -9543,12 +9784,27 @@ async function scanRoutes(ctx, candidatesMap) {
9543
9784
  entries,
9544
9785
  subPackages: subPackageList
9545
9786
  }, resolveBuildScope(configService.weappViteConfig.buildScope));
9546
- const { serialized, moduleCode, typedDefinition } = createAutoRoutesArtifacts(snapshot);
9787
+ const { namedRoutes, namedRouteSourceFiles, pageDeclarationDependencies, pageDeclarationFingerprints, pageSourceFiles } = await collectNamedRoutes(ctx, includedCandidates, new Set(snapshot.entries), options);
9788
+ for (const dependency of pageDeclarationDependencies.keys()) {
9789
+ watchFiles.add(dependency);
9790
+ watchDirs.add(path.dirname(dependency));
9791
+ }
9792
+ const { serialized, moduleCode, namedModuleCode, signature: routeSignature, typedDefinition } = createAutoRoutesArtifacts(snapshot, namedRoutes);
9793
+ const topologyKey = createAutoRoutesTopologyKey(ctx, candidatesSnapshot);
9547
9794
  return {
9548
9795
  snapshot,
9796
+ namedRoutes,
9549
9797
  serialized,
9550
9798
  moduleCode,
9799
+ namedModuleCode,
9800
+ signature: `${routeSignature}\n${topologyKey}`,
9551
9801
  typedDefinition,
9802
+ topologyKey,
9803
+ namedRouteSourceFiles,
9804
+ pageDeclarationDependencies,
9805
+ pageDeclarationFingerprints,
9806
+ usesOpaquePageDeclarationResolver: Boolean(options.resolvePageDeclarationSource && pageDeclarationDependencies.size > 0),
9807
+ pageSourceFiles,
9552
9808
  watchFiles,
9553
9809
  watchDirs
9554
9810
  };
@@ -9591,6 +9847,24 @@ function cloneRoutes(routes) {
9591
9847
  function getResolvedConfig(ctx) {
9592
9848
  return resolveWeappAutoRoutesConfig(ctx.configService?.weappViteConfig?.autoRoutes);
9593
9849
  }
9850
+ function isStringArray(value) {
9851
+ return Array.isArray(value) && value.every((item) => typeof item === "string");
9852
+ }
9853
+ function isStringArrayRecord(value) {
9854
+ return isObject(value) && !Array.isArray(value) && Object.values(value).every(isStringArray);
9855
+ }
9856
+ function isStringRecord(value) {
9857
+ return isObject(value) && !Array.isArray(value) && Object.values(value).every((item) => typeof item === "string");
9858
+ }
9859
+ function isPersistentCache(value, topologyKey) {
9860
+ if (!isObject(value) || Array.isArray(value) || !isObject(value.snapshot) || Array.isArray(value.snapshot) || !isObject(value.fileMtims) || Array.isArray(value.fileMtims) || !isStringArrayRecord(value.pageDeclarationDependencies) || !isStringRecord(value.pageDeclarationFingerprints)) return false;
9861
+ const subPackages = value.snapshot.subPackages;
9862
+ const namedRoutes = value.namedRoutes;
9863
+ const pageSourceFiles = value.pageSourceFiles;
9864
+ const dependencyEntries = Object.entries(value.pageDeclarationDependencies);
9865
+ const fingerprints = value.pageDeclarationFingerprints;
9866
+ return value.version === 6 && value.topologyKey === topologyKey && typeof value.usesOpaquePageDeclarationResolver === "boolean" && isStringArray(value.snapshot.pages) && isStringArray(value.snapshot.entries) && Array.isArray(subPackages) && subPackages.every((pkg) => isObject(pkg) && !Array.isArray(pkg) && typeof pkg.root === "string" && isStringArray(pkg.pages)) && Array.isArray(namedRoutes) && namedRoutes.every((route) => isObject(route) && !Array.isArray(route) && typeof route.name === "string" && typeof route.path === "string" && isObject(route.meta) && !Array.isArray(route.meta)) && isStringArray(pageSourceFiles) && isStringArray(value.namedRouteSourceFiles) && isStringArray(value.watchFiles) && isStringArray(value.watchDirs) && dependencyEntries.every(([, owners]) => isStringArray(owners)) && Object.values(fingerprints).every((fingerprint) => typeof fingerprint === "string") && pageSourceFiles.every((sourceFile) => Object.hasOwn(fingerprints, sourceFile)) && dependencyEntries.every(([dependency, owners]) => Object.hasOwn(fingerprints, dependency) && owners.every((owner) => pageSourceFiles.includes(owner))) && Object.values(value.fileMtims).every((mtime) => typeof mtime === "number" && Number.isFinite(mtime));
9867
+ }
9594
9868
  function resolvePersistentCachePath(ctx) {
9595
9869
  const autoRoutesConfig = getResolvedConfig(ctx);
9596
9870
  if (!autoRoutesConfig.persistentCache) return;
@@ -9629,22 +9903,26 @@ async function collectWatchFileMtims(watchFiles) {
9629
9903
  }));
9630
9904
  return Object.fromEntries(entries);
9631
9905
  }
9632
- async function restorePersistentCache(ctx, state) {
9906
+ async function restorePersistentCache(ctx, state, topologyKey, isCurrent = () => true, hasOpaquePageDeclarationSourceResolver = false) {
9633
9907
  if (!getResolvedConfig(ctx).persistentCache) return false;
9634
9908
  const cachePath = resolvePersistentCachePath(ctx);
9635
9909
  if (!cachePath || !await fs$1.pathExists(cachePath)) return false;
9636
9910
  try {
9637
- const cache = await fs$1.readJson(cachePath);
9638
- if (cache?.version !== 1) return false;
9639
- const watchFiles = Array.isArray(cache.watchFiles) ? cache.watchFiles : [];
9911
+ const cached = await fs$1.readJson(cachePath);
9912
+ if (!isPersistentCache(cached, topologyKey)) return false;
9913
+ const cache = cached;
9914
+ if (Object.keys(cache.pageDeclarationDependencies).length > 0 && (cache.usesOpaquePageDeclarationResolver || hasOpaquePageDeclarationSourceResolver)) return false;
9915
+ const watchFiles = cache.watchFiles;
9640
9916
  if (watchFiles.length === 0) return false;
9641
9917
  const cachedMtims = cache.fileMtims;
9642
- if (!cachedMtims) return false;
9643
9918
  const fileMtims = await collectWatchFileMtims(watchFiles);
9644
9919
  for (const filePath of watchFiles) {
9645
9920
  const expectedMtime = cachedMtims[filePath];
9646
9921
  if (typeof expectedMtime !== "number" || !Number.isFinite(expectedMtime) || fileMtims[filePath] !== expectedMtime) return false;
9647
9922
  }
9923
+ if ((await Promise.all(Object.entries(cache.pageDeclarationFingerprints).map(async ([sourceFile, expectedFingerprint]) => {
9924
+ return [expectedFingerprint, createAutoRoutesSourceFingerprint(await fs$1.readFile(sourceFile, "utf8"))];
9925
+ }))).some(([expected, current]) => expected !== current) || !isCurrent()) return false;
9648
9926
  applyPersistentCache(state, cache);
9649
9927
  return true;
9650
9928
  } catch {
@@ -9654,14 +9932,13 @@ async function restorePersistentCache(ctx, state) {
9654
9932
  async function writePersistentCache(ctx, state) {
9655
9933
  const cachePath = resolvePersistentCachePath(ctx);
9656
9934
  if (!cachePath || !state.initialized || !getResolvedConfig(ctx).persistentCache) return;
9657
- let fileMtims;
9935
+ const payload = createPersistentCachePayload(state, {});
9658
9936
  try {
9659
- fileMtims = await collectWatchFileMtims(state.watchFiles);
9937
+ payload.fileMtims = await collectWatchFileMtims(payload.watchFiles);
9660
9938
  } catch {
9661
9939
  return;
9662
9940
  }
9663
9941
  try {
9664
- const payload = createPersistentCachePayload(state, fileMtims);
9665
9942
  if (await hasSamePersistentCachePayload(cachePath, payload)) return;
9666
9943
  await fs$1.outputJson(cachePath, payload, { spaces: 2 });
9667
9944
  } catch (error) {
@@ -9813,7 +10090,9 @@ async function updateCandidateFromFile(ctx, stateCandidates, filePath, event, ma
9813
10090
  function createAutoRoutesService(ctx) {
9814
10091
  const state = ctx.runtimeState.autoRoutes;
9815
10092
  let pendingScan;
10093
+ let pendingRefresh;
9816
10094
  let lastWrittenTypedDefinition;
10095
+ let resolvePageDeclarationSource;
9817
10096
  let mutationVersion = 0;
9818
10097
  function flagDirty() {
9819
10098
  mutationVersion += 1;
@@ -9836,6 +10115,22 @@ function createAutoRoutesService(ctx) {
9836
10115
  function markNeedsFullRescan() {
9837
10116
  state.needsFullRescan = true;
9838
10117
  }
10118
+ async function mayChangePageDeclaration(sourcePath) {
10119
+ if (!state.pageSourceFiles.has(sourcePath)) return false;
10120
+ if (state.namedRouteSourceFiles.has(sourcePath)) return true;
10121
+ try {
10122
+ const source = await fs$1.readFile(sourcePath, "utf8");
10123
+ return mayContainPageDeclaration(source);
10124
+ } catch {
10125
+ return true;
10126
+ }
10127
+ }
10128
+ function getPageDeclarationOwners(filePath) {
10129
+ const sourcePath = normalizeFsResolvedId(filePath);
10130
+ const dependencyOwners = state.pageDeclarationDependencies.get(sourcePath);
10131
+ if (dependencyOwners) return [...dependencyOwners];
10132
+ return state.pageSourceFiles.has(sourcePath) ? [sourcePath] : [];
10133
+ }
9839
10134
  async function ensureCandidateRegistry() {
9840
10135
  const configService = requireConfigService(ctx, "扫描路由前必须初始化 configService。");
9841
10136
  if (!isEnabled()) {
@@ -9857,46 +10152,76 @@ function createAutoRoutesService(ctx) {
9857
10152
  state.needsFullRescan = false;
9858
10153
  return true;
9859
10154
  }
9860
- async function ensureFresh() {
10155
+ async function refresh() {
9861
10156
  if (!isEnabled()) {
9862
- if (state.dirty || !state.initialized || state.routes.pages.length > 0 || state.routes.entries.length > 0 || state.routes.subPackages.length > 0) resetState();
10157
+ if (state.dirty || !state.initialized || state.routes.pages.length > 0 || state.routes.entries.length > 0 || state.routes.subPackages.length > 0 || state.namedRoutes.length > 0) resetState();
9863
10158
  if (await removeTypedRouterDefinition(ctx)) lastWrittenTypedDefinition = void 0;
9864
10159
  await removePersistentCache(ctx);
9865
10160
  return;
9866
10161
  }
9867
10162
  if (!getResolvedConfig().persistentCache) await removePersistentCache(ctx);
10163
+ let registryUpdated = false;
9868
10164
  if (!state.initialized && state.needsFullRescan) {
9869
- if (await restorePersistentCache(ctx, state)) {
10165
+ registryUpdated = await ensureCandidateRegistry();
10166
+ const topologyKey = createAutoRoutesTopologyKey(ctx, state.candidates);
10167
+ const restoreVersion = mutationVersion;
10168
+ const isRestoreCurrent = () => {
10169
+ return mutationVersion === restoreVersion && topologyKey === createAutoRoutesTopologyKey(ctx, state.candidates);
10170
+ };
10171
+ if (await restorePersistentCache(ctx, state, topologyKey, isRestoreCurrent, Boolean(resolvePageDeclarationSource)) && isRestoreCurrent()) {
9870
10172
  lastWrittenTypedDefinition = await writeTypedRouterDefinition(ctx, state.typedDefinition, lastWrittenTypedDefinition);
9871
- return;
10173
+ if (isRestoreCurrent()) return;
9872
10174
  }
9873
10175
  }
9874
- if (await ensureCandidateRegistry()) flagDirty();
10176
+ if (!registryUpdated) registryUpdated = await ensureCandidateRegistry();
10177
+ if (registryUpdated) flagDirty();
9875
10178
  if (!state.dirty) {
9876
10179
  await (pendingScan ?? Promise.resolve());
9877
- lastWrittenTypedDefinition = await writeTypedRouterDefinition(ctx, state.typedDefinition, lastWrittenTypedDefinition);
10180
+ if (!state.dirty) lastWrittenTypedDefinition = await writeTypedRouterDefinition(ctx, state.typedDefinition, lastWrittenTypedDefinition);
9878
10181
  return;
9879
10182
  }
9880
10183
  while (state.dirty) {
9881
10184
  if (!pendingScan) {
9882
10185
  const versionSnapshot = mutationVersion;
9883
- pendingScan = scanRoutes(ctx, state.candidates).then((result) => {
10186
+ pendingScan = scanRoutes(ctx, state.candidates, { resolvePageDeclarationSource }).then((result) => {
10187
+ if (mutationVersion !== versionSnapshot) return;
9884
10188
  updateRoutesReference(state.routes, result.snapshot);
10189
+ state.namedRoutes = result.namedRoutes;
9885
10190
  state.serialized = result.serialized;
9886
10191
  state.moduleCode = result.moduleCode;
10192
+ state.namedModuleCode = result.namedModuleCode;
10193
+ state.signature = result.signature;
9887
10194
  state.typedDefinition = result.typedDefinition;
10195
+ state.topologyKey = result.topologyKey;
10196
+ updatePageDeclarationDependencies(state.pageDeclarationDependencies, result.pageDeclarationDependencies);
10197
+ state.pageDeclarationFingerprints.clear();
10198
+ for (const [sourceFile, fingerprint] of result.pageDeclarationFingerprints) state.pageDeclarationFingerprints.set(sourceFile, fingerprint);
10199
+ state.usesOpaquePageDeclarationResolver = result.usesOpaquePageDeclarationResolver;
10200
+ updateWatchTargets(state.pageSourceFiles, result.pageSourceFiles);
10201
+ updateWatchTargets(state.namedRouteSourceFiles, result.namedRouteSourceFiles);
9888
10202
  updateWatchTargets(state.watchFiles, result.watchFiles);
9889
10203
  updateWatchTargets(state.watchDirs, result.watchDirs);
9890
- if (mutationVersion === versionSnapshot) state.dirty = false;
10204
+ state.dirty = false;
9891
10205
  state.initialized = true;
10206
+ }).catch((error) => {
10207
+ if (mutationVersion === versionSnapshot) throw error;
9892
10208
  }).finally(() => {
9893
10209
  pendingScan = void 0;
9894
10210
  });
9895
10211
  }
9896
10212
  await pendingScan;
9897
- lastWrittenTypedDefinition = await writeTypedRouterDefinition(ctx, state.typedDefinition, lastWrittenTypedDefinition);
9898
- await writePersistentCache(ctx, state);
9899
10213
  }
10214
+ const publicationVersion = mutationVersion;
10215
+ if (!state.dirty) lastWrittenTypedDefinition = await writeTypedRouterDefinition(ctx, state.typedDefinition, lastWrittenTypedDefinition);
10216
+ if (!state.dirty && mutationVersion === publicationVersion) await writePersistentCache(ctx, state);
10217
+ }
10218
+ async function ensureFresh() {
10219
+ do {
10220
+ pendingRefresh ??= refresh().finally(() => {
10221
+ pendingRefresh = void 0;
10222
+ });
10223
+ await pendingRefresh;
10224
+ } while (state.dirty);
9900
10225
  }
9901
10226
  return {
9902
10227
  async ensureFresh() {
@@ -9913,24 +10238,46 @@ function createAutoRoutesService(ctx) {
9913
10238
  return state.routes;
9914
10239
  },
9915
10240
  getSignature() {
9916
- return state.serialized;
10241
+ return state.signature;
9917
10242
  },
9918
10243
  getModuleCode() {
9919
10244
  return state.moduleCode;
9920
10245
  },
10246
+ getNamedModuleCode() {
10247
+ return state.namedModuleCode;
10248
+ },
9921
10249
  getWatchFiles() {
9922
10250
  return state.watchFiles.values();
9923
10251
  },
9924
10252
  getWatchDirectories() {
9925
10253
  return state.watchDirs.values();
9926
10254
  },
10255
+ getPageDeclarationOwners(filePath) {
10256
+ return isEnabled() ? getPageDeclarationOwners(filePath) : [];
10257
+ },
9927
10258
  isRouteFile(filePath) {
9928
- return isEnabled() && matchesRouteFile(ctx, filePath);
10259
+ return isEnabled() && (getPageDeclarationOwners(filePath).length > 0 || matchesRouteFile(ctx, filePath));
10260
+ },
10261
+ isPageSource(filePath) {
10262
+ const sourcePath = normalizeFsResolvedId(filePath);
10263
+ return isEnabled() && state.pageSourceFiles.has(sourcePath);
10264
+ },
10265
+ isPageDeclarationSource(filePath) {
10266
+ return isEnabled() && getPageDeclarationOwners(filePath).length > 0;
10267
+ },
10268
+ setPageDeclarationSourceResolver(resolve) {
10269
+ resolvePageDeclarationSource = resolve;
9929
10270
  },
9930
10271
  async handleFileChange(filePath, event) {
9931
10272
  if (!isEnabled()) return false;
10273
+ const sourcePath = normalizeFsResolvedId(filePath);
10274
+ if (state.pageDeclarationDependencies.has(sourcePath)) {
10275
+ flagDirty();
10276
+ await ensureFresh();
10277
+ return true;
10278
+ }
9932
10279
  if (!matchesRouteFile(ctx, filePath)) return false;
9933
- if (!await updateCandidateFromFile(ctx, state.candidates, filePath, event, markNeedsFullRescan) && !state.needsFullRescan) return false;
10280
+ if (!await updateCandidateFromFile(ctx, state.candidates, filePath, event, markNeedsFullRescan) && !state.needsFullRescan && !state.dirty && !await mayChangePageDeclaration(sourcePath)) return false;
9934
10281
  flagDirty();
9935
10282
  await ensureFresh();
9936
10283
  return true;
@@ -9944,12 +10291,162 @@ function createAutoRoutesService(ctx) {
9944
10291
  };
9945
10292
  }
9946
10293
  //#endregion
10294
+ //#region src/runtime/autoRoutesPlugin/service/resolver.ts
10295
+ function createDefaultPageDeclarationSourceResolver(ctx) {
10296
+ let currentConfig;
10297
+ let pendingResolver;
10298
+ return async (source, importer) => {
10299
+ const configService = ctx.configService;
10300
+ if (!configService) return;
10301
+ if (!pendingResolver || currentConfig !== configService.inlineConfig) {
10302
+ currentConfig = configService.inlineConfig;
10303
+ pendingResolver = resolveConfig({
10304
+ root: configService.cwd,
10305
+ configFile: false,
10306
+ mode: configService.mode,
10307
+ resolve: currentConfig?.resolve,
10308
+ environments: currentConfig?.environments
10309
+ }, configService.isDev ? "serve" : "build", configService.mode, configService.isDev ? "development" : "production").then((config) => {
10310
+ const environment = new BuildEnvironment("client", config);
10311
+ const resolveId = createIdResolver(config);
10312
+ return (id, importer) => resolveId(environment, id, importer);
10313
+ });
10314
+ }
10315
+ return await (await pendingResolver)(source, importer);
10316
+ };
10317
+ }
10318
+ //#endregion
9947
10319
  //#region src/runtime/autoRoutesPlugin/index.ts
9948
10320
  function createAutoRoutesServicePlugin(ctx) {
9949
- ctx.autoRoutesService = createAutoRoutesService(ctx);
10321
+ const service = createAutoRoutesService(ctx);
10322
+ service.setPageDeclarationSourceResolver(createDefaultPageDeclarationSourceResolver(ctx));
10323
+ ctx.autoRoutesService = service;
9950
10324
  return { name: "weapp-runtime:auto-routes-service" };
9951
10325
  }
9952
10326
  //#endregion
10327
+ //#region src/plugins/autoRoutes.shared.ts
10328
+ const AUTO_ROUTES_ID$1 = "weapp-vite/auto-routes";
10329
+ const VIRTUAL_MODULE_ID = "virtual:weapp-vite-auto-routes";
10330
+ const RESOLVED_VIRTUAL_ID = "\0weapp-vite:auto-routes";
10331
+ /**
10332
+ * 判断当前是否应按 watch 模式为 auto-routes 注册依赖文件。
10333
+ */
10334
+ function isAutoRoutesWatchMode(configService) {
10335
+ return Boolean(configService?.isDev || configService?.inlineConfig?.build?.watch);
10336
+ }
10337
+ /**
10338
+ * 合并 service 与 matcher 提供的监听目录,并去重保留顺序。
10339
+ */
10340
+ function collectAutoRoutesWatchDirs(watchDirectories, matcherWatchRoots) {
10341
+ const watchDirs = /* @__PURE__ */ new Set();
10342
+ for (const dir of watchDirectories) watchDirs.add(dir);
10343
+ for (const dir of matcherWatchRoots) watchDirs.add(dir);
10344
+ return [...watchDirs];
10345
+ }
10346
+ /**
10347
+ * 过滤出真正需要交给 auto-routes watcher 处理的路由源文件。
10348
+ * 已知声明依赖不受普通页面发现扩展名限制,其他文件仍沿用发现规则。
10349
+ */
10350
+ function isAutoRoutesWatchFile(filePath, allowedExtensions, isPagesRelatedPath, isPageDeclarationSource) {
10351
+ if (isAutoRoutesGeneratedFileName(path.basename(filePath))) return false;
10352
+ if (isPageDeclarationSource(filePath)) return true;
10353
+ return allowedExtensions.has(path.extname(filePath)) && isPagesRelatedPath(filePath);
10354
+ }
10355
+ /**
10356
+ * 判断是否满足 auto-routes sidecar watcher 的启动前置条件。
10357
+ */
10358
+ function shouldStartAutoRoutesWatcher(options) {
10359
+ if (options.routeWatcherStarted) return false;
10360
+ if (!options.isDev) return false;
10361
+ if (!options.autoRoutesEnabled || !options.autoRoutesWatch || !options.serviceEnabled) return false;
10362
+ return options.watchDirsLength > 0;
10363
+ }
10364
+ /**
10365
+ * 生成 sidecar watcher map 使用的关闭句柄。
10366
+ */
10367
+ function createAutoRoutesSidecarWatcher(watcher) {
10368
+ return { close: async () => {
10369
+ await watcher.close();
10370
+ } };
10371
+ }
10372
+ /**
10373
+ * 向插件上下文注册 auto-routes 相关 watch 目标,忽略单个 addWatchFile 失败。
10374
+ */
10375
+ function addAutoRoutesWatchTargets(pluginCtx, targets) {
10376
+ for (const file of targets.files) try {
10377
+ pluginCtx.addWatchFile?.(normalizeWatchPath(file));
10378
+ } catch {}
10379
+ for (const dir of targets.directories) try {
10380
+ pluginCtx.addWatchFile?.(normalizeWatchPath(dir));
10381
+ } catch {}
10382
+ }
10383
+ function invalidateAutoRoutesVirtualModules(server, resolvedIds) {
10384
+ if (!server) return;
10385
+ const seen = /* @__PURE__ */ new Set();
10386
+ const invalidateModuleWithImporters = (module) => {
10387
+ if (seen.has(module)) return;
10388
+ seen.add(module);
10389
+ server.moduleGraph.invalidateModule(module);
10390
+ for (const importer of module.importers) invalidateModuleWithImporters(importer);
10391
+ };
10392
+ for (const id of resolvedIds) {
10393
+ const virtualModule = server.moduleGraph.getModuleById(id);
10394
+ if (virtualModule) invalidateModuleWithImporters(virtualModule);
10395
+ }
10396
+ }
10397
+ /**
10398
+ * 统一解析 auto-routes 虚拟模块与 alias 入口的命中关系。
10399
+ */
10400
+ function resolveAutoRoutesVirtualId(id, aliasTargets) {
10401
+ if (id === WEVU_AUTO_ROUTES_MODULE_ID$1 || id === WEVU_AUTO_ROUTES_VIRTUAL_MODULE_ID$1 || id === WEVU_AUTO_ROUTES_RESOLVED_MODULE_ID$1) return WEVU_AUTO_ROUTES_RESOLVED_MODULE_ID$1;
10402
+ if (id === "weapp-vite/auto-routes" || id === "virtual:weapp-vite-auto-routes" || id === "\0weapp-vite:auto-routes") return RESOLVED_VIRTUAL_ID;
10403
+ return aliasTargets?.has(id) ? RESOLVED_VIRTUAL_ID : null;
10404
+ }
10405
+ /**
10406
+ * 将 create/delete 这类结构性变化映射为 auto-routes 的全量重扫语义。
10407
+ */
10408
+ function resolveAutoRoutesWatchChangeEvent(event) {
10409
+ if (event === "create" || event === "delete") return "rename";
10410
+ }
10411
+ /**
10412
+ * 判断某次热更新是否需要触发 auto-routes 虚拟模块失效。
10413
+ */
10414
+ function resolveAutoRoutesHotUpdateAction(command, options) {
10415
+ if (command === "serve") return options.isRouteFile ? {
10416
+ shouldHandle: true,
10417
+ shouldUpdateRouteFile: true
10418
+ } : {
10419
+ shouldHandle: false,
10420
+ shouldUpdateRouteFile: false
10421
+ };
10422
+ if (options.isRouteFile || options.isPagesRelatedPath) return {
10423
+ shouldHandle: true,
10424
+ shouldUpdateRouteFile: false
10425
+ };
10426
+ return {
10427
+ shouldHandle: false,
10428
+ shouldUpdateRouteFile: false
10429
+ };
10430
+ }
10431
+ /**
10432
+ * Web 路由表在创建 router 时完成快照,必须越过 SFC 自接受边界重新加载入口。
10433
+ * 入口排在前面,避免依赖失效先将生成的入口降为仅更新时间戳的软失效。
10434
+ */
10435
+ function collectAutoRoutesReloadModules(modules) {
10436
+ const pending = [...modules];
10437
+ const visited = new Set(pending);
10438
+ const reloadModules = /* @__PURE__ */ new Set();
10439
+ for (const module of pending) {
10440
+ if (module.importers.size === 0) reloadModules.add(module);
10441
+ for (const importer of module.importers) if (!visited.has(importer)) {
10442
+ visited.add(importer);
10443
+ pending.push(importer);
10444
+ }
10445
+ }
10446
+ for (const module of modules) reloadModules.add(module);
10447
+ return [...reloadModules];
10448
+ }
10449
+ //#endregion
9953
10450
  //#region src/runtime/npmPlugin/service/dependencies.ts
9954
10451
  const DEFAULT_NPM_STRATEGY = "explicit";
9955
10452
  function dedupeDependencies(dependencies) {
@@ -10124,10 +10621,10 @@ function collectResolverPlugins(config) {
10124
10621
  return (Array.isArray(config.plugins) ? config.plugins : config.plugins ? [config.plugins] : []).filter((plugin) => !isInternalPlugin(plugin));
10125
10622
  }
10126
10623
  async function transformVueSource(code, id, config) {
10127
- const { descriptor, errors } = parse$1(code, { filename: id });
10624
+ const { descriptor, errors } = await readAndParseSfc(id, { source: code });
10128
10625
  if (errors.length) throw errors[0];
10129
- const blocks = [descriptor.script, descriptor.scriptSetup].filter((block) => block?.content);
10130
- const source = blocks.map((block) => block.content).join("\n") || "export default {}";
10626
+ const blocks = [descriptor.script, descriptor.scriptSetup].filter((block) => block?.content || block?.src);
10627
+ const source = blocks.map((block) => block.src ? `import ${JSON.stringify(block.src)};` : block.content).join("\n") || "export default {}";
10131
10628
  const lang = blocks.some((block) => block?.lang === "tsx") ? "tsx" : blocks.some((block) => block?.lang === "ts") ? "ts" : "js";
10132
10629
  return await transformWithOxc(source, id, {
10133
10630
  lang,
@@ -10151,7 +10648,18 @@ function createProviderPlugin(ctx, config, onChange) {
10151
10648
  return {
10152
10649
  name: "weapp-vite:module-graph-provider",
10153
10650
  enforce: "pre",
10651
+ config() {
10652
+ return { resolve: { alias: [{
10653
+ find: WEVU_AUTO_ROUTES_MODULE_ID$1,
10654
+ replacement: WEVU_AUTO_ROUTES_VIRTUAL_MODULE_ID$1
10655
+ }, {
10656
+ find: AUTO_ROUTES_ID$1,
10657
+ replacement: VIRTUAL_MODULE_ID
10658
+ }] } };
10659
+ },
10154
10660
  async resolveId(id, importer) {
10661
+ const autoRoutesId = resolveAutoRoutesVirtualId(id);
10662
+ if (autoRoutesId) return autoRoutesId;
10155
10663
  const virtualId = resolveVirtualModuleId(id);
10156
10664
  if (virtualId) return virtualId;
10157
10665
  if (parseSidecarSourceRequest(id)) return id;
@@ -10165,6 +10673,9 @@ function createProviderPlugin(ctx, config, onChange) {
10165
10673
  return null;
10166
10674
  },
10167
10675
  load(id) {
10676
+ const autoRoutesId = resolveAutoRoutesVirtualId(id);
10677
+ const service = ctx.autoRoutesService;
10678
+ if (autoRoutesId && service) return service.ensureFresh().then(() => autoRoutesId === WEVU_AUTO_ROUTES_RESOLVED_MODULE_ID$1 ? service.getNamedModuleCode() : service.getModuleCode());
10168
10679
  if (id.startsWith(DEV_EXTERNAL_PREFIX)) return "export default {}";
10169
10680
  const logicalEntry = parseLogicalEntryId(id);
10170
10681
  if (logicalEntry) return createLogicalEntryModuleCode(logicalEntry, ctx.moduleGraphService.getEntryDependencies(logicalEntry.sourceId));
@@ -10292,7 +10803,7 @@ async function collectVueStyleScriptChanges(ctx, filename, configService) {
10292
10803
  const changedEntries = /* @__PURE__ */ new Set();
10293
10804
  for (const [entryId, bindings] of ctx.runtimeState.build.hmr.vueEntryStyleBindings) {
10294
10805
  if (!bindings.sources.some((source) => normalizeFsResolvedId(source) === filename)) continue;
10295
- const { descriptor } = await readAndParseSfc(entryId, createReadAndParseSfcOptions(ctx.moduleGraphService, configService));
10806
+ const { descriptor } = await readAndParseSfc$1(entryId, createReadAndParseSfcOptions(ctx.moduleGraphService, configService));
10296
10807
  if (!hasSameCssVars(bindings.expressions, descriptor.cssVars)) changedEntries.add(entryId);
10297
10808
  }
10298
10809
  return changedEntries;
@@ -11476,9 +11987,18 @@ function createRuntimeState() {
11476
11987
  },
11477
11988
  autoRoutes: {
11478
11989
  routes: emptyAutoRoutesSnapshot,
11990
+ namedRoutes: [],
11479
11991
  serialized: emptyAutoRoutesArtifacts.serialized,
11480
11992
  moduleCode: emptyAutoRoutesArtifacts.moduleCode,
11993
+ namedModuleCode: emptyAutoRoutesArtifacts.namedModuleCode,
11994
+ signature: emptyAutoRoutesArtifacts.signature,
11995
+ topologyKey: "",
11481
11996
  typedDefinition: "",
11997
+ pageDeclarationDependencies: /* @__PURE__ */ new Map(),
11998
+ pageDeclarationFingerprints: /* @__PURE__ */ new Map(),
11999
+ usesOpaquePageDeclarationResolver: false,
12000
+ pageSourceFiles: /* @__PURE__ */ new Set(),
12001
+ namedRouteSourceFiles: /* @__PURE__ */ new Set(),
11482
12002
  watchFiles: /* @__PURE__ */ new Set(),
11483
12003
  watchDirs: /* @__PURE__ */ new Set(),
11484
12004
  dirty: true,
@@ -11528,6 +12048,7 @@ function createRuntimeState() {
11528
12048
  lastHmrEntryIds: /* @__PURE__ */ new Set(),
11529
12049
  lastEmittedEntryIds: /* @__PURE__ */ new Set(),
11530
12050
  lastEmittedChunkFileNames: /* @__PURE__ */ new Set(),
12051
+ forceEmitUnchangedChunks: true,
11531
12052
  sharedChunkSourceModuleIds: /* @__PURE__ */ new Set(),
11532
12053
  recentProfiles: [],
11533
12054
  profile: {}
@@ -11594,18 +12115,7 @@ function resetRuntimeStateForFreshBuild(runtimeState) {
11594
12115
  runtimeState.glassEasel.diagnostics.clear();
11595
12116
  runtimeState.glassEasel.warnedDiagnostics.clear();
11596
12117
  runtimeState.glassEasel.silent = false;
11597
- const autoRoutes = runtimeState.autoRoutes;
11598
- autoRoutes.routes = fresh.autoRoutes.routes;
11599
- autoRoutes.serialized = fresh.autoRoutes.serialized;
11600
- autoRoutes.moduleCode = fresh.autoRoutes.moduleCode;
11601
- autoRoutes.typedDefinition = fresh.autoRoutes.typedDefinition;
11602
- autoRoutes.watchFiles.clear();
11603
- autoRoutes.watchDirs.clear();
11604
- autoRoutes.dirty = fresh.autoRoutes.dirty;
11605
- autoRoutes.initialized = fresh.autoRoutes.initialized;
11606
- autoRoutes.candidates.clear();
11607
- autoRoutes.needsFullRescan = fresh.autoRoutes.needsFullRescan;
11608
- autoRoutes.loadingAppConfig = fresh.autoRoutes.loadingAppConfig;
12118
+ Object.assign(runtimeState.autoRoutes, fresh.autoRoutes);
11609
12119
  const autoImport = runtimeState.autoImport;
11610
12120
  autoImport.registry.clear();
11611
12121
  autoImport.normalizedLocalComponents.clear();
@@ -13258,6 +13768,15 @@ function normalizeModuleId(id) {
13258
13768
  stripLeadingNullByte: true
13259
13769
  }).replaceAll("\\", "/");
13260
13770
  }
13771
+ function isWevuOwnedModuleId(id) {
13772
+ if (WEVU_RUNTIME_MODULE_IDS.includes(id)) return true;
13773
+ const normalized = normalizeModuleId(id);
13774
+ const workspaceIndex = normalized.lastIndexOf("/packages-runtime/wevu/");
13775
+ if (workspaceIndex >= 0) return !normalized.slice(workspaceIndex + 23).split("/").includes("node_modules");
13776
+ const nodeModulesIndex = normalized.lastIndexOf("/node_modules/");
13777
+ if (nodeModulesIndex < 0) return false;
13778
+ return normalized.slice(nodeModulesIndex + 14).split("/", 1)[0] === "wevu";
13779
+ }
13261
13780
  function resolveWevuPreservedModulePath(id) {
13262
13781
  const normalized = normalizeModuleId(id);
13263
13782
  const sourceMarker = "/packages-runtime/wevu/src/";
@@ -13316,6 +13835,7 @@ const REG_COMMONJS_HELPERS = /commonjsHelpers\.js$/;
13316
13835
  const REG_REQUEST_GLOBAL_RUNTIME_VENDOR_ID = /(?:^|[/\\])(?:@wevu[/\\]web-apis|web-apis[/\\]dist[/\\]index\.(?:m?js|cjs)|weapp-vite[/\\](?:dist[/\\]web-apis\.mjs|src[/\\](?:webApis\.ts|runtime[/\\]webApis[/\\]index\.ts)))(?:$|[?#])/;
13317
13836
  const REG_WEAPP_VITE_RUNTIME_VENDOR_ID = /(?:^|[/\\])weapp-vite[/\\](?:dist[/\\]runtime\.mjs|src[/\\]plugins[/\\]vue[/\\]runtime\.ts)(?:$|[?#])/;
13318
13837
  const REG_HASHED_DIST_CHUNK_ID = /(?:^|[/\\])dist[/\\](?:dev[/\\])?([^/\\-]+)-([\w-]{6,})\.(?:m?js|cjs)(?:$|[?#])/;
13838
+ const REG_WEVU_RUNTIME_SUPPORT_ID = /(?:^|\/)@weapp-core\/(?:constants|shared)\/dist\//;
13319
13839
  const STABLE_HASHED_DIST_CHUNK_PRIORITY = ["src"];
13320
13840
  const STABLE_HASHED_DIST_CHUNK_PRIORITY_BY_PACKAGE = { wevu: [
13321
13841
  "index",
@@ -13443,14 +13963,24 @@ function isWeappViteRuntimeModuleId(id) {
13443
13963
  REG_WEAPP_VITE_RUNTIME_VENDOR_ID.lastIndex = 0;
13444
13964
  return REG_WEAPP_VITE_RUNTIME_VENDOR_ID.test(cleanedAbsoluteId);
13445
13965
  }
13966
+ function isPackagedRuntimeModuleId(id) {
13967
+ const cleanedAbsoluteId = normalizeSharedPathCandidate(id);
13968
+ REG_NODE_MODULES_DIR.lastIndex = 0;
13969
+ return REG_NODE_MODULES_DIR.test(cleanedAbsoluteId) || Boolean(resolveDistChunkPackageToken(cleanedAbsoluteId));
13970
+ }
13971
+ function isWevuRuntimeSupportModuleId(id) {
13972
+ return REG_WEVU_RUNTIME_SUPPORT_ID.test(normalizeSharedPathCandidate(id));
13973
+ }
13446
13974
  function resolveStableHashedDistChunkFileName(chunk) {
13447
13975
  const candidateIds = [chunk.facadeModuleId, ...chunk.moduleIds ?? []].filter((id) => typeof id === "string");
13448
13976
  const matchedChunks = [];
13449
13977
  let facadeMatchedChunk;
13450
- for (const id of candidateIds) {
13451
- const fileName = resolveWevuStableVendorFileName(id);
13452
- if (fileName) return fileName;
13453
- }
13978
+ const wevuOwnedCandidates = candidateIds.map((id) => isWevuOwnedModuleId(id));
13979
+ const hasWevuOwnedCandidate = wevuOwnedCandidates.some(Boolean);
13980
+ const hasOtherPackagedCandidate = candidateIds.some((id, index) => !wevuOwnedCandidates[index] && !isWevuRuntimeSupportModuleId(id) && isPackagedRuntimeModuleId(id));
13981
+ if (hasWevuOwnedCandidate && hasOtherPackagedCandidate) return "weapp-vendors/common.js";
13982
+ const firstWevuVendorFileName = candidateIds.map((id) => resolveWevuStableVendorFileName(id)).find((fileName) => Boolean(fileName));
13983
+ if (firstWevuVendorFileName) return firstWevuVendorFileName;
13454
13984
  for (const id of candidateIds) {
13455
13985
  if (isWeappViteRuntimeModuleId(id)) return "weapp-vendors/weapp-vite-runtime.js";
13456
13986
  const cleanedAbsoluteId = normalizeSharedPathCandidate(id);
@@ -18842,7 +19372,7 @@ async function applyScriptSetupUsingComponents(options) {
18842
19372
  const { pluginCtx, vueEntryPath, source, templatePath, json, configService, wxmlService, reExportResolutionCache, externalComponentEntryMap } = options;
18843
19373
  try {
18844
19374
  if (source !== void 0 && !hasTemplateComponentTagHint(source)) return;
18845
- const { descriptor, errors } = await readAndParseSfc(vueEntryPath, { ...createReadAndParseSfcOptions(pluginCtx, configService, source === void 0 ? void 0 : { source }) });
19375
+ const { descriptor, errors } = await readAndParseSfc$1(vueEntryPath, { ...createReadAndParseSfcOptions(pluginCtx, configService, source === void 0 ? void 0 : { source }) });
18846
19376
  if (!errors?.length && descriptor?.template && !templatePath) {
18847
19377
  const tags = collectVueTemplateAutoImportTags(descriptor.template.content, vueEntryPath);
18848
19378
  if (tags.size) {
@@ -20194,7 +20724,7 @@ async function syncManagedTsconfigSupportFiles(ctx) {
20194
20724
  };
20195
20725
  }
20196
20726
  async function syncAutoRoutesSupportFiles(ctx) {
20197
- if (ctx.autoRoutesService?.isEnabled()) await ctx.autoRoutesService.ensureFresh();
20727
+ await ctx.autoRoutesService?.ensureFresh();
20198
20728
  }
20199
20729
  async function syncAutoImportSupportFiles(ctx, syncAutoImport, configService) {
20200
20730
  const autoImportConfig = syncAutoImport ? getAutoImportConfig(configService) : void 0;
@@ -20640,10 +21170,24 @@ async function cleanOutputs(configService) {
20640
21170
  //#endregion
20641
21171
  //#region src/runtime/buildPlugin/snapshotSources.ts
20642
21172
  /** 一次性 snapshot 不经过 watchChange,构建前必须刷新整个批次的真实源状态。 */
20643
- async function refreshSnapshotSources(ctx, files) {
21173
+ async function refreshSnapshotSources(ctx, files, emittedRouteSignature) {
20644
21174
  const changedFiles = new Set(Array.from(files, (file) => normalizeFsResolvedId(file)));
20645
21175
  for (const file of changedFiles) invalidateFileCache(file);
20646
- for (const file of changedFiles) if (isTemplate(file)) await ctx.wxmlService?.scan(file);
21176
+ for (const file of changedFiles) {
21177
+ await ctx.autoRoutesService?.handleFileChange(file);
21178
+ if (isTemplate(file)) await ctx.wxmlService?.scan(file);
21179
+ }
21180
+ const routeSignature = ctx.autoRoutesService?.getSignature();
21181
+ const routeDependentEntries = /* @__PURE__ */ new Set();
21182
+ if (emittedRouteSignature !== routeSignature) for (const id of [RESOLVED_VIRTUAL_ID, WEVU_AUTO_ROUTES_RESOLVED_MODULE_ID]) {
21183
+ invalidateFileCache(id);
21184
+ ctx.moduleGraphService.recordChangedFile(id, "update");
21185
+ for (const entry of ctx.moduleGraphService.invalidate(id)) routeDependentEntries.add(entry);
21186
+ }
21187
+ return {
21188
+ routeSignature,
21189
+ routeDependentEntries
21190
+ };
20647
21191
  }
20648
21192
  //#endregion
20649
21193
  //#region src/runtime/buildPlugin/touchAppWxss.ts
@@ -21585,6 +22129,7 @@ function createBuildService(ctx) {
21585
22129
  let pendingSnapshotBatch;
21586
22130
  let failedSnapshotReasons = [];
21587
22131
  let snapshotBatchTimer;
22132
+ let emittedAutoRoutesSignature;
21588
22133
  const devBuildWatcher = target === "app" ? createDevBuildWatcher() : void 0;
21589
22134
  function markSnapshotEntriesFullDirty() {
21590
22135
  for (const entryId of ctx.runtimeState.build.hmr.resolvedEntryMap.keys()) {
@@ -21645,7 +22190,9 @@ function createBuildService(ctx) {
21645
22190
  recordHmrProfileDuration(ctx.runtimeState.build.hmr.profile, "snapshotResolveMs", performance.now() - snapshotResolveStartedAt);
21646
22191
  const snapshotBuildStartedAt = performance.now();
21647
22192
  const requiresFullRescan = batchReasons.some((batchReason) => batchReason.forceFullRescan || batchReason.event === "create" || batchReason.event === "delete");
21648
- await refreshSnapshotSources(ctx, batchReasons.flatMap((batchReason) => batchReason.file ? [batchReason.file] : []));
22193
+ const { routeSignature, routeDependentEntries } = await refreshSnapshotSources(ctx, batchReasons.flatMap((batchReason) => batchReason.file ? [batchReason.file] : []), emittedAutoRoutesSignature);
22194
+ for (const entryId of graphAffectedEntries) routeDependentEntries.delete(entryId);
22195
+ for (const entryId of routeDependentEntries) graphAffectedEntries.add(entryId);
21649
22196
  const styleScriptChanges = /* @__PURE__ */ new Set();
21650
22197
  for (const batchReason of batchReasons) {
21651
22198
  if (!batchReason.file) continue;
@@ -21657,7 +22204,7 @@ function createBuildService(ctx) {
21657
22204
  if (!requiresFullRescan && graphAffectedEntries.size) {
21658
22205
  const dirtyReasons = batchReasons.map(resolveSnapshotDirtyReason);
21659
22206
  const dirtyReason = dirtyReasons.includes("direct") ? "direct" : dirtyReasons.includes("dependency") ? "dependency" : "metadata";
21660
- for (const entryId of graphAffectedEntries) if (ctx.runtimeState.build.hmr.resolvedEntryMap.has(entryId)) markSnapshotEntryDirty(entryId, reason, styleScriptChanges.has(entryId) ? "direct" : dirtyReason);
22207
+ for (const entryId of graphAffectedEntries) if (ctx.runtimeState.build.hmr.resolvedEntryMap.has(entryId)) markSnapshotEntryDirty(entryId, reason, styleScriptChanges.has(entryId) ? "direct" : routeDependentEntries.has(entryId) ? "dependency" : dirtyReason);
21661
22208
  const summaryCounts = /* @__PURE__ */ new Map();
21662
22209
  for (const batchReason of batchReasons) {
21663
22210
  if (!batchReason.file) continue;
@@ -21669,6 +22216,7 @@ function createBuildService(ctx) {
21669
22216
  try {
21670
22217
  devBuildWatcher?.emitEvent({ code: "START" });
21671
22218
  await build(snapshotBuildOptions);
22219
+ emittedAutoRoutesSignature = routeSignature;
21672
22220
  devBuildWatcher?.emitEvent({ code: "END" });
21673
22221
  } catch (error) {
21674
22222
  devBuildWatcher?.emitEvent({
@@ -21695,6 +22243,7 @@ function createBuildService(ctx) {
21695
22243
  emptyOutDir: shouldCleanOutputs(configService, "rebuild")
21696
22244
  }
21697
22245
  });
22246
+ emittedAutoRoutesSignature = routeSignature;
21698
22247
  devBuildWatcher?.emitEvent({ code: "END" });
21699
22248
  return "snapshot";
21700
22249
  } catch (error) {
@@ -21759,7 +22308,10 @@ function createBuildService(ctx) {
21759
22308
  const watcherPromise = target === "app" ? (async () => {
21760
22309
  devBuildWatcher.emitEvent({ code: "START" });
21761
22310
  try {
22311
+ await ctx.autoRoutesService?.ensureFresh();
22312
+ const routeSignature = ctx.autoRoutesService?.getSignature();
21762
22313
  await build(snapshotBuildOptions);
22314
+ emittedAutoRoutesSignature = routeSignature;
21763
22315
  devBuildWatcher.emitEvent({ code: "END" });
21764
22316
  return devBuildWatcher.watcher;
21765
22317
  } catch (error) {
@@ -22160,34 +22712,6 @@ function resolveBuiltinPackageAliases(options = {}) {
22160
22712
  return aliases;
22161
22713
  }
22162
22714
  //#endregion
22163
- //#region src/runtime/config/internal/alias.ts
22164
- function normalizeAliasOptions(alias) {
22165
- if (!alias) return [];
22166
- if (Array.isArray(alias)) return alias.filter((entry) => {
22167
- return Boolean(entry && typeof entry === "object" && "find" in entry && "replacement" in entry);
22168
- });
22169
- return Object.entries(alias).map(([find, replacement]) => {
22170
- return {
22171
- find,
22172
- replacement
22173
- };
22174
- });
22175
- }
22176
- function createAliasManager(oxcAlias, defaultBuiltinAliases) {
22177
- function injectBuiltinAliases(config, builtinAliases = defaultBuiltinAliases) {
22178
- const resolve = config.resolve ?? (config.resolve = {});
22179
- const aliasArray = normalizeAliasOptions(resolve.alias);
22180
- if (!aliasArray.some((entry) => {
22181
- return entry.find instanceof RegExp && entry.find.source === oxcAlias.find.source;
22182
- })) aliasArray.unshift(oxcAlias);
22183
- for (const builtin of builtinAliases) if (!aliasArray.some((entry) => {
22184
- return typeof entry.find === "string" && entry.find === builtin.find;
22185
- })) aliasArray.unshift(builtin);
22186
- resolve.alias = aliasArray;
22187
- }
22188
- return { injectBuiltinAliases };
22189
- }
22190
- //#endregion
22191
22715
  //#region src/runtime/config/enhance.ts
22192
22716
  const enhanceKeys = [
22193
22717
  "wxml",
@@ -24347,89 +24871,6 @@ function asset(ctx) {
24347
24871
  buildTarget: ctx.currentBuildTarget ?? "app"
24348
24872
  })];
24349
24873
  }
24350
- const RESOLVED_VIRTUAL_ID = "\0weapp-vite:auto-routes";
24351
- /**
24352
- * 判断当前是否应按 watch 模式为 auto-routes 注册依赖文件。
24353
- */
24354
- function isAutoRoutesWatchMode(configService) {
24355
- return Boolean(configService?.isDev || configService?.inlineConfig?.build?.watch);
24356
- }
24357
- /**
24358
- * 合并 service 与 matcher 提供的监听目录,并去重保留顺序。
24359
- */
24360
- function collectAutoRoutesWatchDirs(watchDirectories, matcherWatchRoots) {
24361
- const watchDirs = /* @__PURE__ */ new Set();
24362
- for (const dir of watchDirectories) watchDirs.add(dir);
24363
- for (const dir of matcherWatchRoots) watchDirs.add(dir);
24364
- return [...watchDirs];
24365
- }
24366
- /**
24367
- * 过滤出真正需要交给 auto-routes watcher 处理的路由 Vue 文件。
24368
- */
24369
- function isAutoRoutesWatchFile(filePath, allowedExtensions, isPagesRelatedPath) {
24370
- return !isAutoRoutesGeneratedFileName(path.basename(filePath)) && allowedExtensions.has(path.extname(filePath)) && isPagesRelatedPath(filePath);
24371
- }
24372
- /**
24373
- * 判断是否满足 auto-routes sidecar watcher 的启动前置条件。
24374
- */
24375
- function shouldStartAutoRoutesWatcher(options) {
24376
- if (options.routeWatcherStarted) return false;
24377
- if (!options.isDev) return false;
24378
- if (!options.autoRoutesEnabled || !options.autoRoutesWatch || !options.serviceEnabled) return false;
24379
- return options.watchDirsLength > 0;
24380
- }
24381
- /**
24382
- * 生成 sidecar watcher map 使用的关闭句柄。
24383
- */
24384
- function createAutoRoutesSidecarWatcher(watcher) {
24385
- return { close: async () => {
24386
- await watcher.close();
24387
- } };
24388
- }
24389
- /**
24390
- * 向插件上下文注册 auto-routes 相关 watch 目标,忽略单个 addWatchFile 失败。
24391
- */
24392
- function addAutoRoutesWatchTargets(pluginCtx, targets) {
24393
- for (const file of targets.files) try {
24394
- pluginCtx.addWatchFile?.(normalizeWatchPath(file));
24395
- } catch {}
24396
- for (const dir of targets.directories) try {
24397
- pluginCtx.addWatchFile?.(normalizeWatchPath(dir));
24398
- } catch {}
24399
- }
24400
- /**
24401
- * 统一解析 auto-routes 虚拟模块与 alias 入口的命中关系。
24402
- */
24403
- function resolveAutoRoutesVirtualId(id, aliasTargets) {
24404
- if (id === "weapp-vite/auto-routes" || id === "virtual:weapp-vite-auto-routes" || id === "\0weapp-vite:auto-routes") return RESOLVED_VIRTUAL_ID;
24405
- return aliasTargets.has(id) ? RESOLVED_VIRTUAL_ID : null;
24406
- }
24407
- /**
24408
- * 将 create/delete 这类结构性变化映射为 auto-routes 的全量重扫语义。
24409
- */
24410
- function resolveAutoRoutesWatchChangeEvent(event) {
24411
- if (event === "create" || event === "delete") return "rename";
24412
- }
24413
- /**
24414
- * 判断某次热更新是否需要触发 auto-routes 虚拟模块失效。
24415
- */
24416
- function resolveAutoRoutesHotUpdateAction(command, options) {
24417
- if (command === "serve") return options.isRouteFile ? {
24418
- shouldHandle: true,
24419
- shouldUpdateRouteFile: true
24420
- } : {
24421
- shouldHandle: false,
24422
- shouldUpdateRouteFile: false
24423
- };
24424
- if (options.isRouteFile || options.isPagesRelatedPath) return {
24425
- shouldHandle: true,
24426
- shouldUpdateRouteFile: false
24427
- };
24428
- return {
24429
- shouldHandle: false,
24430
- shouldUpdateRouteFile: false
24431
- };
24432
- }
24433
24874
  //#endregion
24434
24875
  //#region src/plugins/core/lifecycle/autoRoutesTopology.ts
24435
24876
  /**
@@ -24441,31 +24882,95 @@ function markAppEntryForAutoRoutesTopology(ctx, options) {
24441
24882
  invalidateFileCache("weapp-vite/auto-routes");
24442
24883
  invalidateFileCache("virtual:weapp-vite-auto-routes");
24443
24884
  invalidateFileCache("\0weapp-vite:auto-routes");
24885
+ invalidateFileCache(WEVU_AUTO_ROUTES_MODULE_ID);
24886
+ invalidateFileCache(WEVU_AUTO_ROUTES_VIRTUAL_MODULE_ID);
24887
+ invalidateFileCache(WEVU_AUTO_ROUTES_RESOLVED_MODULE_ID);
24444
24888
  for (const target of resolveAutoRoutesAliasTargets(ctx.configService?.packageInfo?.rootPath)) invalidateFileCache(normalizeFsResolvedId(target));
24445
- options.loadEntry?.invalidateResolveCache?.();
24889
+ const loadEntry = options.loadEntry;
24890
+ if (loadEntry && typeof loadEntry === "object" && "invalidateResolveCache" in loadEntry && typeof loadEntry.invalidateResolveCache === "function") loadEntry.invalidateResolveCache();
24446
24891
  ctx.runtimeState.build.hmr.appEntryAutoRoutesSignature = void 0;
24447
24892
  if (!appEntryId || !options.resolvedEntryMap.has(appEntryId)) return false;
24448
24893
  options.markEntryDirty(appEntryId, "direct");
24449
24894
  return true;
24450
24895
  }
24451
24896
  //#endregion
24897
+ //#region src/plugins/utils/parse.ts
24898
+ function hasOwn$2(source, key) {
24899
+ return Object.prototype.hasOwnProperty.call(source, key);
24900
+ }
24901
+ /**
24902
+ * 参考:https://github.com/tailwindlabs/tailwindcss/blob/main/packages/%40tailwindcss-vite/src/index.ts
24903
+ * 解析请求ID,返回包含文件名和查询参数的对象。
24904
+ * 如果查询参数中包含'wxss',则将其值设置为true。
24905
+ * @param id - 请求ID,格式为'filename?query'
24906
+ * @returns 解析后的请求响应对象
24907
+ */
24908
+ function parseRequest(id) {
24909
+ const [filename, rawQuery] = id.split(`?`, 2);
24910
+ const query = {};
24911
+ if (rawQuery) {
24912
+ const params = new URLSearchParams(rawQuery);
24913
+ for (const [key, value] of params.entries()) query[key] = value;
24914
+ if (hasOwn$2(query, "wxss")) query.wxss = true;
24915
+ }
24916
+ return {
24917
+ filename,
24918
+ query
24919
+ };
24920
+ }
24921
+ /**
24922
+ * 根据请求响应获取 CSS 文件的真实路径。
24923
+ * 如果请求中包含 wxss 查询参数,则将文件扩展名更改为 'wxss'。
24924
+ * @param res - 解析请求的响应对象,包含文件名和查询参数。
24925
+ * @returns 返回文件的真实路径。
24926
+ */
24927
+ function getCssRealPath(res) {
24928
+ if (typeof res.query.nativeStyle === "string" && res.query.nativeStyle) return changeFileExtension(res.filename, res.query.nativeStyle);
24929
+ if (res.query.wxss) return changeFileExtension(res.filename, "wxss");
24930
+ return res.filename;
24931
+ }
24932
+ //#endregion
24452
24933
  //#region src/plugins/autoRoutes.ts
24453
24934
  /**
24454
24935
  * 路由文件监听器的唯一标识,用于在 sidecarWatcherMap 中注册。
24455
24936
  */
24456
- const ROUTE_WATCHER_KEY = "__auto-routes-vue-watcher__";
24457
- function createAutoRoutesPlugin(ctx) {
24458
- const service = ctx.autoRoutesService;
24937
+ const ROUTE_WATCHER_KEY = "__auto-routes-source-watcher__";
24938
+ const AUTO_ROUTES_RESOLVED_IDS = [RESOLVED_VIRTUAL_ID, WEVU_AUTO_ROUTES_RESOLVED_MODULE_ID$1];
24939
+ const AUTO_ROUTES_VUE_SUFFIXES = vueExtensions.map((extension) => `.${extension}`);
24940
+ function isAutoRoutesWatcherController(watcher) {
24941
+ return Boolean(watcher && typeof watcher === "object" && "addWatchTargets" in watcher && typeof watcher.addWatchTargets === "function" && "close" in watcher && typeof watcher.close === "function" && "subscribers" in watcher && watcher.subscribers instanceof Map);
24942
+ }
24943
+ /**
24944
+ * 这里只排除非脚本 Vue 子资源;外部脚本是否属于页面声明由 service 的依赖所有权判定。
24945
+ */
24946
+ function isPageScriptTransformRequest(id, normalizedId) {
24947
+ const query = id.includes("?") ? parseRequest(id).query : void 0;
24948
+ if (AUTO_ROUTES_VUE_SUFFIXES.some((suffix) => normalizedId.endsWith(suffix))) return query?.type === "script";
24949
+ return !query || !("vue" in query) || query.type === "script";
24950
+ }
24951
+ function createAutoRoutesPlugin(ctx, service) {
24459
24952
  let resolvedConfig;
24460
24953
  let devServer;
24954
+ let servedRouteSignature;
24461
24955
  const autoRoutesAliasTargets = /* @__PURE__ */ new Set();
24462
24956
  const autoRoutesTopologyDirtyEntries = /* @__PURE__ */ new Set();
24463
- let routeWatcherStarted = false;
24957
+ const watcherSubscriber = {
24958
+ topologyDirtyEntries: autoRoutesTopologyDirtyEntries,
24959
+ get devServer() {
24960
+ return devServer;
24961
+ }
24962
+ };
24963
+ function registerPageDeclarationSourceResolver(pluginContext) {
24964
+ service.setPageDeclarationSourceResolver(typeof pluginContext.resolve === "function" ? async (source, importer) => {
24965
+ return (await pluginContext.resolve(source, importer, { skipSelf: true }))?.id;
24966
+ } : void 0);
24967
+ }
24464
24968
  const refreshAutoRoutesAliasTargets = () => {
24465
24969
  autoRoutesAliasTargets.clear();
24466
24970
  for (const target of resolveAutoRoutesAliasTargets(ctx.configService?.packageInfo?.rootPath)) autoRoutesAliasTargets.add(target);
24467
24971
  };
24468
24972
  function isPagesRelatedPath(id) {
24973
+ if (service.isPageDeclarationSource(id)) return true;
24469
24974
  const configService = ctx.configService;
24470
24975
  if (!configService) return false;
24471
24976
  const { autoRoutesConfig, subPackageRoots } = resolveAutoRoutesMatcherContext(ctx);
@@ -24477,37 +24982,14 @@ function createAutoRoutesPlugin(ctx) {
24477
24982
  subPackageRoots
24478
24983
  });
24479
24984
  }
24480
- /**
24481
- * 启动 chokidar 监听 pages 目录下的路由文件增删。
24482
- * Rolldown 的 watcher 不会为新建文件触发 watchChange,
24483
- * 因此需要独立的文件监听来补偿。
24484
- *
24485
- * 注意:chokidar v5 在 macOS 上使用 glob 模式时无法检测新建文件,
24486
- * 必须直接监听目录,然后在事件回调中按扩展名过滤。
24487
- *
24488
- * 生命周期:watcher 注册到 sidecarWatcherMap,由 watcherService.closeAll()
24489
- * 统一回收,不在 closeBundle 中销毁(build watch 模式下 closeBundle 每次
24490
- * 重编译都会触发,提前销毁会导致后续文件变更无法感知)。
24491
- */
24492
- function invalidateAutoRoutesVirtualModule() {
24493
- const server = devServer;
24494
- const virtualModule = server?.moduleGraph.getModuleById(RESOLVED_VIRTUAL_ID);
24495
- if (!virtualModule || !server) return;
24496
- const seen = /* @__PURE__ */ new Set();
24497
- const invalidateModuleWithImporters = (module) => {
24498
- if (seen.has(module)) return;
24499
- seen.add(module);
24500
- server.moduleGraph.invalidateModule(module);
24501
- for (const importer of module.importers) invalidateModuleWithImporters(importer);
24502
- };
24503
- invalidateModuleWithImporters(virtualModule);
24504
- }
24505
- function markAutoRoutesTopologyDirty() {
24985
+ function markAutoRoutesTopologyDirty(controller) {
24986
+ const appEntry = ctx.scanService?.appEntry?.path;
24987
+ if (appEntry) controller.subscribers.get("web")?.topologyDirtyEntries.add(normalizeFsResolvedId(appEntry));
24506
24988
  return markAppEntryForAutoRoutesTopology(ctx, {
24507
24989
  resolvedEntryMap: ctx.runtimeState.build.hmr.resolvedEntryMap,
24508
24990
  markEntryDirty(entryId) {
24509
24991
  const hmr = ctx.runtimeState.build.hmr;
24510
- autoRoutesTopologyDirtyEntries.add(entryId);
24992
+ for (const subscriber of controller.subscribers.values()) subscriber.topologyDirtyEntries.add(entryId);
24511
24993
  hmr.dirtyEntrySet.add(entryId);
24512
24994
  hmr.dirtyEntryReasons.set(entryId, "direct");
24513
24995
  hmr.loadedEntrySet.delete(entryId);
@@ -24516,32 +24998,80 @@ function createAutoRoutesPlugin(ctx) {
24516
24998
  }
24517
24999
  });
24518
25000
  }
24519
- function notifyAppEntryChange() {
24520
- const appEntryPath = ctx.scanService?.appEntry?.path;
24521
- if (!appEntryPath || !devServer) return;
24522
- devServer.watcher.emit("change", appEntryPath);
24523
- }
24524
- async function handleRouteStructureChange(filePath, event) {
24525
- if (await service.handleFileChange(filePath, event)) {
24526
- invalidateAutoRoutesVirtualModule();
24527
- markAutoRoutesTopologyDirty();
24528
- notifyAppEntryChange();
25001
+ function reportRouteStructureChangeError(filePath, event, error, controller) {
25002
+ const action = event === "create" ? "新增" : "删除";
25003
+ const reason = error instanceof Error ? error.message : String(error);
25004
+ const routeError = /* @__PURE__ */ new Error(`[auto-routes:watch] ${action}路由文件 ${ctx.configService?.relativeCwd(filePath) ?? filePath} 处理失败:${reason}`);
25005
+ const servers = /* @__PURE__ */ new Set();
25006
+ for (const subscriber of controller.subscribers.values()) if (subscriber.devServer) servers.add(subscriber.devServer);
25007
+ if (servers.size === 0) {
25008
+ logger_default.error(routeError);
25009
+ return;
24529
25010
  }
25011
+ for (const server of servers) server.ws.send({
25012
+ type: "error",
25013
+ err: {
25014
+ message: routeError.message,
25015
+ stack: routeError.stack ?? routeError.message,
25016
+ id: filePath,
25017
+ plugin: "weapp-vite:auto-routes"
25018
+ }
25019
+ });
25020
+ }
25021
+ async function handleRouteStructureChange(filePath, event, controller) {
25022
+ const changedSource = normalizeFsResolvedId(filePath);
25023
+ const declarationOwners = new Set(service.getPageDeclarationOwners(changedSource));
25024
+ const didChangeRoutes = await service.handleFileChange(filePath, resolveAutoRoutesWatchChangeEvent(event));
25025
+ controller.addWatchTargets([...service.getWatchDirectories()]);
25026
+ if (!didChangeRoutes) return;
25027
+ for (const owner of service.getPageDeclarationOwners(changedSource)) declarationOwners.add(owner);
25028
+ const servers = /* @__PURE__ */ new Set();
25029
+ for (const subscriber of controller.subscribers.values()) if (subscriber.devServer) servers.add(subscriber.devServer);
25030
+ for (const server of servers) invalidateAutoRoutesVirtualModules(server, AUTO_ROUTES_RESOLVED_IDS);
25031
+ const appEntryPath = ctx.scanService?.appEntry?.path;
25032
+ markAutoRoutesTopologyDirty(controller);
25033
+ ctx.scanService?.markDirty();
25034
+ const notificationFiles = /* @__PURE__ */ new Set();
25035
+ for (const owner of declarationOwners) if (owner !== changedSource) notificationFiles.add(owner);
25036
+ if (appEntryPath) notificationFiles.add(appEntryPath);
25037
+ for (const server of servers) for (const file of notificationFiles) server.watcher.emit("change", file);
24530
25038
  }
25039
+ /**
25040
+ * 启动 chokidar 监听页面路由源文件及其外部声明依赖所在目录的增删。
25041
+ * Rolldown 的 watcher 不会为新建文件触发 watchChange,
25042
+ * 因此需要独立的文件监听来补偿。
25043
+ *
25044
+ * 注意:chokidar v5 在 macOS 上使用 glob 模式时无法检测新建文件,
25045
+ * 必须直接监听目录,然后在事件回调中按扩展名过滤。
25046
+ *
25047
+ * 生命周期:watcher 注册到 sidecarWatcherMap,由 watcherService.closeAll()
25048
+ * 统一回收,不在 closeBundle 中销毁(build watch 模式下 closeBundle 每次
25049
+ * 重编译都会触发,提前销毁会导致后续文件变更无法感知)。
25050
+ */
24531
25051
  function startRouteFileWatcher() {
24532
25052
  const configService = ctx.configService;
24533
25053
  if (!configService) return;
24534
25054
  const { autoRoutesConfig, matcher: resolvedMatcher } = resolveAutoRoutesMatcherContext(ctx);
24535
- const allowedExtensions = new Set(vueExtensions.map((ext) => `.${ext}`));
25055
+ const allowedExtensions = new Set([...vueExtensions, ...scriptExtensions].map((ext) => `.${ext}`));
24536
25056
  const watchDirs = collectAutoRoutesWatchDirs(service.getWatchDirectories(), resolvedMatcher.getWatchRoots(configService.absoluteSrcRoot));
24537
25057
  if (!shouldStartAutoRoutesWatcher({
24538
- routeWatcherStarted,
25058
+ routeWatcherStarted: false,
24539
25059
  isDev: configService.isDev,
24540
25060
  autoRoutesEnabled: autoRoutesConfig.enabled,
24541
25061
  autoRoutesWatch: autoRoutesConfig.watch,
24542
25062
  serviceEnabled: service.isEnabled(),
24543
25063
  watchDirsLength: watchDirs.length
24544
25064
  })) return;
25065
+ const subscriberId = resolvedConfig?.weappVite?.runtime ?? "miniprogram";
25066
+ const { sidecarWatcherMap } = ctx.runtimeState.watcher;
25067
+ const activeWatcher = sidecarWatcherMap.get(ROUTE_WATCHER_KEY);
25068
+ if (isAutoRoutesWatcherController(activeWatcher)) {
25069
+ activeWatcher.addWatchTargets(watchDirs);
25070
+ activeWatcher.subscribers.set(subscriberId, watcherSubscriber);
25071
+ return;
25072
+ }
25073
+ if (activeWatcher) return;
25074
+ const subscribers = /* @__PURE__ */ new Map([[subscriberId, watcherSubscriber]]);
24545
25075
  const watcher = chokidar.watch(watchDirs, createSidecarWatchOptions(configService, {
24546
25076
  ignoreInitial: true,
24547
25077
  persistent: true,
@@ -24550,23 +25080,43 @@ function createAutoRoutesPlugin(ctx) {
24550
25080
  pollInterval: 20
24551
25081
  }
24552
25082
  }));
25083
+ const sidecarWatcher = createAutoRoutesSidecarWatcher(watcher);
25084
+ const controller = {
25085
+ addWatchTargets(paths) {
25086
+ watcher.add(paths);
25087
+ },
25088
+ subscribers,
25089
+ async close() {
25090
+ if (sidecarWatcherMap.get(ROUTE_WATCHER_KEY) === controller) sidecarWatcherMap.delete(ROUTE_WATCHER_KEY);
25091
+ controller.subscribers.clear();
25092
+ await sidecarWatcher.close();
25093
+ }
25094
+ };
24553
25095
  watcher.on("add", (filePath) => {
24554
- if (!isAutoRoutesWatchFile(filePath, allowedExtensions, isPagesRelatedPath)) return;
25096
+ if (!isAutoRoutesWatchFile(filePath, allowedExtensions, isPagesRelatedPath, service.isPageDeclarationSource)) return;
24555
25097
  logger_default.info(`[auto-routes:watch] 新增路由文件 ${configService.relativeCwd(filePath)}`);
24556
- handleRouteStructureChange(filePath, "create");
25098
+ handleRouteStructureChange(filePath, "create", controller).catch((error) => {
25099
+ reportRouteStructureChangeError(filePath, "create", error, controller);
25100
+ });
24557
25101
  });
24558
25102
  watcher.on("unlink", (filePath) => {
24559
- if (!isAutoRoutesWatchFile(filePath, allowedExtensions, isPagesRelatedPath)) return;
25103
+ if (!isAutoRoutesWatchFile(filePath, allowedExtensions, isPagesRelatedPath, service.isPageDeclarationSource)) return;
24560
25104
  logger_default.info(`[auto-routes:watch] 删除路由文件 ${configService.relativeCwd(filePath)}`);
24561
- handleRouteStructureChange(filePath, "delete");
25105
+ handleRouteStructureChange(filePath, "delete", controller).catch((error) => {
25106
+ reportRouteStructureChangeError(filePath, "delete", error, controller);
25107
+ });
24562
25108
  });
24563
- const { sidecarWatcherMap } = ctx.runtimeState.watcher;
24564
- sidecarWatcherMap.set(ROUTE_WATCHER_KEY, createAutoRoutesSidecarWatcher(watcher));
24565
- routeWatcherStarted = true;
25109
+ sidecarWatcherMap.set(ROUTE_WATCHER_KEY, controller);
24566
25110
  }
24567
25111
  return {
24568
25112
  name: "weapp-vite:auto-routes",
24569
25113
  enforce: "pre",
25114
+ config() {
25115
+ return { resolve: { alias: [{
25116
+ find: WEVU_AUTO_ROUTES_MODULE_ID,
25117
+ replacement: WEVU_AUTO_ROUTES_VIRTUAL_MODULE_ID
25118
+ }] } };
25119
+ },
24570
25120
  configResolved(config) {
24571
25121
  resolvedConfig = config;
24572
25122
  refreshAutoRoutesAliasTargets();
@@ -24575,6 +25125,7 @@ function createAutoRoutesPlugin(ctx) {
24575
25125
  devServer = server;
24576
25126
  },
24577
25127
  buildStart() {
25128
+ registerPageDeclarationSourceResolver(this);
24578
25129
  refreshAutoRoutesAliasTargets();
24579
25130
  startRouteFileWatcher();
24580
25131
  },
@@ -24589,50 +25140,111 @@ function createAutoRoutesPlugin(ctx) {
24589
25140
  }
24590
25141
  },
24591
25142
  async load(id) {
24592
- if (resolveAutoRoutesVirtualId(id, autoRoutesAliasTargets) !== "\0weapp-vite:auto-routes") return null;
25143
+ const resolvedId = resolveAutoRoutesVirtualId(id, autoRoutesAliasTargets);
25144
+ if (!resolvedId) return null;
25145
+ registerPageDeclarationSourceResolver(this);
25146
+ if (resolvedId === WEVU_AUTO_ROUTES_RESOLVED_MODULE_ID$1 && !service.isEnabled()) this.error(`${WEVU_AUTO_ROUTES_MODULE_ID} 需要启用 weapp.autoRoutes。`);
24593
25147
  await service.ensureFresh();
24594
- if (isAutoRoutesWatchMode(ctx.configService)) addAutoRoutesWatchTargets(this, {
25148
+ if (isAutoRoutesWatchMode(ctx.configService)) addAutoRoutesWatchTargets(resolvedConfig?.command === "serve" ? { addWatchFile: (file) => devServer?.watcher.add(file) } : this, {
24595
25149
  files: service.getWatchFiles(),
24596
- directories: service.getWatchDirectories()
25150
+ directories: resolvedConfig?.command === "serve" ? [] : service.getWatchDirectories()
24597
25151
  });
24598
25152
  startRouteFileWatcher();
25153
+ if (resolvedConfig?.weappVite?.runtime === "web") servedRouteSignature ??= service.getSignature();
24599
25154
  return {
24600
- code: service.getModuleCode(),
25155
+ code: resolvedId === WEVU_AUTO_ROUTES_RESOLVED_MODULE_ID$1 ? service.getNamedModuleCode() : service.getModuleCode(),
24601
25156
  map: { mappings: "" }
24602
25157
  };
24603
25158
  },
25159
+ async transform(code, id) {
25160
+ if (!mayContainPageDeclaration(code)) return null;
25161
+ const normalizedId = normalizeFsResolvedId(id);
25162
+ if (!isPageScriptTransformRequest(id, normalizedId)) return null;
25163
+ registerPageDeclarationSourceResolver(this);
25164
+ await service.ensureFresh();
25165
+ startRouteFileWatcher();
25166
+ if (!service.isPageDeclarationSource(normalizedId)) return null;
25167
+ const stripped = stripPageDeclaration(code, id);
25168
+ return stripped ? {
25169
+ code: stripped.code,
25170
+ map: normalizeEncodedSourceMapLike(stripped.map)
25171
+ } : null;
25172
+ },
24604
25173
  shouldTransformCachedModule({ id }) {
24605
25174
  return autoRoutesTopologyDirtyEntries.delete(id) || void 0;
24606
25175
  },
24607
25176
  async watchChange(id, change) {
25177
+ registerPageDeclarationSourceResolver(this);
24608
25178
  const event = change?.event;
24609
25179
  if (service.isRouteFile(id)) {
24610
25180
  if (resolvedConfig?.command === "serve" && event === "update") return;
24611
- await service.handleFileChange(id, event);
25181
+ await service.handleFileChange(id, resolveAutoRoutesWatchChangeEvent(event) ?? event);
25182
+ startRouteFileWatcher();
24612
25183
  return;
24613
25184
  }
24614
25185
  if (!isPagesRelatedPath(id)) return;
24615
25186
  const resolvedEvent = resolveAutoRoutesWatchChangeEvent(event);
24616
- if (resolvedEvent) await service.handleFileChange(id, resolvedEvent);
25187
+ if (resolvedEvent) {
25188
+ await service.handleFileChange(id, resolvedEvent);
25189
+ startRouteFileWatcher();
25190
+ }
24617
25191
  },
24618
25192
  async handleHotUpdate(context) {
25193
+ const changedSource = normalizeFsResolvedId(context.file);
25194
+ const webRuntime = resolvedConfig?.weappVite?.runtime === "web";
25195
+ const topologyChanged = webRuntime && autoRoutesTopologyDirtyEntries.delete(changedSource);
25196
+ const declarationOwners = new Set(service.getPageDeclarationOwners(changedSource));
24619
25197
  const routeFile = service.isRouteFile(context.file);
24620
25198
  const hotUpdateAction = resolveAutoRoutesHotUpdateAction(resolvedConfig?.command, {
24621
25199
  isRouteFile: routeFile,
24622
25200
  isPagesRelatedPath: routeFile ? false : isPagesRelatedPath(context.file)
24623
25201
  });
24624
- if (!hotUpdateAction.shouldHandle) return;
25202
+ if (!hotUpdateAction.shouldHandle && !topologyChanged) return;
24625
25203
  let didChangeRoutes = false;
24626
- if (hotUpdateAction.shouldUpdateRouteFile) didChangeRoutes = await service.handleFileChange(context.file, "update");
24627
- if (resolvedConfig?.command === "serve" && routeFile && !didChangeRoutes) return;
24628
- const virtualModule = context.server.moduleGraph.getModuleById(RESOLVED_VIRTUAL_ID);
24629
- if (virtualModule) return [virtualModule];
24630
- return context.modules.filter((module) => module.id === RESOLVED_VIRTUAL_ID);
25204
+ if (hotUpdateAction.shouldUpdateRouteFile) {
25205
+ didChangeRoutes = await service.handleFileChange(context.file, "update");
25206
+ startRouteFileWatcher();
25207
+ for (const owner of service.getPageDeclarationOwners(changedSource)) declarationOwners.add(owner);
25208
+ }
25209
+ declarationOwners.delete(changedSource);
25210
+ if (resolvedConfig?.command === "serve" && routeFile && !didChangeRoutes && declarationOwners.size === 0) return;
25211
+ const signature = webRuntime ? service.getSignature() : void 0;
25212
+ const reloadRoutes = webRuntime && (topologyChanged || servedRouteSignature !== void 0 && signature !== servedRouteSignature);
25213
+ const modules = new Set(!webRuntime || reloadRoutes ? AUTO_ROUTES_RESOLVED_IDS.map((id) => context.server.moduleGraph.getModuleById(id)).filter((module) => Boolean(module)) : context.modules);
25214
+ for (const owner of declarationOwners) {
25215
+ const ownerModules = context.server.moduleGraph.getModulesByFile(owner);
25216
+ if (ownerModules) {
25217
+ for (const module of ownerModules) modules.add(module);
25218
+ continue;
25219
+ }
25220
+ const ownerModule = context.server.moduleGraph.getModuleById(owner);
25221
+ if (ownerModule) modules.add(ownerModule);
25222
+ }
25223
+ if (topologyChanged) for (const module of context.modules) modules.add(module);
25224
+ if (modules.size > 0) {
25225
+ if (reloadRoutes) {
25226
+ servedRouteSignature = signature;
25227
+ return collectAutoRoutesReloadModules(modules);
25228
+ }
25229
+ return [...modules];
25230
+ }
25231
+ return context.modules.filter((module) => {
25232
+ return module.id !== null && (AUTO_ROUTES_RESOLVED_IDS.includes(module.id) || declarationOwners.has(normalizeFsResolvedId(module.id)));
25233
+ });
25234
+ },
25235
+ async closeBundle() {
25236
+ if (resolvedConfig?.command !== "serve") return;
25237
+ const watcher = ctx.runtimeState.watcher.sidecarWatcherMap.get(ROUTE_WATCHER_KEY);
25238
+ const subscriberId = resolvedConfig.weappVite?.runtime ?? "miniprogram";
25239
+ if (!isAutoRoutesWatcherController(watcher) || watcher.subscribers.get(subscriberId) !== watcherSubscriber) return;
25240
+ watcher.subscribers.delete(subscriberId);
25241
+ if (watcher.subscribers.size === 0) await watcher.close();
24631
25242
  }
24632
25243
  };
24633
25244
  }
24634
25245
  function autoRoutes(ctx) {
24635
- return [createAutoRoutesPlugin(ctx)];
25246
+ if (!ctx.autoRoutesService || !ctx.configService) return [];
25247
+ return [createAutoRoutesPlugin(ctx, ctx.autoRoutesService)];
24636
25248
  }
24637
25249
  //#endregion
24638
25250
  //#region src/plugins/hooks/useLoadEntry/autoImport.ts
@@ -25130,13 +25742,24 @@ function findNativePageOptionsObject(ast) {
25130
25742
  return matched;
25131
25743
  }
25132
25744
  function stripDefinePageMetaCalls(ast) {
25745
+ const calls = new Set(collectPageMetaCallsFromPrograms({ script: ast }));
25133
25746
  let mutated = false;
25134
- traverse(ast, { ExpressionStatement(path) {
25135
- const expression = path.node.expression;
25136
- if (!t.isCallExpression(expression) || !t.isIdentifier(expression.callee, { name: "definePageMeta" })) return;
25137
- mutated = true;
25138
- path.remove();
25139
- } });
25747
+ traverse(ast, {
25748
+ ImportDeclaration(path) {
25749
+ if (path.node.source.value !== "wevu" || path.node.importKind === "type") return;
25750
+ const specifiers = path.node.specifiers.filter((specifier) => !t.isImportSpecifier(specifier) || (t.isIdentifier(specifier.imported) ? specifier.imported.name : specifier.imported.value) !== WEVU_DEFINE_PAGE_META_MACRO || specifier.importKind === "type");
25751
+ if (specifiers.length === path.node.specifiers.length) return;
25752
+ mutated = true;
25753
+ path.node.specifiers = specifiers;
25754
+ if (!path.node.specifiers.length) path.remove();
25755
+ },
25756
+ ExpressionStatement(path) {
25757
+ const expression = path.node.expression;
25758
+ if (!t.isCallExpression(expression) || !calls.has(expression)) return;
25759
+ mutated = true;
25760
+ path.remove();
25761
+ }
25762
+ });
25140
25763
  return mutated;
25141
25764
  }
25142
25765
  //#endregion
@@ -25271,7 +25894,6 @@ function createCompilerPageLayoutPlanSignature(plan) {
25271
25894
  }
25272
25895
  //#endregion
25273
25896
  //#region src/plugins/vue/transform/pageLayout/meta.ts
25274
- const PAGE_META_MACRO_NAME = "definePageMeta";
25275
25897
  const analyzedPageLayoutSourceCache = /* @__PURE__ */ new Map();
25276
25898
  function unwrapStaticExpression(node) {
25277
25899
  if (t.isTSAsExpression(node) || t.isTSSatisfiesExpression(node) || t.isTSNonNullExpression(node) || t.isTypeCastExpression(node)) return unwrapStaticExpression(node.expression);
@@ -25353,14 +25975,10 @@ function extractLayoutValueFromObject(node, filename) {
25353
25975
  }
25354
25976
  return layout;
25355
25977
  }
25356
- function extractLayoutFromProgram(ast, filename) {
25978
+ function extractLayoutFromPrograms(programs, filename) {
25357
25979
  let layout;
25358
- let macroCount = 0;
25359
- for (const statement of ast.program.body) {
25360
- if (!t.isExpressionStatement(statement) || !t.isCallExpression(statement.expression)) continue;
25361
- const call = statement.expression;
25362
- if (!t.isIdentifier(call.callee, { name: PAGE_META_MACRO_NAME })) continue;
25363
- macroCount += 1;
25980
+ const calls = collectPageMetaCallsFromPrograms(programs);
25981
+ for (const call of calls) {
25364
25982
  if (call.arguments.length !== 1) throw new Error(`${filename} 中 definePageMeta() 必须且只能接收一个对象参数。`);
25365
25983
  const firstArg = call.arguments[0];
25366
25984
  if (t.isSpreadElement(firstArg) || !t.isExpression(firstArg)) throw new Error(`${filename} 中 definePageMeta() 仅支持对象字面量参数。`);
@@ -25368,7 +25986,7 @@ function extractLayoutFromProgram(ast, filename) {
25368
25986
  if (!t.isObjectExpression(normalized)) throw new Error(`${filename} 中 definePageMeta() 仅支持对象字面量参数。`);
25369
25987
  layout = extractLayoutValueFromObject(normalized, filename);
25370
25988
  }
25371
- if (macroCount > 1) throw new Error(`${filename} 中 definePageMeta() 只能声明一次。`);
25989
+ if (calls.length > 1) throw new Error(`${filename} 中 definePageMeta() 只能声明一次。`);
25372
25990
  return layout;
25373
25991
  }
25374
25992
  function hasSetPageLayoutCallInProgram(ast) {
@@ -25410,25 +26028,21 @@ function analyzeVueScriptBlocks(source, filename) {
25410
26028
  function analyzePageLayoutSourceUncached(source, filename) {
25411
26029
  if (filename.endsWith(".vue")) {
25412
26030
  const { scriptAst, scriptSetupAst } = analyzeVueScriptBlocks(source, filename);
25413
- let layoutMeta;
25414
- if (scriptAst) layoutMeta = extractLayoutFromProgram(scriptAst, filename);
25415
- if (scriptSetupAst) {
25416
- const setupLayout = extractLayoutFromProgram(scriptSetupAst, filename);
25417
- if (layoutMeta !== void 0 && setupLayout !== void 0) throw new Error(`${filename} 中的 <script> 与 <script setup> 不能同时声明 definePageMeta().`);
25418
- if (setupLayout !== void 0) layoutMeta = setupLayout;
25419
- }
26031
+ const layoutMeta = extractLayoutFromPrograms({
26032
+ script: scriptAst,
26033
+ scriptSetup: scriptSetupAst
26034
+ }, filename);
25420
26035
  const dynamicSwitch = Boolean(scriptAst && hasSetPageLayoutCallInProgram(scriptAst) || scriptSetupAst && hasSetPageLayoutCallInProgram(scriptSetupAst));
25421
- const dynamicPropKeys = dynamicSwitch ? Array.from(/* @__PURE__ */ new Set([...scriptAst ? collectSetPageLayoutPropKeysFromProgram(scriptAst) : [], ...scriptSetupAst ? collectSetPageLayoutPropKeysFromProgram(scriptSetupAst) : []])) : [];
25422
26036
  return {
25423
26037
  layoutMeta,
25424
26038
  dynamicSwitch,
25425
- dynamicPropKeys
26039
+ dynamicPropKeys: dynamicSwitch ? Array.from(/* @__PURE__ */ new Set([...scriptAst ? collectSetPageLayoutPropKeysFromProgram(scriptAst) : [], ...scriptSetupAst ? collectSetPageLayoutPropKeysFromProgram(scriptSetupAst) : []])) : []
25426
26040
  };
25427
26041
  }
25428
26042
  const ast = parseScriptAst(source);
25429
26043
  const dynamicSwitch = hasSetPageLayoutCallInProgram(ast);
25430
26044
  return {
25431
- layoutMeta: extractLayoutFromProgram(ast, filename),
26045
+ layoutMeta: extractLayoutFromPrograms({ script: ast }, filename),
25432
26046
  dynamicSwitch,
25433
26047
  dynamicPropKeys: dynamicSwitch ? collectSetPageLayoutPropKeysFromProgram(ast) : []
25434
26048
  };
@@ -25462,7 +26076,6 @@ const TRAILING_INDEX_RE = /\/index$/;
25462
26076
  const LEADING_SLASHES_RE = /^\/+/;
25463
26077
  const ROUTE_RULE_GLOB_TOKEN_RE = /[*?[\]{}()!+@]/g;
25464
26078
  const layoutFilesCache = /* @__PURE__ */ new Map();
25465
- const PAGE_META_HINT = "definePageMeta";
25466
26079
  const SET_PAGE_LAYOUT_HINT = "setPageLayout";
25467
26080
  function normalizePageRouteCandidates(filename, configService) {
25468
26081
  const fullPath = `/${toPosixPath(configService.relativeOutputPath(removeFileExtension(filename))).replace(LEADING_SLASHES_RE, "")}`;
@@ -25607,7 +26220,7 @@ function invalidateResolvedPageLayoutsCache(absoluteSrcRoot) {
25607
26220
  layoutFilesCache.delete(normalizeComparablePath(absoluteSrcRoot));
25608
26221
  }
25609
26222
  async function resolvePageLayoutPlan(source, filename, configService) {
25610
- const hasPageMetaHint = source.includes(PAGE_META_HINT);
26223
+ const hasPageMetaHint = mayContainPageMeta(source);
25611
26224
  const hasDynamicLayoutHint = source.includes(SET_PAGE_LAYOUT_HINT);
25612
26225
  const analyzedSource = hasPageMetaHint || hasDynamicLayoutHint ? analyzePageLayoutSource(source, filename) : void 0;
25613
26226
  const layoutMeta = (hasPageMetaHint ? analyzedSource?.layoutMeta : void 0) ?? resolveRouteRuleLayoutMeta(filename, configService);
@@ -26612,6 +27225,7 @@ async function emitEntryOutput(options) {
26612
27225
  if (error && typeof error === "object" && "code" in error && error.code === "ENOENT" && configService.isDev && !await fs$1.pathExists(id)) return;
26613
27226
  throw error;
26614
27227
  }
27228
+ if (type === "page" && !NON_VUE_PAGE_RE.test(id) && mayContainPageDeclaration(code)) code = stripPageDeclaration(code, id)?.code ?? code;
26615
27229
  if (type === "page" && templatePath && !NON_VUE_PAGE_RE.test(id)) {
26616
27230
  const layoutStartedAt = performance$1.now();
26617
27231
  try {
@@ -26734,7 +27348,7 @@ const VUE_JSON_BLOCK_RE = /<json\b[^>]*>[\s\S]*?<\/json>/gi;
26734
27348
  const VUE_JSON_MACRO_HINT_RE = /\bdefine(?:App|Page|Component|Sitemap|Theme)Json\s*\(/;
26735
27349
  const NO_VUE_CONFIG_SIGNATURE = "no-vue-config";
26736
27350
  function hasPageLayoutSourceHint(source) {
26737
- return source.includes("definePageMeta") || source.includes("setPageLayout");
27351
+ return mayContainPageMeta(source) || source.includes("setPageLayout");
26738
27352
  }
26739
27353
  function hashText(value) {
26740
27354
  return createHash("sha256").update(value).digest("hex").slice(0, 16);
@@ -27554,6 +28168,7 @@ function useLoadEntry(ctx, options) {
27554
28168
  },
27555
28169
  async emitDirtyEntries() {
27556
28170
  entryChunkLifecycle.beginBuild();
28171
+ ctx.runtimeState.build.hmr.forceEmitUnchangedChunks = false;
27557
28172
  if (!dirtyEntrySet.size) {
27558
28173
  options?.hmr?.setDidEmitAllEntries?.(false);
27559
28174
  options?.hmr?.setLastEmittedEntries?.(/* @__PURE__ */ new Set());
@@ -27588,6 +28203,7 @@ function useLoadEntry(ctx, options) {
27588
28203
  rootInputIds
27589
28204
  });
27590
28205
  const pendingEntryIds = pendingResolution.pending;
28206
+ ctx.runtimeState.build.hmr.forceEmitUnchangedChunks = [...pendingEntryIds].some((entryId) => dirtyEntryReasons.get(entryId) !== "metadata");
27591
28207
  const pending = [];
27592
28208
  chunkEmitStats.chunkEmitCount = 0;
27593
28209
  chunkEmitStats.emitFileMs = 0;
@@ -29630,42 +30246,6 @@ function injectSharedStyleImports(css, modulePath, fileName, sharedStyles, confi
29630
30246
  return prependSharedStyleImports(css, statements);
29631
30247
  }
29632
30248
  //#endregion
29633
- //#region src/plugins/utils/parse.ts
29634
- function hasOwn$2(source, key) {
29635
- return Object.prototype.hasOwnProperty.call(source, key);
29636
- }
29637
- /**
29638
- * 参考:https://github.com/tailwindlabs/tailwindcss/blob/main/packages/%40tailwindcss-vite/src/index.ts
29639
- * 解析请求ID,返回包含文件名和查询参数的对象。
29640
- * 如果查询参数中包含'wxss',则将其值设置为true。
29641
- * @param id - 请求ID,格式为'filename?query'
29642
- * @returns 解析后的请求响应对象
29643
- */
29644
- function parseRequest(id) {
29645
- const [filename, rawQuery] = id.split(`?`, 2);
29646
- const query = {};
29647
- if (rawQuery) {
29648
- const params = new URLSearchParams(rawQuery);
29649
- for (const [key, value] of params.entries()) query[key] = value;
29650
- if (hasOwn$2(query, "wxss")) query.wxss = true;
29651
- }
29652
- return {
29653
- filename,
29654
- query
29655
- };
29656
- }
29657
- /**
29658
- * 根据请求响应获取 CSS 文件的真实路径。
29659
- * 如果请求中包含 wxss 查询参数,则将文件扩展名更改为 'wxss'。
29660
- * @param res - 解析请求的响应对象,包含文件名和查询参数。
29661
- * @returns 返回文件的真实路径。
29662
- */
29663
- function getCssRealPath(res) {
29664
- if (typeof res.query.nativeStyle === "string" && res.query.nativeStyle) return changeFileExtension(res.filename, res.query.nativeStyle);
29665
- if (res.query.wxss) return changeFileExtension(res.filename, "wxss");
29666
- return res.filename;
29667
- }
29668
- //#endregion
29669
30249
  //#region src/plugins/css/styleOwnership.ts
29670
30250
  /** 在样式模块上保存实际消费的源文件,避免把仅用于失效的图边当作产物所有权。 */
29671
30251
  function createStyleSourceMeta(sources) {
@@ -29700,6 +30280,16 @@ const LEADING_BLANK_LINES_RE = /^(?:[ \t]*\r?\n)+/;
29700
30280
  const TAILWIND_CONTENT_HMR_NONCE_RE = /\n\/\* weapp-vite tailwind-content [^*\n]+ \*\/$/;
29701
30281
  const VITE_PREPROCESS_STYLE_RE = /\.(?:acss|css|less|sass|scss|styl|stylus|pcss|postcss|sss)$/;
29702
30282
  const TAILWIND_GENERATOR_PLACEHOLDER = "/*! weapp-tailwindcss generator-placeholder */";
30283
+ const VITE_STYLE_ASSET_PLACEHOLDER_RE = /__VITE_ASSET__([\w$]+)__(?:\$_(.*?)__)?/g;
30284
+ function resolveViteStyleAssetPlaceholders(source, fileName, pluginCtx) {
30285
+ if (!source.includes("__VITE_ASSET__") || typeof pluginCtx.getFileName !== "function") return source;
30286
+ return source.replace(VITE_STYLE_ASSET_PLACEHOLDER_RE, (_placeholder, referenceId, postfix = "") => {
30287
+ const assetFileName = toPosixPath(pluginCtx.getFileName(referenceId));
30288
+ const relativePath = path.posix.relative(path.posix.dirname(toPosixPath(fileName)), assetFileName);
30289
+ const assetUrl = relativePath.startsWith(".") ? relativePath : `./${relativePath}`;
30290
+ return `${encodeURI(assetUrl)}${postfix}`;
30291
+ });
30292
+ }
29703
30293
  const pendingOwnerStyleSources = /* @__PURE__ */ new WeakMap();
29704
30294
  function consumePendingOwnerStyleSources(ctx) {
29705
30295
  const sources = pendingOwnerStyleSources.get(ctx);
@@ -29827,7 +30417,8 @@ function emitCssAssetIfChanged(ctx, pluginCtx, bundle, fileName, source, options
29827
30417
  const cache = ctx.runtimeState?.css?.emittedSource;
29828
30418
  const existing = bundle[fileName];
29829
30419
  const forceEmit = hasTailwindContentDirtyReason(ctx) || hasManagedTailwindcssOutputMarker(source);
29830
- const emittedSource = appendTailwindContentHmrNonce(ctx, source);
30420
+ const resolvedSource = resolveViteStyleAssetPlaceholders(source, fileName, pluginCtx);
30421
+ const emittedSource = appendTailwindContentHmrNonce(ctx, resolvedSource);
29831
30422
  if (existing?.type === "asset") {
29832
30423
  const current = existing.source?.toString?.() ?? "";
29833
30424
  if (!forceEmit && isUnchangedDevHmrStyleAsset(ctx, normalizedFileName, current, emittedSource)) {
@@ -29835,17 +30426,17 @@ function emitCssAssetIfChanged(ctx, pluginCtx, bundle, fileName, source, options
29835
30426
  return false;
29836
30427
  }
29837
30428
  if (current !== emittedSource) existing.source = emittedSource;
29838
- cache?.set(normalizedFileName, source);
30429
+ cache?.set(normalizedFileName, resolvedSource);
29839
30430
  return true;
29840
30431
  }
29841
- if (!forceEmit && cache?.get(normalizedFileName) === source) return false;
30432
+ if (!forceEmit && cache?.get(normalizedFileName) === resolvedSource) return false;
29842
30433
  pluginCtx.emitFile({
29843
30434
  type: "asset",
29844
30435
  fileName,
29845
30436
  ...options?.originalFileName ? { originalFileName: options.originalFileName } : {},
29846
30437
  source: emittedSource
29847
30438
  });
29848
- cache?.set(normalizedFileName, source);
30439
+ cache?.set(normalizedFileName, resolvedSource);
29849
30440
  return true;
29850
30441
  }
29851
30442
  function injectSharedStyleImportsCached(css, modulePath, fileName, sharedStyles, configService, cache) {
@@ -29985,7 +30576,7 @@ async function handleBundleEntry(ctx, bundle, bundleKey, asset, configService, s
29985
30576
  const { css, dependencies } = await preprocessStyleSource(preprocessInput, preprocessId, resolvedConfig, { enabled: shouldPreprocess });
29986
30577
  syncCssImportDependencies(ctx, preprocessId, freshHmrStyleSourcePath ? preprocessInput : graphSource, dependencies);
29987
30578
  if (typeof this.addWatchFile === "function") for (const dependency of dependencies) this.addWatchFile(normalizeWatchPath(dependency));
29988
- const processedCss = await processCssWithCache(css, configService);
30579
+ const processedCss = resolveViteStyleAssetPlaceholders(await processCssWithCache(css, configService), fileName, this);
29989
30580
  if (fileName !== bundleKey) {
29990
30581
  delete bundle[bundleKey];
29991
30582
  emitCssAssetIfChanged(ctx, this, bundle, fileName, processedCss);
@@ -30683,6 +31274,74 @@ async function flushIndependentOutputs(ctx, subPackageMeta, emitAsset) {
30683
31274
  for (const output of outputs) for (const bundleOutput of getBundleOutputs(output)) emitAsset(toEmittedAsset(bundleOutput));
30684
31275
  }
30685
31276
  //#endregion
31277
+ //#region src/plugins/outputFinalizer/scopedStyles.ts
31278
+ const SCOPE_ATTRIBUTE_RE = /^data-v-[\w-]+$/;
31279
+ /** 支付宝和抖音不支持 scoped 属性选择器,使用同等优先级的 class 保留作用域。 */
31280
+ function normalizeClassScopedTemplate(source) {
31281
+ if (!source.includes("data-v-")) return source;
31282
+ const result = new MagicString(source);
31283
+ let scopes = [];
31284
+ let classEnd;
31285
+ let unquotedClass;
31286
+ let classes = /* @__PURE__ */ new Set();
31287
+ let tagEnd = 0;
31288
+ const parser = new Parser({
31289
+ onopentagname(name) {
31290
+ scopes = [];
31291
+ classEnd = void 0;
31292
+ unquotedClass = void 0;
31293
+ classes = /* @__PURE__ */ new Set();
31294
+ tagEnd = parser.startIndex + 1 + name.length;
31295
+ },
31296
+ onattribute(name, value, quote) {
31297
+ if (SCOPE_ATTRIBUTE_RE.test(name) && value === "") scopes.push(name);
31298
+ if (name === "class") {
31299
+ classEnd = parser.endIndex - (quote ? 1 : 0);
31300
+ classes = new Set(value.split(/\s+/));
31301
+ if (!quote) unquotedClass = {
31302
+ start: parser.startIndex,
31303
+ end: parser.endIndex,
31304
+ value
31305
+ };
31306
+ }
31307
+ },
31308
+ onopentag() {
31309
+ scopes = scopes.filter((scope) => !classes.has(scope));
31310
+ if (!scopes.length) return;
31311
+ if (unquotedClass) result.overwrite(unquotedClass.start, unquotedClass.end, `class="${unquotedClass.value} ${scopes.join(" ")}"`);
31312
+ else if (classEnd !== void 0) result.appendLeft(classEnd, ` ${scopes.join(" ")}`);
31313
+ else result.appendLeft(tagEnd, ` class="${scopes.join(" ")}"`);
31314
+ }
31315
+ }, {
31316
+ xmlMode: true,
31317
+ decodeEntities: false
31318
+ });
31319
+ parser.end(source);
31320
+ return result.toString();
31321
+ }
31322
+ function normalizeClassScopedStyle(source) {
31323
+ if (!source.includes("data-v-")) return source;
31324
+ const root = postcss.parse(source);
31325
+ root.walkRules((rule) => {
31326
+ if (!rule.selector.includes("data-v-")) return;
31327
+ rule.selector = selectorParser((selectors) => {
31328
+ selectors.walkAttributes((attribute) => {
31329
+ if (SCOPE_ATTRIBUTE_RE.test(attribute.attribute) && !attribute.operator) attribute.replaceWith(selectorParser.className({ value: attribute.attribute }));
31330
+ });
31331
+ }).processSync(rule.selector);
31332
+ });
31333
+ return root.toString();
31334
+ }
31335
+ /** 在 bundler 写盘前同时归一化模板和样式,也覆盖仅包含样式资源的 HMR。 */
31336
+ function normalizeClassScopedAssets(bundle, extensions) {
31337
+ for (const output of Object.values(bundle)) {
31338
+ if (output.type !== "asset") continue;
31339
+ const source = typeof output.source === "string" ? output.source : Buffer.from(output.source).toString("utf8");
31340
+ if (output.fileName.endsWith(`.${extensions.wxml}`)) output.source = normalizeClassScopedTemplate(source);
31341
+ else if (output.fileName.endsWith(`.${extensions.wxss}`)) output.source = normalizeClassScopedStyle(source);
31342
+ }
31343
+ }
31344
+ //#endregion
30686
31345
  //#region src/plugins/outputFinalizer.ts
30687
31346
  const PREPROCESSOR_STYLE_ASSET_RE = /\.(?:less|sass|scss|styl|stylus|pcss|postcss|sss)$/i;
30688
31347
  const TEMPLATE_ASSET_RE = /\.(?:wxml|axml|swan|ttml|jxml|qml|ksml|xhsml)$/i;
@@ -30855,8 +31514,9 @@ function pruneUnchangedDevHmrOutputs(ctx, bundle, rewriteOptions, options) {
30855
31514
  stabilizeWevuRuntimeChunkAccess(bundle);
30856
31515
  }
30857
31516
  for (const [fileName, output] of Object.entries(bundle)) {
30858
- const shouldForceEmitCurrentHmrChunk = isHmrBuild && output.type === "chunk" && (emittedChunkFileNames?.has(fileName) === true || emittedChunkFileNames?.has(output.fileName) === true);
30859
- if (isHmrBuild && output.type === "chunk" && emittedChunkFileNames?.size && !shouldForceEmitCurrentHmrChunk) {
31517
+ const isCurrentHmrChunk = isHmrBuild && output.type === "chunk" && (emittedChunkFileNames?.has(fileName) === true || emittedChunkFileNames?.has(output.fileName) === true);
31518
+ const shouldForceEmitCurrentHmrChunk = isCurrentHmrChunk && ctx.runtimeState.build.hmr.forceEmitUnchangedChunks !== false;
31519
+ if (isHmrBuild && output.type === "chunk" && emittedChunkFileNames?.size && !isCurrentHmrChunk) {
30860
31520
  delete bundle[fileName];
30861
31521
  continue;
30862
31522
  }
@@ -30912,6 +31572,7 @@ function createOutputFinalizerPlugin(ctx, subPackageMeta) {
30912
31572
  if (ctx.configService.platform === "weapp") analyzeGlassEaselBundle(ctx, outputBundle);
30913
31573
  normalizePreprocessorStyleAssetEntries(outputBundle, assetEntries.preprocessorStyleAssets, ctx.configService.outputExtensions?.wxss, assets.stage);
30914
31574
  normalizeTemplateAssetEntries(ctx, assetEntries.templateAssets, subPackageMeta);
31575
+ if (ctx.configService.platform === "alipay" || ctx.configService.platform === "tt") normalizeClassScopedAssets(outputBundle, ctx.configService.outputExtensions);
30915
31576
  pruneUnchangedDevHmrOutputs(ctx, outputBundle, wevuRuntimeRewriteOptions, {
30916
31577
  runtimeRewriteDone: true,
30917
31578
  preserveCompleteBundle
@@ -33177,7 +33838,7 @@ async function resolveAppShellForCompilation(ctx, pluginCtx) {
33177
33838
  if (!configService || !scanService || configService.weappLibConfig?.enabled) return;
33178
33839
  const appEntry = await scanService.loadAppEntry();
33179
33840
  if (!isAppVueFile(appEntry.path)) return;
33180
- const { descriptor } = await readAndParseSfc(appEntry.path, createReadAndParseSfcOptions(pluginCtx, configService));
33841
+ const { descriptor } = await readAndParseSfc$1(appEntry.path, createReadAndParseSfcOptions(pluginCtx, configService));
33181
33842
  if (!descriptor.template?.content.trim()) return;
33182
33843
  return resolveAppShellLayout(configService);
33183
33844
  }
@@ -36149,7 +36810,7 @@ async function refreshCompiledVueEntryCacheInDev(options) {
36149
36810
  }
36150
36811
  const currentStyleIndependentSignature = dirtyEntryId && filename.endsWith(".vue") && isVueStyleOnlyDirtyReasonSummary(ctx.runtimeState?.build?.hmr?.profile?.dirtyReasonSummary) ? resolveVueSfcStyleIndependentSignature(source, filename) : void 0;
36151
36812
  if (dirtyEntryId && filename.endsWith(".vue") && cached.styleIndependentSignature && currentStyleIndependentSignature && cached.styleIndependentSignature === currentStyleIndependentSignature && transformed.signature === cached.autoRoutesSignature && cached.source !== source) {
36152
- const { descriptor } = await readAndParseSfc(filename, {
36813
+ const { descriptor } = await readAndParseSfc$1(filename, {
36153
36814
  source,
36154
36815
  checkMtime: configService.isDev
36155
36816
  });
@@ -37339,7 +38000,7 @@ function createVueTransformPlugin(ctx, options = {}) {
37339
38000
  },
37340
38001
  scopedSlotModules,
37341
38002
  parseWeappVueStyleRequest: (id) => parseWeappVueStyleRequest(id) ?? null,
37342
- readAndParseSfc,
38003
+ readAndParseSfc: readAndParseSfc$1,
37343
38004
  createReadAndParseSfcOptions
37344
38005
  });
37345
38006
  },
@@ -37368,7 +38029,7 @@ function createVueTransformPlugin(ctx, options = {}) {
37368
38029
  scopedSlotModules,
37369
38030
  emittedScopedSlotChunks,
37370
38031
  classStyleRuntimeWarned,
37371
- readAndParseSfc,
38032
+ readAndParseSfc: readAndParseSfc$1,
37372
38033
  createReadAndParseSfcOptions
37373
38034
  });
37374
38035
  } finally {
@@ -37948,9 +38609,13 @@ function mergeMiniprogram(options, ...configs) {
37948
38609
  }
37949
38610
  //#endregion
37950
38611
  //#region src/runtime/config/internal/merge/web.ts
37951
- function mergeWebPlugins(rawPlugins, webPlugin, runtimeProviderPlugin) {
38612
+ function mergeWebPlugins(rawPlugins, webPlugin, runtimeProviderPlugin, internalPlugins = []) {
37952
38613
  const remaining = [];
37953
- const ownedPluginNames = new Set([webPlugin, runtimeProviderPlugin].map((option) => option && typeof option === "object" && "name" in option ? option.name : void 0).filter((name) => typeof name === "string"));
38614
+ const ownedPluginNames = new Set([
38615
+ webPlugin,
38616
+ runtimeProviderPlugin,
38617
+ ...internalPlugins
38618
+ ].map((option) => option && typeof option === "object" && "name" in option ? option.name : void 0).filter((name) => typeof name === "string"));
37954
38619
  const collect = (option) => {
37955
38620
  if (!option) return;
37956
38621
  if (Array.isArray(option)) {
@@ -37965,6 +38630,7 @@ function mergeWebPlugins(rawPlugins, webPlugin, runtimeProviderPlugin) {
37965
38630
  return [
37966
38631
  runtimeProviderPlugin,
37967
38632
  webPlugin,
38633
+ ...internalPlugins,
37968
38634
  ...remaining
37969
38635
  ].filter(Boolean);
37970
38636
  }
@@ -37999,7 +38665,8 @@ function mergeWeb(options, ...configs) {
37999
38665
  hmrAcceptCode: resolveRuntimeProviderHmrFooter(runtimeProvider)
38000
38666
  }
38001
38667
  });
38002
- inline.plugins = mergeWebPlugins(inline.plugins, webPlugin, runtimeProviderPlugin);
38668
+ const autoRoutesPlugins = options.ctx && !options.configService?.weappLibConfig?.enabled && resolveWeappAutoRoutesConfig(options.configService?.weappViteConfig?.autoRoutes).enabled ? autoRoutes(options.ctx) : [];
38669
+ inline.plugins = mergeWebPlugins(inline.plugins, webPlugin, runtimeProviderPlugin, autoRoutesPlugins);
38003
38670
  inline.build ??= {};
38004
38671
  inline.build.outDir = web.outDir;
38005
38672
  inline.build.emptyOutDir ??= !isDev;
@@ -38115,6 +38782,7 @@ function createMergeFactories(options) {
38115
38782
  const subPackageRoots = Object.keys(configService.weappViteConfig?.subPackages ?? {});
38116
38783
  const sharedOutput = configService.options.chunksConfigured ? createSharedBuildOutput(configService, () => subPackageRoots, { runtime: "web" }) : void 0;
38117
38784
  return backend.driver.mergeConfig({ merge: (...backendConfigs) => mergeWeb({
38785
+ ctx,
38118
38786
  configService,
38119
38787
  config: currentOptions.config,
38120
38788
  web: currentOptions.weappWeb,
@@ -38735,7 +39403,7 @@ async function loadAppEntry(ctx, scanState) {
38735
39403
  const { path: appEntryPath } = appEntry;
38736
39404
  let configFromVue;
38737
39405
  if (!appConfigFile && vueAppPath) {
38738
- const { extractConfigFromVue } = await import("./file-DxMrh1lh.mjs");
39406
+ const { extractConfigFromVue } = await import("./file-BRwj-D25.mjs");
38739
39407
  configFromVue = await extractConfigFromVue(vueAppPath);
38740
39408
  if (configFromVue) appConfigFile = vueAppPath;
38741
39409
  }