weapp-vite 7.1.3 → 7.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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-CD9gXASh.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));
@@ -10199,6 +10710,7 @@ function createProviderPlugin(ctx, config, onChange) {
10199
10710
  async function createDevModuleGraphProvider(ctx, buildConfig, onChange) {
10200
10711
  const configService = ctx.configService;
10201
10712
  const userWatch = buildConfig.server?.watch;
10713
+ const pollingWatchOptions = resolvePollingWatchOptions({ inlineConfig: configService?.inlineConfig ?? {} });
10202
10714
  const ignored = configService?.outDir ? createViteWatchIgnored(buildConfig.root ?? configService.cwd, configService.outDir, userWatch?.ignored) : userWatch?.ignored;
10203
10715
  const server = await createServer({
10204
10716
  ...buildConfig,
@@ -10213,6 +10725,7 @@ async function createDevModuleGraphProvider(ctx, buildConfig, onChange) {
10213
10725
  middlewareMode: true,
10214
10726
  watch: {
10215
10727
  ...userWatch ?? {},
10728
+ ...Object.fromEntries(Object.entries(pollingWatchOptions).filter(([, value]) => value !== void 0)),
10216
10729
  ...ignored !== void 0 ? { ignored } : {}
10217
10730
  }
10218
10731
  },
@@ -10290,7 +10803,7 @@ async function collectVueStyleScriptChanges(ctx, filename, configService) {
10290
10803
  const changedEntries = /* @__PURE__ */ new Set();
10291
10804
  for (const [entryId, bindings] of ctx.runtimeState.build.hmr.vueEntryStyleBindings) {
10292
10805
  if (!bindings.sources.some((source) => normalizeFsResolvedId(source) === filename)) continue;
10293
- const { descriptor } = await readAndParseSfc(entryId, createReadAndParseSfcOptions(ctx.moduleGraphService, configService));
10806
+ const { descriptor } = await readAndParseSfc$1(entryId, createReadAndParseSfcOptions(ctx.moduleGraphService, configService));
10294
10807
  if (!hasSameCssVars(bindings.expressions, descriptor.cssVars)) changedEntries.add(entryId);
10295
10808
  }
10296
10809
  return changedEntries;
@@ -10478,6 +10991,9 @@ function resolveHmrRuntimeDecision(options) {
10478
10991
  runtime: "classic"
10479
10992
  };
10480
10993
  }
10994
+ function resolveHmrRuntime(options) {
10995
+ return resolveHmrRuntimeDecision(options).runtime;
10996
+ }
10481
10997
  function findSkylineRendererFiles(output) {
10482
10998
  const jsonConfigs = /* @__PURE__ */ new Map();
10483
10999
  for (const item of output) {
@@ -11471,9 +11987,18 @@ function createRuntimeState() {
11471
11987
  },
11472
11988
  autoRoutes: {
11473
11989
  routes: emptyAutoRoutesSnapshot,
11990
+ namedRoutes: [],
11474
11991
  serialized: emptyAutoRoutesArtifacts.serialized,
11475
11992
  moduleCode: emptyAutoRoutesArtifacts.moduleCode,
11993
+ namedModuleCode: emptyAutoRoutesArtifacts.namedModuleCode,
11994
+ signature: emptyAutoRoutesArtifacts.signature,
11995
+ topologyKey: "",
11476
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(),
11477
12002
  watchFiles: /* @__PURE__ */ new Set(),
11478
12003
  watchDirs: /* @__PURE__ */ new Set(),
11479
12004
  dirty: true,
@@ -11523,6 +12048,7 @@ function createRuntimeState() {
11523
12048
  lastHmrEntryIds: /* @__PURE__ */ new Set(),
11524
12049
  lastEmittedEntryIds: /* @__PURE__ */ new Set(),
11525
12050
  lastEmittedChunkFileNames: /* @__PURE__ */ new Set(),
12051
+ forceEmitUnchangedChunks: true,
11526
12052
  sharedChunkSourceModuleIds: /* @__PURE__ */ new Set(),
11527
12053
  recentProfiles: [],
11528
12054
  profile: {}
@@ -11589,18 +12115,7 @@ function resetRuntimeStateForFreshBuild(runtimeState) {
11589
12115
  runtimeState.glassEasel.diagnostics.clear();
11590
12116
  runtimeState.glassEasel.warnedDiagnostics.clear();
11591
12117
  runtimeState.glassEasel.silent = false;
11592
- const autoRoutes = runtimeState.autoRoutes;
11593
- autoRoutes.routes = fresh.autoRoutes.routes;
11594
- autoRoutes.serialized = fresh.autoRoutes.serialized;
11595
- autoRoutes.moduleCode = fresh.autoRoutes.moduleCode;
11596
- autoRoutes.typedDefinition = fresh.autoRoutes.typedDefinition;
11597
- autoRoutes.watchFiles.clear();
11598
- autoRoutes.watchDirs.clear();
11599
- autoRoutes.dirty = fresh.autoRoutes.dirty;
11600
- autoRoutes.initialized = fresh.autoRoutes.initialized;
11601
- autoRoutes.candidates.clear();
11602
- autoRoutes.needsFullRescan = fresh.autoRoutes.needsFullRescan;
11603
- autoRoutes.loadingAppConfig = fresh.autoRoutes.loadingAppConfig;
12118
+ Object.assign(runtimeState.autoRoutes, fresh.autoRoutes);
11604
12119
  const autoImport = runtimeState.autoImport;
11605
12120
  autoImport.registry.clear();
11606
12121
  autoImport.normalizedLocalComponents.clear();
@@ -13184,6 +13699,29 @@ function createPreserveModulesGroup(configService, getSubPackageRoots) {
13184
13699
  };
13185
13700
  }
13186
13701
  //#endregion
13702
+ //#region src/runtime/sharedBuildConfig/virtualChunk.ts
13703
+ /** 虚拟模块的完整路径只作为标识参与散列,避免泄漏到文件名并超过文件系统长度限制。 */
13704
+ function resolveVirtualChunkFileName(chunk, root) {
13705
+ const ids = chunk.facadeModuleId ? [chunk.facadeModuleId] : chunk.moduleIds ?? [];
13706
+ if (ids.length !== 1) return;
13707
+ const id = ids[0];
13708
+ const entry = parseLogicalEntryId(id);
13709
+ const sidecar = parseSidecarModuleId(id);
13710
+ const identity = entry ? [
13711
+ "entry",
13712
+ entry.type,
13713
+ path.relative(root, entry.sourceId)
13714
+ ] : sidecar ? [
13715
+ "sidecar",
13716
+ sidecar.kind,
13717
+ path.relative(root, sidecar.ownerId),
13718
+ path.relative(root, sidecar.sourceId)
13719
+ ] : void 0;
13720
+ if (!identity) return;
13721
+ const hash = createHash("sha256").update(JSON.stringify(identity)).digest("hex").slice(0, 16);
13722
+ return `weapp-${identity[0]}-${identity[1]}-${hash}.js`;
13723
+ }
13724
+ //#endregion
13187
13725
  //#region src/runtime/wevuModules.ts
13188
13726
  const WEVU_RUNTIME_MODULE_IDS = [
13189
13727
  "wevu",
@@ -13230,6 +13768,15 @@ function normalizeModuleId(id) {
13230
13768
  stripLeadingNullByte: true
13231
13769
  }).replaceAll("\\", "/");
13232
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
+ }
13233
13780
  function resolveWevuPreservedModulePath(id) {
13234
13781
  const normalized = normalizeModuleId(id);
13235
13782
  const sourceMarker = "/packages-runtime/wevu/src/";
@@ -13288,6 +13835,7 @@ const REG_COMMONJS_HELPERS = /commonjsHelpers\.js$/;
13288
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)))(?:$|[?#])/;
13289
13836
  const REG_WEAPP_VITE_RUNTIME_VENDOR_ID = /(?:^|[/\\])weapp-vite[/\\](?:dist[/\\]runtime\.mjs|src[/\\]plugins[/\\]vue[/\\]runtime\.ts)(?:$|[?#])/;
13290
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\//;
13291
13839
  const STABLE_HASHED_DIST_CHUNK_PRIORITY = ["src"];
13292
13840
  const STABLE_HASHED_DIST_CHUNK_PRIORITY_BY_PACKAGE = { wevu: [
13293
13841
  "index",
@@ -13415,14 +13963,24 @@ function isWeappViteRuntimeModuleId(id) {
13415
13963
  REG_WEAPP_VITE_RUNTIME_VENDOR_ID.lastIndex = 0;
13416
13964
  return REG_WEAPP_VITE_RUNTIME_VENDOR_ID.test(cleanedAbsoluteId);
13417
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
+ }
13418
13974
  function resolveStableHashedDistChunkFileName(chunk) {
13419
13975
  const candidateIds = [chunk.facadeModuleId, ...chunk.moduleIds ?? []].filter((id) => typeof id === "string");
13420
13976
  const matchedChunks = [];
13421
13977
  let facadeMatchedChunk;
13422
- for (const id of candidateIds) {
13423
- const fileName = resolveWevuStableVendorFileName(id);
13424
- if (fileName) return fileName;
13425
- }
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;
13426
13984
  for (const id of candidateIds) {
13427
13985
  if (isWeappViteRuntimeModuleId(id)) return "weapp-vendors/weapp-vite-runtime.js";
13428
13986
  const cleanedAbsoluteId = normalizeSharedPathCandidate(id);
@@ -13519,7 +14077,7 @@ function createSharedBuildOutput(configService, getSubPackageRoots, options = {}
13519
14077
  const stableHashedDistChunkFileName = resolveStableHashedDistChunkFileName(chunk);
13520
14078
  if (stableHashedDistChunkFileName) return stableHashedDistChunkFileName;
13521
14079
  }
13522
- return "[name].js";
14080
+ return resolveVirtualChunkFileName(chunk, configService.absoluteSrcRoot) ?? "[name].js";
13523
14081
  }
13524
14082
  };
13525
14083
  }
@@ -14275,37 +14833,6 @@ function isStatefulHmrRuntimeCompatibilityError(error) {
14275
14833
  return error instanceof StatefulHmrRuntimeCompatibilityError || typeof error === "object" && error !== null && Reflect.get(error, "code") === "WEAPP_VITE_STATEFUL_HMR_RUNTIME_INCOMPATIBLE";
14276
14834
  }
14277
14835
  //#endregion
14278
- //#region src/runtime/statefulHmr/componentPageStyles.ts
14279
- /** 以完整产物中的最终 JSON 覆盖注册选项,只接纳已确认的 Component 页面。 */
14280
- function resolveComponentPageGlobalStyleRoutes(output, pageOptions) {
14281
- const assets = new Map(output.flatMap((item) => item.type === "asset" ? [[item.fileName, item]] : []));
14282
- const appAsset = assets.get("app.json");
14283
- const appConfig = appAsset ? JSON.parse(Buffer.from(appAsset.source).toString("utf8")) : void 0;
14284
- const independentRoots = [];
14285
- if (appConfig && typeof appConfig === "object" && !Array.isArray(appConfig)) {
14286
- const config = appConfig;
14287
- for (const key of ["subPackages", "subpackages"]) {
14288
- const packages = config[key];
14289
- if (!Array.isArray(packages)) continue;
14290
- for (const entry of packages) if (entry && typeof entry === "object" && "independent" in entry && entry.independent === true && "root" in entry && typeof entry.root === "string") independentRoots.push(path.normalize(entry.root).replace(/^\/+|\/+$/g, ""));
14291
- }
14292
- }
14293
- const routes = [];
14294
- for (const [sourceRoute, options] of pageOptions) {
14295
- const route = path.normalize(sourceRoute);
14296
- if (independentRoots.some((root) => route === root || route.startsWith(`${root}/`))) continue;
14297
- const jsonAsset = assets.get(`${route}.json`);
14298
- let isolation = options.styleIsolation.kind === "known" ? options.styleIsolation.value : void 0;
14299
- if (jsonAsset) {
14300
- const config = JSON.parse(Buffer.from(jsonAsset.source).toString("utf8"));
14301
- if (config === null || typeof config !== "object" || Array.isArray(config)) throw new Error(`Invalid Component page JSON: ${route}.json`);
14302
- if ("styleIsolation" in config && config.styleIsolation !== void 0) isolation = config.styleIsolation;
14303
- }
14304
- if (isolation === "apply-shared") routes.push(route);
14305
- }
14306
- return routes.sort();
14307
- }
14308
- //#endregion
14309
14836
  //#region src/plugins/hooks/useLoadEntry/entryChunkLifecycle.ts
14310
14837
  const ENTRY_GRAPH_CHANGE_REASON = "entry-graph-changed";
14311
14838
  /** 入口注册属于完整扫描;局部扫描只能复用已注册入口或请求重建入口图。 */
@@ -15079,7 +15606,7 @@ function createStatefulHmrGlobalStyleAssets(output, styleExtension, options = {}
15079
15606
  const globalStyle = result.find((item) => item.type === "asset" && item.fileName === styleFile);
15080
15607
  const marker = pageStyleRefreshMarker(styleRefreshToken(globalStyle?.type === "asset" ? globalStyle.source : ""));
15081
15608
  for (const [index, item] of result.entries()) {
15082
- if (item.type !== "asset" || path.extname(item.fileName) !== path.extname(styleFile) || item.fileName === entryFile || item.fileName === styleFile) continue;
15609
+ if (item.type !== "asset" || path.extname(item.fileName) !== path.extname(styleFile) || !routes.has(item.fileName.slice(0, -path.extname(styleFile).length))) continue;
15083
15610
  const original = Buffer.from(item.source).toString("utf8");
15084
15611
  const source = stripPageStyleRefreshMarker(original);
15085
15612
  if (!source) continue;
@@ -17808,6 +18335,7 @@ async function runStatefulHmrDev(ctx, buildOptions, restart, snapshots) {
17808
18335
  port: 0,
17809
18336
  watch: {
17810
18337
  ...buildOptions.server?.watch ?? {},
18338
+ ...Object.fromEntries(Object.entries(pollingWatchOptions).filter(([, value]) => value !== void 0)),
17811
18339
  ignored: createViteWatchIgnored(buildOptions.root ?? configService.cwd, configService.outDir, buildOptions.server?.watch?.ignored)
17812
18340
  }
17813
18341
  },
@@ -18278,6 +18806,65 @@ function formatStatefulHmrError(error) {
18278
18806
  return String(error);
18279
18807
  }
18280
18808
  //#endregion
18809
+ //#region src/runtime/statefulHmr/componentPageStyles.ts
18810
+ function hasNativePageRegistration(code) {
18811
+ if (!code.includes("Page")) return false;
18812
+ let found = false;
18813
+ traverse(parseJsLike(code), { CallExpression(callPath) {
18814
+ const callee = callPath.node.callee;
18815
+ if (callee.type === "Identifier" && callee.name === "Page" && !callPath.scope.hasBinding("Page")) {
18816
+ found = true;
18817
+ callPath.stop();
18818
+ }
18819
+ } });
18820
+ return found;
18821
+ }
18822
+ /** 以最终 JSON 和注册方式确认继承全局样式的页面,保留独立分包与隔离边界。 */
18823
+ function resolveComponentPageGlobalStyleRoutes(output, pageOptions) {
18824
+ const assets = new Map(output.flatMap((item) => item.type === "asset" ? [[item.fileName, item]] : []));
18825
+ const appAsset = assets.get("app.json");
18826
+ const appConfig = appAsset ? JSON.parse(Buffer.from(appAsset.source).toString("utf8")) : void 0;
18827
+ const independentRoots = [];
18828
+ const nativeCandidates = [];
18829
+ if (appConfig && typeof appConfig === "object" && !Array.isArray(appConfig)) {
18830
+ const config = appConfig;
18831
+ if (Array.isArray(config.pages)) nativeCandidates.push(...config.pages.filter((route) => typeof route === "string"));
18832
+ for (const key of ["subPackages", "subpackages"]) {
18833
+ const packages = config[key];
18834
+ if (!Array.isArray(packages)) continue;
18835
+ for (const entry of packages) if (entry && typeof entry === "object" && "independent" in entry && entry.independent === true && "root" in entry && typeof entry.root === "string") independentRoots.push(path.normalize(entry.root).replace(/^\/+|\/+$/g, ""));
18836
+ else if (entry && typeof entry === "object" && "root" in entry && typeof entry.root === "string" && "pages" in entry && Array.isArray(entry.pages)) nativeCandidates.push(...entry.pages.filter((route) => typeof route === "string").map((route) => path.join(entry.root, route)));
18837
+ }
18838
+ }
18839
+ const routes = [];
18840
+ const componentRoutes = new Set(Array.from(pageOptions.keys(), (route) => path.normalize(route)));
18841
+ for (const [sourceRoute, options] of pageOptions) {
18842
+ const route = path.normalize(sourceRoute);
18843
+ if (independentRoots.some((root) => route === root || route.startsWith(`${root}/`))) continue;
18844
+ const jsonAsset = assets.get(`${route}.json`);
18845
+ let isolation = options.styleIsolation.kind === "known" ? options.styleIsolation.value : void 0;
18846
+ if (jsonAsset) {
18847
+ const config = JSON.parse(Buffer.from(jsonAsset.source).toString("utf8"));
18848
+ if (config === null || typeof config !== "object" || Array.isArray(config)) throw new Error(`Invalid Component page JSON: ${route}.json`);
18849
+ if ("styleIsolation" in config && config.styleIsolation !== void 0) isolation = config.styleIsolation;
18850
+ }
18851
+ if (isolation === "apply-shared") routes.push(route);
18852
+ }
18853
+ const chunks = new Map(output.flatMap((item) => item.type === "chunk" ? [[item.fileName, item]] : []));
18854
+ for (const sourceRoute of nativeCandidates) {
18855
+ const route = path.normalize(sourceRoute);
18856
+ if (componentRoutes.has(route) || independentRoots.some((root) => route === root || route.startsWith(`${root}/`))) continue;
18857
+ const chunk = chunks.get(`${route}.js`);
18858
+ if (!chunk || !hasNativePageRegistration(chunk.code)) continue;
18859
+ const json = assets.get(`${route}.json`);
18860
+ const config = json ? JSON.parse(Buffer.from(json.source).toString("utf8")) : {};
18861
+ if (!config || typeof config !== "object" || Array.isArray(config)) throw new Error(`Invalid native page JSON: ${route}.json`);
18862
+ if ("component" in config && config.component === true) continue;
18863
+ routes.push(route);
18864
+ }
18865
+ return [...new Set(routes)].sort();
18866
+ }
18867
+ //#endregion
18281
18868
  //#region src/runtime/statefulHmr/snapshotBuild.ts
18282
18869
  /** 快照独立编译;初始化到构建收尾均不写支持文件,由活动 DevEngine 统一维护。 */
18283
18870
  async function buildStatefulHmrSnapshot(loadOptions, configure = (options) => options) {
@@ -18287,7 +18874,16 @@ async function buildStatefulHmrSnapshot(loadOptions, configure = (options) => op
18287
18874
  await ctx.configService.load(loadOptions);
18288
18875
  await ctx.scanService.loadAppEntry();
18289
18876
  ctx.scanService.loadSubPackages();
18290
- const options = configure(ctx.configService.merge(void 0, createSharedBuildConfig(ctx.configService, ctx.scanService)));
18877
+ let globalStyleRoutes = [];
18878
+ const baseOptions = ctx.configService.merge(void 0, createSharedBuildConfig(ctx.configService, ctx.scanService));
18879
+ baseOptions.plugins = [...baseOptions.plugins ?? [], {
18880
+ name: "weapp-vite:stateful-hmr-page-style-metadata",
18881
+ enforce: "post",
18882
+ generateBundle(_options, bundle) {
18883
+ globalStyleRoutes = resolveComponentPageGlobalStyleRoutes(Object.values(bundle), ctx.runtimeState.build.hmr.componentPageStyleOptions);
18884
+ }
18885
+ }];
18886
+ const options = configure(baseOptions);
18291
18887
  options.build = {
18292
18888
  ...options.build,
18293
18889
  watch: void 0,
@@ -18297,7 +18893,7 @@ async function buildStatefulHmrSnapshot(loadOptions, configure = (options) => op
18297
18893
  output: await build(options),
18298
18894
  getEntryIds: () => ctx.runtimeState.build.hmr.resolvedEntryMap.keys(),
18299
18895
  getDelegatedComponentEntryIds: () => Array.from(ctx.runtimeState.build.hmr.resolvedEntryMap.keys()).filter((id) => /\.(?:vue|jsx|tsx)$/.test(id) && ctx.runtimeState.build.hmr.entriesMap.get(ctx.configService.relativeAbsoluteSrcRoot(removeExtensionDeep(id)))?.type === "component"),
18300
- getComponentPageStyleOptions: () => ctx.runtimeState.build.hmr.componentPageStyleOptions
18896
+ getGlobalStyleRoutes: () => globalStyleRoutes
18301
18897
  };
18302
18898
  });
18303
18899
  }
@@ -18776,7 +19372,7 @@ async function applyScriptSetupUsingComponents(options) {
18776
19372
  const { pluginCtx, vueEntryPath, source, templatePath, json, configService, wxmlService, reExportResolutionCache, externalComponentEntryMap } = options;
18777
19373
  try {
18778
19374
  if (source !== void 0 && !hasTemplateComponentTagHint(source)) return;
18779
- 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 }) });
18780
19376
  if (!errors?.length && descriptor?.template && !templatePath) {
18781
19377
  const tags = collectVueTemplateAutoImportTags(descriptor.template.content, vueEntryPath);
18782
19378
  if (tags.size) {
@@ -20128,7 +20724,7 @@ async function syncManagedTsconfigSupportFiles(ctx) {
20128
20724
  };
20129
20725
  }
20130
20726
  async function syncAutoRoutesSupportFiles(ctx) {
20131
- if (ctx.autoRoutesService?.isEnabled()) await ctx.autoRoutesService.ensureFresh();
20727
+ await ctx.autoRoutesService?.ensureFresh();
20132
20728
  }
20133
20729
  async function syncAutoImportSupportFiles(ctx, syncAutoImport, configService) {
20134
20730
  const autoImportConfig = syncAutoImport ? getAutoImportConfig(configService) : void 0;
@@ -20551,6 +21147,10 @@ function resetEmittedOutputCaches(runtimeState) {
20551
21147
  runtimeState.css.transformedSidecarSource.clear();
20552
21148
  runtimeState.wxml.emittedCode.clear();
20553
21149
  }
21150
+ function shouldCleanOutputs(configService, phase) {
21151
+ if (configService.inlineConfig.build?.emptyOutDir === false) return false;
21152
+ return phase === "rebuild" || !configService.isDev || configService.weappViteConfig.cleanOutputsInDev !== false;
21153
+ }
20554
21154
  async function cleanOutputs(configService) {
20555
21155
  if (configService.mpDistRoot) {
20556
21156
  const preservedNpmDirNames = resolvePreservedNpmDirNames(configService);
@@ -20570,10 +21170,24 @@ async function cleanOutputs(configService) {
20570
21170
  //#endregion
20571
21171
  //#region src/runtime/buildPlugin/snapshotSources.ts
20572
21172
  /** 一次性 snapshot 不经过 watchChange,构建前必须刷新整个批次的真实源状态。 */
20573
- async function refreshSnapshotSources(ctx, files) {
21173
+ async function refreshSnapshotSources(ctx, files, emittedRouteSignature) {
20574
21174
  const changedFiles = new Set(Array.from(files, (file) => normalizeFsResolvedId(file)));
20575
21175
  for (const file of changedFiles) invalidateFileCache(file);
20576
- 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
+ };
20577
21191
  }
20578
21192
  //#endregion
20579
21193
  //#region src/runtime/buildPlugin/touchAppWxss.ts
@@ -21415,7 +22029,7 @@ function createBuildService(ctx) {
21415
22029
  if (target === "app" && hmrDecision.runtime === "stateful-experimental") try {
21416
22030
  const snapshot = await buildStatefulHmrSnapshot(configService.loadOptions, appendHmrMetricsPlugin);
21417
22031
  const initialSnapshot = toStatefulHmrOutput(snapshot.output);
21418
- const initialGlobalStyleRoutes = resolveComponentPageGlobalStyleRoutes(initialSnapshot, snapshot.getComponentPageStyleOptions());
22032
+ const initialGlobalStyleRoutes = snapshot.getGlobalStyleRoutes();
21419
22033
  const initialEntryIds = collectStatefulHmrEntryIds(snapshot.getEntryIds());
21420
22034
  const skylineFiles = findSkylineRendererFiles(initialSnapshot);
21421
22035
  if (skylineFiles.length > 0) await applySkylineHmrFallback({
@@ -21475,12 +22089,11 @@ function createBuildService(ctx) {
21475
22089
  }];
21476
22090
  return snapshotOptions;
21477
22091
  });
21478
- const output = toStatefulHmrOutput(snapshot.output);
21479
22092
  return {
21480
- output,
22093
+ output: toStatefulHmrOutput(snapshot.output),
21481
22094
  entryIds: [...collectStatefulHmrEntryIds(snapshot.getEntryIds())],
21482
22095
  delegatedComponentEntryIds: snapshot.getDelegatedComponentEntryIds(),
21483
- componentPageGlobalStyleRoutes: resolveComponentPageGlobalStyleRoutes(output, snapshot.getComponentPageStyleOptions())
22096
+ componentPageGlobalStyleRoutes: snapshot.getGlobalStyleRoutes()
21484
22097
  };
21485
22098
  }
21486
22099
  }), workerPromise]);
@@ -21516,6 +22129,7 @@ function createBuildService(ctx) {
21516
22129
  let pendingSnapshotBatch;
21517
22130
  let failedSnapshotReasons = [];
21518
22131
  let snapshotBatchTimer;
22132
+ let emittedAutoRoutesSignature;
21519
22133
  const devBuildWatcher = target === "app" ? createDevBuildWatcher() : void 0;
21520
22134
  function markSnapshotEntriesFullDirty() {
21521
22135
  for (const entryId of ctx.runtimeState.build.hmr.resolvedEntryMap.keys()) {
@@ -21576,7 +22190,9 @@ function createBuildService(ctx) {
21576
22190
  recordHmrProfileDuration(ctx.runtimeState.build.hmr.profile, "snapshotResolveMs", performance.now() - snapshotResolveStartedAt);
21577
22191
  const snapshotBuildStartedAt = performance.now();
21578
22192
  const requiresFullRescan = batchReasons.some((batchReason) => batchReason.forceFullRescan || batchReason.event === "create" || batchReason.event === "delete");
21579
- 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);
21580
22196
  const styleScriptChanges = /* @__PURE__ */ new Set();
21581
22197
  for (const batchReason of batchReasons) {
21582
22198
  if (!batchReason.file) continue;
@@ -21588,7 +22204,7 @@ function createBuildService(ctx) {
21588
22204
  if (!requiresFullRescan && graphAffectedEntries.size) {
21589
22205
  const dirtyReasons = batchReasons.map(resolveSnapshotDirtyReason);
21590
22206
  const dirtyReason = dirtyReasons.includes("direct") ? "direct" : dirtyReasons.includes("dependency") ? "dependency" : "metadata";
21591
- 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);
21592
22208
  const summaryCounts = /* @__PURE__ */ new Map();
21593
22209
  for (const batchReason of batchReasons) {
21594
22210
  if (!batchReason.file) continue;
@@ -21600,6 +22216,7 @@ function createBuildService(ctx) {
21600
22216
  try {
21601
22217
  devBuildWatcher?.emitEvent({ code: "START" });
21602
22218
  await build(snapshotBuildOptions);
22219
+ emittedAutoRoutesSignature = routeSignature;
21603
22220
  devBuildWatcher?.emitEvent({ code: "END" });
21604
22221
  } catch (error) {
21605
22222
  devBuildWatcher?.emitEvent({
@@ -21623,9 +22240,10 @@ function createBuildService(ctx) {
21623
22240
  ...snapshotBuildOptions,
21624
22241
  build: {
21625
22242
  ...snapshotBuildOptions.build ?? {},
21626
- emptyOutDir: true
22243
+ emptyOutDir: shouldCleanOutputs(configService, "rebuild")
21627
22244
  }
21628
22245
  });
22246
+ emittedAutoRoutesSignature = routeSignature;
21629
22247
  devBuildWatcher?.emitEvent({ code: "END" });
21630
22248
  return "snapshot";
21631
22249
  } catch (error) {
@@ -21690,7 +22308,10 @@ function createBuildService(ctx) {
21690
22308
  const watcherPromise = target === "app" ? (async () => {
21691
22309
  devBuildWatcher.emitEvent({ code: "START" });
21692
22310
  try {
22311
+ await ctx.autoRoutesService?.ensureFresh();
22312
+ const routeSignature = ctx.autoRoutesService?.getSignature();
21693
22313
  await build(snapshotBuildOptions);
22314
+ emittedAutoRoutesSignature = routeSignature;
21694
22315
  devBuildWatcher.emitEvent({ code: "END" });
21695
22316
  return devBuildWatcher.watcher;
21696
22317
  } catch (error) {
@@ -21875,6 +22496,8 @@ function createBuildService(ctx) {
21875
22496
  const pluginOutputRoot = configService.absolutePluginOutputRoot;
21876
22497
  if (!pluginOutputRoot) return;
21877
22498
  const inlineConfig = { build: { outDir: pluginOutputRoot } };
22499
+ const emptyOutDir = configService.inlineConfig.build?.emptyOutDir;
22500
+ if (typeof emptyOutDir === "boolean") inlineConfig.build.emptyOutDir = emptyOutDir;
21878
22501
  const isolatedCtx = await createCompilerContext({
21879
22502
  key: `plugin-build:${configService.cwd}`,
21880
22503
  cwd: configService.cwd,
@@ -21903,7 +22526,7 @@ function createBuildService(ctx) {
21903
22526
  return await runProd(target);
21904
22527
  }
21905
22528
  async function buildEntry(options) {
21906
- if (!configService.isDev || configService.weappViteConfig.cleanOutputsInDev !== false) {
22529
+ if (shouldCleanOutputs(configService, "startup")) {
21907
22530
  await cleanOutputs(configService);
21908
22531
  resetEmittedOutputCaches(ctx.runtimeState);
21909
22532
  }
@@ -22089,34 +22712,6 @@ function resolveBuiltinPackageAliases(options = {}) {
22089
22712
  return aliases;
22090
22713
  }
22091
22714
  //#endregion
22092
- //#region src/runtime/config/internal/alias.ts
22093
- function normalizeAliasOptions(alias) {
22094
- if (!alias) return [];
22095
- if (Array.isArray(alias)) return alias.filter((entry) => {
22096
- return Boolean(entry && typeof entry === "object" && "find" in entry && "replacement" in entry);
22097
- });
22098
- return Object.entries(alias).map(([find, replacement]) => {
22099
- return {
22100
- find,
22101
- replacement
22102
- };
22103
- });
22104
- }
22105
- function createAliasManager(oxcAlias, defaultBuiltinAliases) {
22106
- function injectBuiltinAliases(config, builtinAliases = defaultBuiltinAliases) {
22107
- const resolve = config.resolve ?? (config.resolve = {});
22108
- const aliasArray = normalizeAliasOptions(resolve.alias);
22109
- if (!aliasArray.some((entry) => {
22110
- return entry.find instanceof RegExp && entry.find.source === oxcAlias.find.source;
22111
- })) aliasArray.unshift(oxcAlias);
22112
- for (const builtin of builtinAliases) if (!aliasArray.some((entry) => {
22113
- return typeof entry.find === "string" && entry.find === builtin.find;
22114
- })) aliasArray.unshift(builtin);
22115
- resolve.alias = aliasArray;
22116
- }
22117
- return { injectBuiltinAliases };
22118
- }
22119
- //#endregion
22120
22715
  //#region src/runtime/config/enhance.ts
22121
22716
  const enhanceKeys = [
22122
22717
  "wxml",
@@ -24276,89 +24871,6 @@ function asset(ctx) {
24276
24871
  buildTarget: ctx.currentBuildTarget ?? "app"
24277
24872
  })];
24278
24873
  }
24279
- const RESOLVED_VIRTUAL_ID = "\0weapp-vite:auto-routes";
24280
- /**
24281
- * 判断当前是否应按 watch 模式为 auto-routes 注册依赖文件。
24282
- */
24283
- function isAutoRoutesWatchMode(configService) {
24284
- return Boolean(configService?.isDev || configService?.inlineConfig?.build?.watch);
24285
- }
24286
- /**
24287
- * 合并 service 与 matcher 提供的监听目录,并去重保留顺序。
24288
- */
24289
- function collectAutoRoutesWatchDirs(watchDirectories, matcherWatchRoots) {
24290
- const watchDirs = /* @__PURE__ */ new Set();
24291
- for (const dir of watchDirectories) watchDirs.add(dir);
24292
- for (const dir of matcherWatchRoots) watchDirs.add(dir);
24293
- return [...watchDirs];
24294
- }
24295
- /**
24296
- * 过滤出真正需要交给 auto-routes watcher 处理的路由 Vue 文件。
24297
- */
24298
- function isAutoRoutesWatchFile(filePath, allowedExtensions, isPagesRelatedPath) {
24299
- return !isAutoRoutesGeneratedFileName(path.basename(filePath)) && allowedExtensions.has(path.extname(filePath)) && isPagesRelatedPath(filePath);
24300
- }
24301
- /**
24302
- * 判断是否满足 auto-routes sidecar watcher 的启动前置条件。
24303
- */
24304
- function shouldStartAutoRoutesWatcher(options) {
24305
- if (options.routeWatcherStarted) return false;
24306
- if (!options.isDev) return false;
24307
- if (!options.autoRoutesEnabled || !options.autoRoutesWatch || !options.serviceEnabled) return false;
24308
- return options.watchDirsLength > 0;
24309
- }
24310
- /**
24311
- * 生成 sidecar watcher map 使用的关闭句柄。
24312
- */
24313
- function createAutoRoutesSidecarWatcher(watcher) {
24314
- return { close: async () => {
24315
- await watcher.close();
24316
- } };
24317
- }
24318
- /**
24319
- * 向插件上下文注册 auto-routes 相关 watch 目标,忽略单个 addWatchFile 失败。
24320
- */
24321
- function addAutoRoutesWatchTargets(pluginCtx, targets) {
24322
- for (const file of targets.files) try {
24323
- pluginCtx.addWatchFile?.(normalizeWatchPath(file));
24324
- } catch {}
24325
- for (const dir of targets.directories) try {
24326
- pluginCtx.addWatchFile?.(normalizeWatchPath(dir));
24327
- } catch {}
24328
- }
24329
- /**
24330
- * 统一解析 auto-routes 虚拟模块与 alias 入口的命中关系。
24331
- */
24332
- function resolveAutoRoutesVirtualId(id, aliasTargets) {
24333
- if (id === "weapp-vite/auto-routes" || id === "virtual:weapp-vite-auto-routes" || id === "\0weapp-vite:auto-routes") return RESOLVED_VIRTUAL_ID;
24334
- return aliasTargets.has(id) ? RESOLVED_VIRTUAL_ID : null;
24335
- }
24336
- /**
24337
- * 将 create/delete 这类结构性变化映射为 auto-routes 的全量重扫语义。
24338
- */
24339
- function resolveAutoRoutesWatchChangeEvent(event) {
24340
- if (event === "create" || event === "delete") return "rename";
24341
- }
24342
- /**
24343
- * 判断某次热更新是否需要触发 auto-routes 虚拟模块失效。
24344
- */
24345
- function resolveAutoRoutesHotUpdateAction(command, options) {
24346
- if (command === "serve") return options.isRouteFile ? {
24347
- shouldHandle: true,
24348
- shouldUpdateRouteFile: true
24349
- } : {
24350
- shouldHandle: false,
24351
- shouldUpdateRouteFile: false
24352
- };
24353
- if (options.isRouteFile || options.isPagesRelatedPath) return {
24354
- shouldHandle: true,
24355
- shouldUpdateRouteFile: false
24356
- };
24357
- return {
24358
- shouldHandle: false,
24359
- shouldUpdateRouteFile: false
24360
- };
24361
- }
24362
24874
  //#endregion
24363
24875
  //#region src/plugins/core/lifecycle/autoRoutesTopology.ts
24364
24876
  /**
@@ -24370,31 +24882,95 @@ function markAppEntryForAutoRoutesTopology(ctx, options) {
24370
24882
  invalidateFileCache("weapp-vite/auto-routes");
24371
24883
  invalidateFileCache("virtual:weapp-vite-auto-routes");
24372
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);
24373
24888
  for (const target of resolveAutoRoutesAliasTargets(ctx.configService?.packageInfo?.rootPath)) invalidateFileCache(normalizeFsResolvedId(target));
24374
- options.loadEntry?.invalidateResolveCache?.();
24889
+ const loadEntry = options.loadEntry;
24890
+ if (loadEntry && typeof loadEntry === "object" && "invalidateResolveCache" in loadEntry && typeof loadEntry.invalidateResolveCache === "function") loadEntry.invalidateResolveCache();
24375
24891
  ctx.runtimeState.build.hmr.appEntryAutoRoutesSignature = void 0;
24376
24892
  if (!appEntryId || !options.resolvedEntryMap.has(appEntryId)) return false;
24377
24893
  options.markEntryDirty(appEntryId, "direct");
24378
24894
  return true;
24379
24895
  }
24380
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
24381
24933
  //#region src/plugins/autoRoutes.ts
24382
24934
  /**
24383
24935
  * 路由文件监听器的唯一标识,用于在 sidecarWatcherMap 中注册。
24384
24936
  */
24385
- const ROUTE_WATCHER_KEY = "__auto-routes-vue-watcher__";
24386
- function createAutoRoutesPlugin(ctx) {
24387
- 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) {
24388
24952
  let resolvedConfig;
24389
24953
  let devServer;
24954
+ let servedRouteSignature;
24390
24955
  const autoRoutesAliasTargets = /* @__PURE__ */ new Set();
24391
24956
  const autoRoutesTopologyDirtyEntries = /* @__PURE__ */ new Set();
24392
- 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
+ }
24393
24968
  const refreshAutoRoutesAliasTargets = () => {
24394
24969
  autoRoutesAliasTargets.clear();
24395
24970
  for (const target of resolveAutoRoutesAliasTargets(ctx.configService?.packageInfo?.rootPath)) autoRoutesAliasTargets.add(target);
24396
24971
  };
24397
24972
  function isPagesRelatedPath(id) {
24973
+ if (service.isPageDeclarationSource(id)) return true;
24398
24974
  const configService = ctx.configService;
24399
24975
  if (!configService) return false;
24400
24976
  const { autoRoutesConfig, subPackageRoots } = resolveAutoRoutesMatcherContext(ctx);
@@ -24406,37 +24982,14 @@ function createAutoRoutesPlugin(ctx) {
24406
24982
  subPackageRoots
24407
24983
  });
24408
24984
  }
24409
- /**
24410
- * 启动 chokidar 监听 pages 目录下的路由文件增删。
24411
- * Rolldown 的 watcher 不会为新建文件触发 watchChange,
24412
- * 因此需要独立的文件监听来补偿。
24413
- *
24414
- * 注意:chokidar v5 在 macOS 上使用 glob 模式时无法检测新建文件,
24415
- * 必须直接监听目录,然后在事件回调中按扩展名过滤。
24416
- *
24417
- * 生命周期:watcher 注册到 sidecarWatcherMap,由 watcherService.closeAll()
24418
- * 统一回收,不在 closeBundle 中销毁(build watch 模式下 closeBundle 每次
24419
- * 重编译都会触发,提前销毁会导致后续文件变更无法感知)。
24420
- */
24421
- function invalidateAutoRoutesVirtualModule() {
24422
- const server = devServer;
24423
- const virtualModule = server?.moduleGraph.getModuleById(RESOLVED_VIRTUAL_ID);
24424
- if (!virtualModule || !server) return;
24425
- const seen = /* @__PURE__ */ new Set();
24426
- const invalidateModuleWithImporters = (module) => {
24427
- if (seen.has(module)) return;
24428
- seen.add(module);
24429
- server.moduleGraph.invalidateModule(module);
24430
- for (const importer of module.importers) invalidateModuleWithImporters(importer);
24431
- };
24432
- invalidateModuleWithImporters(virtualModule);
24433
- }
24434
- function markAutoRoutesTopologyDirty() {
24985
+ function markAutoRoutesTopologyDirty(controller) {
24986
+ const appEntry = ctx.scanService?.appEntry?.path;
24987
+ if (appEntry) controller.subscribers.get("web")?.topologyDirtyEntries.add(normalizeFsResolvedId(appEntry));
24435
24988
  return markAppEntryForAutoRoutesTopology(ctx, {
24436
24989
  resolvedEntryMap: ctx.runtimeState.build.hmr.resolvedEntryMap,
24437
24990
  markEntryDirty(entryId) {
24438
24991
  const hmr = ctx.runtimeState.build.hmr;
24439
- autoRoutesTopologyDirtyEntries.add(entryId);
24992
+ for (const subscriber of controller.subscribers.values()) subscriber.topologyDirtyEntries.add(entryId);
24440
24993
  hmr.dirtyEntrySet.add(entryId);
24441
24994
  hmr.dirtyEntryReasons.set(entryId, "direct");
24442
24995
  hmr.loadedEntrySet.delete(entryId);
@@ -24445,32 +24998,80 @@ function createAutoRoutesPlugin(ctx) {
24445
24998
  }
24446
24999
  });
24447
25000
  }
24448
- function notifyAppEntryChange() {
24449
- const appEntryPath = ctx.scanService?.appEntry?.path;
24450
- if (!appEntryPath || !devServer) return;
24451
- devServer.watcher.emit("change", appEntryPath);
24452
- }
24453
- async function handleRouteStructureChange(filePath, event) {
24454
- if (await service.handleFileChange(filePath, event)) {
24455
- invalidateAutoRoutesVirtualModule();
24456
- markAutoRoutesTopologyDirty();
24457
- 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;
24458
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
+ });
24459
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);
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
+ */
24460
25051
  function startRouteFileWatcher() {
24461
25052
  const configService = ctx.configService;
24462
25053
  if (!configService) return;
24463
25054
  const { autoRoutesConfig, matcher: resolvedMatcher } = resolveAutoRoutesMatcherContext(ctx);
24464
- const allowedExtensions = new Set(vueExtensions.map((ext) => `.${ext}`));
25055
+ const allowedExtensions = new Set([...vueExtensions, ...scriptExtensions].map((ext) => `.${ext}`));
24465
25056
  const watchDirs = collectAutoRoutesWatchDirs(service.getWatchDirectories(), resolvedMatcher.getWatchRoots(configService.absoluteSrcRoot));
24466
25057
  if (!shouldStartAutoRoutesWatcher({
24467
- routeWatcherStarted,
25058
+ routeWatcherStarted: false,
24468
25059
  isDev: configService.isDev,
24469
25060
  autoRoutesEnabled: autoRoutesConfig.enabled,
24470
25061
  autoRoutesWatch: autoRoutesConfig.watch,
24471
25062
  serviceEnabled: service.isEnabled(),
24472
25063
  watchDirsLength: watchDirs.length
24473
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]]);
24474
25075
  const watcher = chokidar.watch(watchDirs, createSidecarWatchOptions(configService, {
24475
25076
  ignoreInitial: true,
24476
25077
  persistent: true,
@@ -24479,23 +25080,43 @@ function createAutoRoutesPlugin(ctx) {
24479
25080
  pollInterval: 20
24480
25081
  }
24481
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
+ };
24482
25095
  watcher.on("add", (filePath) => {
24483
- if (!isAutoRoutesWatchFile(filePath, allowedExtensions, isPagesRelatedPath)) return;
25096
+ if (!isAutoRoutesWatchFile(filePath, allowedExtensions, isPagesRelatedPath, service.isPageDeclarationSource)) return;
24484
25097
  logger_default.info(`[auto-routes:watch] 新增路由文件 ${configService.relativeCwd(filePath)}`);
24485
- handleRouteStructureChange(filePath, "create");
25098
+ handleRouteStructureChange(filePath, "create", controller).catch((error) => {
25099
+ reportRouteStructureChangeError(filePath, "create", error, controller);
25100
+ });
24486
25101
  });
24487
25102
  watcher.on("unlink", (filePath) => {
24488
- if (!isAutoRoutesWatchFile(filePath, allowedExtensions, isPagesRelatedPath)) return;
25103
+ if (!isAutoRoutesWatchFile(filePath, allowedExtensions, isPagesRelatedPath, service.isPageDeclarationSource)) return;
24489
25104
  logger_default.info(`[auto-routes:watch] 删除路由文件 ${configService.relativeCwd(filePath)}`);
24490
- handleRouteStructureChange(filePath, "delete");
25105
+ handleRouteStructureChange(filePath, "delete", controller).catch((error) => {
25106
+ reportRouteStructureChangeError(filePath, "delete", error, controller);
25107
+ });
24491
25108
  });
24492
- const { sidecarWatcherMap } = ctx.runtimeState.watcher;
24493
- sidecarWatcherMap.set(ROUTE_WATCHER_KEY, createAutoRoutesSidecarWatcher(watcher));
24494
- routeWatcherStarted = true;
25109
+ sidecarWatcherMap.set(ROUTE_WATCHER_KEY, controller);
24495
25110
  }
24496
25111
  return {
24497
25112
  name: "weapp-vite:auto-routes",
24498
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
+ },
24499
25120
  configResolved(config) {
24500
25121
  resolvedConfig = config;
24501
25122
  refreshAutoRoutesAliasTargets();
@@ -24504,6 +25125,7 @@ function createAutoRoutesPlugin(ctx) {
24504
25125
  devServer = server;
24505
25126
  },
24506
25127
  buildStart() {
25128
+ registerPageDeclarationSourceResolver(this);
24507
25129
  refreshAutoRoutesAliasTargets();
24508
25130
  startRouteFileWatcher();
24509
25131
  },
@@ -24518,50 +25140,111 @@ function createAutoRoutesPlugin(ctx) {
24518
25140
  }
24519
25141
  },
24520
25142
  async load(id) {
24521
- 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。`);
24522
25147
  await service.ensureFresh();
24523
- if (isAutoRoutesWatchMode(ctx.configService)) addAutoRoutesWatchTargets(this, {
25148
+ if (isAutoRoutesWatchMode(ctx.configService)) addAutoRoutesWatchTargets(resolvedConfig?.command === "serve" ? { addWatchFile: (file) => devServer?.watcher.add(file) } : this, {
24524
25149
  files: service.getWatchFiles(),
24525
- directories: service.getWatchDirectories()
25150
+ directories: resolvedConfig?.command === "serve" ? [] : service.getWatchDirectories()
24526
25151
  });
24527
25152
  startRouteFileWatcher();
25153
+ if (resolvedConfig?.weappVite?.runtime === "web") servedRouteSignature ??= service.getSignature();
24528
25154
  return {
24529
- code: service.getModuleCode(),
25155
+ code: resolvedId === WEVU_AUTO_ROUTES_RESOLVED_MODULE_ID$1 ? service.getNamedModuleCode() : service.getModuleCode(),
24530
25156
  map: { mappings: "" }
24531
25157
  };
24532
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
+ },
24533
25173
  shouldTransformCachedModule({ id }) {
24534
25174
  return autoRoutesTopologyDirtyEntries.delete(id) || void 0;
24535
25175
  },
24536
25176
  async watchChange(id, change) {
25177
+ registerPageDeclarationSourceResolver(this);
24537
25178
  const event = change?.event;
24538
25179
  if (service.isRouteFile(id)) {
24539
25180
  if (resolvedConfig?.command === "serve" && event === "update") return;
24540
- await service.handleFileChange(id, event);
25181
+ await service.handleFileChange(id, resolveAutoRoutesWatchChangeEvent(event) ?? event);
25182
+ startRouteFileWatcher();
24541
25183
  return;
24542
25184
  }
24543
25185
  if (!isPagesRelatedPath(id)) return;
24544
25186
  const resolvedEvent = resolveAutoRoutesWatchChangeEvent(event);
24545
- if (resolvedEvent) await service.handleFileChange(id, resolvedEvent);
25187
+ if (resolvedEvent) {
25188
+ await service.handleFileChange(id, resolvedEvent);
25189
+ startRouteFileWatcher();
25190
+ }
24546
25191
  },
24547
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));
24548
25197
  const routeFile = service.isRouteFile(context.file);
24549
25198
  const hotUpdateAction = resolveAutoRoutesHotUpdateAction(resolvedConfig?.command, {
24550
25199
  isRouteFile: routeFile,
24551
25200
  isPagesRelatedPath: routeFile ? false : isPagesRelatedPath(context.file)
24552
25201
  });
24553
- if (!hotUpdateAction.shouldHandle) return;
25202
+ if (!hotUpdateAction.shouldHandle && !topologyChanged) return;
24554
25203
  let didChangeRoutes = false;
24555
- if (hotUpdateAction.shouldUpdateRouteFile) didChangeRoutes = await service.handleFileChange(context.file, "update");
24556
- if (resolvedConfig?.command === "serve" && routeFile && !didChangeRoutes) return;
24557
- const virtualModule = context.server.moduleGraph.getModuleById(RESOLVED_VIRTUAL_ID);
24558
- if (virtualModule) return [virtualModule];
24559
- 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();
24560
25242
  }
24561
25243
  };
24562
25244
  }
24563
25245
  function autoRoutes(ctx) {
24564
- return [createAutoRoutesPlugin(ctx)];
25246
+ if (!ctx.autoRoutesService || !ctx.configService) return [];
25247
+ return [createAutoRoutesPlugin(ctx, ctx.autoRoutesService)];
24565
25248
  }
24566
25249
  //#endregion
24567
25250
  //#region src/plugins/hooks/useLoadEntry/autoImport.ts
@@ -25059,13 +25742,24 @@ function findNativePageOptionsObject(ast) {
25059
25742
  return matched;
25060
25743
  }
25061
25744
  function stripDefinePageMetaCalls(ast) {
25745
+ const calls = new Set(collectPageMetaCallsFromPrograms({ script: ast }));
25062
25746
  let mutated = false;
25063
- traverse(ast, { ExpressionStatement(path) {
25064
- const expression = path.node.expression;
25065
- if (!t.isCallExpression(expression) || !t.isIdentifier(expression.callee, { name: "definePageMeta" })) return;
25066
- mutated = true;
25067
- path.remove();
25068
- } });
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
+ });
25069
25763
  return mutated;
25070
25764
  }
25071
25765
  //#endregion
@@ -25200,7 +25894,6 @@ function createCompilerPageLayoutPlanSignature(plan) {
25200
25894
  }
25201
25895
  //#endregion
25202
25896
  //#region src/plugins/vue/transform/pageLayout/meta.ts
25203
- const PAGE_META_MACRO_NAME = "definePageMeta";
25204
25897
  const analyzedPageLayoutSourceCache = /* @__PURE__ */ new Map();
25205
25898
  function unwrapStaticExpression(node) {
25206
25899
  if (t.isTSAsExpression(node) || t.isTSSatisfiesExpression(node) || t.isTSNonNullExpression(node) || t.isTypeCastExpression(node)) return unwrapStaticExpression(node.expression);
@@ -25282,14 +25975,10 @@ function extractLayoutValueFromObject(node, filename) {
25282
25975
  }
25283
25976
  return layout;
25284
25977
  }
25285
- function extractLayoutFromProgram(ast, filename) {
25978
+ function extractLayoutFromPrograms(programs, filename) {
25286
25979
  let layout;
25287
- let macroCount = 0;
25288
- for (const statement of ast.program.body) {
25289
- if (!t.isExpressionStatement(statement) || !t.isCallExpression(statement.expression)) continue;
25290
- const call = statement.expression;
25291
- if (!t.isIdentifier(call.callee, { name: PAGE_META_MACRO_NAME })) continue;
25292
- macroCount += 1;
25980
+ const calls = collectPageMetaCallsFromPrograms(programs);
25981
+ for (const call of calls) {
25293
25982
  if (call.arguments.length !== 1) throw new Error(`${filename} 中 definePageMeta() 必须且只能接收一个对象参数。`);
25294
25983
  const firstArg = call.arguments[0];
25295
25984
  if (t.isSpreadElement(firstArg) || !t.isExpression(firstArg)) throw new Error(`${filename} 中 definePageMeta() 仅支持对象字面量参数。`);
@@ -25297,7 +25986,7 @@ function extractLayoutFromProgram(ast, filename) {
25297
25986
  if (!t.isObjectExpression(normalized)) throw new Error(`${filename} 中 definePageMeta() 仅支持对象字面量参数。`);
25298
25987
  layout = extractLayoutValueFromObject(normalized, filename);
25299
25988
  }
25300
- if (macroCount > 1) throw new Error(`${filename} 中 definePageMeta() 只能声明一次。`);
25989
+ if (calls.length > 1) throw new Error(`${filename} 中 definePageMeta() 只能声明一次。`);
25301
25990
  return layout;
25302
25991
  }
25303
25992
  function hasSetPageLayoutCallInProgram(ast) {
@@ -25339,25 +26028,21 @@ function analyzeVueScriptBlocks(source, filename) {
25339
26028
  function analyzePageLayoutSourceUncached(source, filename) {
25340
26029
  if (filename.endsWith(".vue")) {
25341
26030
  const { scriptAst, scriptSetupAst } = analyzeVueScriptBlocks(source, filename);
25342
- let layoutMeta;
25343
- if (scriptAst) layoutMeta = extractLayoutFromProgram(scriptAst, filename);
25344
- if (scriptSetupAst) {
25345
- const setupLayout = extractLayoutFromProgram(scriptSetupAst, filename);
25346
- if (layoutMeta !== void 0 && setupLayout !== void 0) throw new Error(`${filename} 中的 <script> 与 <script setup> 不能同时声明 definePageMeta().`);
25347
- if (setupLayout !== void 0) layoutMeta = setupLayout;
25348
- }
26031
+ const layoutMeta = extractLayoutFromPrograms({
26032
+ script: scriptAst,
26033
+ scriptSetup: scriptSetupAst
26034
+ }, filename);
25349
26035
  const dynamicSwitch = Boolean(scriptAst && hasSetPageLayoutCallInProgram(scriptAst) || scriptSetupAst && hasSetPageLayoutCallInProgram(scriptSetupAst));
25350
- const dynamicPropKeys = dynamicSwitch ? Array.from(/* @__PURE__ */ new Set([...scriptAst ? collectSetPageLayoutPropKeysFromProgram(scriptAst) : [], ...scriptSetupAst ? collectSetPageLayoutPropKeysFromProgram(scriptSetupAst) : []])) : [];
25351
26036
  return {
25352
26037
  layoutMeta,
25353
26038
  dynamicSwitch,
25354
- dynamicPropKeys
26039
+ dynamicPropKeys: dynamicSwitch ? Array.from(/* @__PURE__ */ new Set([...scriptAst ? collectSetPageLayoutPropKeysFromProgram(scriptAst) : [], ...scriptSetupAst ? collectSetPageLayoutPropKeysFromProgram(scriptSetupAst) : []])) : []
25355
26040
  };
25356
26041
  }
25357
26042
  const ast = parseScriptAst(source);
25358
26043
  const dynamicSwitch = hasSetPageLayoutCallInProgram(ast);
25359
26044
  return {
25360
- layoutMeta: extractLayoutFromProgram(ast, filename),
26045
+ layoutMeta: extractLayoutFromPrograms({ script: ast }, filename),
25361
26046
  dynamicSwitch,
25362
26047
  dynamicPropKeys: dynamicSwitch ? collectSetPageLayoutPropKeysFromProgram(ast) : []
25363
26048
  };
@@ -25391,7 +26076,6 @@ const TRAILING_INDEX_RE = /\/index$/;
25391
26076
  const LEADING_SLASHES_RE = /^\/+/;
25392
26077
  const ROUTE_RULE_GLOB_TOKEN_RE = /[*?[\]{}()!+@]/g;
25393
26078
  const layoutFilesCache = /* @__PURE__ */ new Map();
25394
- const PAGE_META_HINT = "definePageMeta";
25395
26079
  const SET_PAGE_LAYOUT_HINT = "setPageLayout";
25396
26080
  function normalizePageRouteCandidates(filename, configService) {
25397
26081
  const fullPath = `/${toPosixPath(configService.relativeOutputPath(removeFileExtension(filename))).replace(LEADING_SLASHES_RE, "")}`;
@@ -25536,7 +26220,7 @@ function invalidateResolvedPageLayoutsCache(absoluteSrcRoot) {
25536
26220
  layoutFilesCache.delete(normalizeComparablePath(absoluteSrcRoot));
25537
26221
  }
25538
26222
  async function resolvePageLayoutPlan(source, filename, configService) {
25539
- const hasPageMetaHint = source.includes(PAGE_META_HINT);
26223
+ const hasPageMetaHint = mayContainPageMeta(source);
25540
26224
  const hasDynamicLayoutHint = source.includes(SET_PAGE_LAYOUT_HINT);
25541
26225
  const analyzedSource = hasPageMetaHint || hasDynamicLayoutHint ? analyzePageLayoutSource(source, filename) : void 0;
25542
26226
  const layoutMeta = (hasPageMetaHint ? analyzedSource?.layoutMeta : void 0) ?? resolveRouteRuleLayoutMeta(filename, configService);
@@ -26541,6 +27225,7 @@ async function emitEntryOutput(options) {
26541
27225
  if (error && typeof error === "object" && "code" in error && error.code === "ENOENT" && configService.isDev && !await fs$1.pathExists(id)) return;
26542
27226
  throw error;
26543
27227
  }
27228
+ if (type === "page" && !NON_VUE_PAGE_RE.test(id) && mayContainPageDeclaration(code)) code = stripPageDeclaration(code, id)?.code ?? code;
26544
27229
  if (type === "page" && templatePath && !NON_VUE_PAGE_RE.test(id)) {
26545
27230
  const layoutStartedAt = performance$1.now();
26546
27231
  try {
@@ -26663,7 +27348,7 @@ const VUE_JSON_BLOCK_RE = /<json\b[^>]*>[\s\S]*?<\/json>/gi;
26663
27348
  const VUE_JSON_MACRO_HINT_RE = /\bdefine(?:App|Page|Component|Sitemap|Theme)Json\s*\(/;
26664
27349
  const NO_VUE_CONFIG_SIGNATURE = "no-vue-config";
26665
27350
  function hasPageLayoutSourceHint(source) {
26666
- return source.includes("definePageMeta") || source.includes("setPageLayout");
27351
+ return mayContainPageMeta(source) || source.includes("setPageLayout");
26667
27352
  }
26668
27353
  function hashText(value) {
26669
27354
  return createHash("sha256").update(value).digest("hex").slice(0, 16);
@@ -27483,6 +28168,7 @@ function useLoadEntry(ctx, options) {
27483
28168
  },
27484
28169
  async emitDirtyEntries() {
27485
28170
  entryChunkLifecycle.beginBuild();
28171
+ ctx.runtimeState.build.hmr.forceEmitUnchangedChunks = false;
27486
28172
  if (!dirtyEntrySet.size) {
27487
28173
  options?.hmr?.setDidEmitAllEntries?.(false);
27488
28174
  options?.hmr?.setLastEmittedEntries?.(/* @__PURE__ */ new Set());
@@ -27517,6 +28203,7 @@ function useLoadEntry(ctx, options) {
27517
28203
  rootInputIds
27518
28204
  });
27519
28205
  const pendingEntryIds = pendingResolution.pending;
28206
+ ctx.runtimeState.build.hmr.forceEmitUnchangedChunks = [...pendingEntryIds].some((entryId) => dirtyEntryReasons.get(entryId) !== "metadata");
27520
28207
  const pending = [];
27521
28208
  chunkEmitStats.chunkEmitCount = 0;
27522
28209
  chunkEmitStats.emitFileMs = 0;
@@ -29559,42 +30246,6 @@ function injectSharedStyleImports(css, modulePath, fileName, sharedStyles, confi
29559
30246
  return prependSharedStyleImports(css, statements);
29560
30247
  }
29561
30248
  //#endregion
29562
- //#region src/plugins/utils/parse.ts
29563
- function hasOwn$2(source, key) {
29564
- return Object.prototype.hasOwnProperty.call(source, key);
29565
- }
29566
- /**
29567
- * 参考:https://github.com/tailwindlabs/tailwindcss/blob/main/packages/%40tailwindcss-vite/src/index.ts
29568
- * 解析请求ID,返回包含文件名和查询参数的对象。
29569
- * 如果查询参数中包含'wxss',则将其值设置为true。
29570
- * @param id - 请求ID,格式为'filename?query'
29571
- * @returns 解析后的请求响应对象
29572
- */
29573
- function parseRequest(id) {
29574
- const [filename, rawQuery] = id.split(`?`, 2);
29575
- const query = {};
29576
- if (rawQuery) {
29577
- const params = new URLSearchParams(rawQuery);
29578
- for (const [key, value] of params.entries()) query[key] = value;
29579
- if (hasOwn$2(query, "wxss")) query.wxss = true;
29580
- }
29581
- return {
29582
- filename,
29583
- query
29584
- };
29585
- }
29586
- /**
29587
- * 根据请求响应获取 CSS 文件的真实路径。
29588
- * 如果请求中包含 wxss 查询参数,则将文件扩展名更改为 'wxss'。
29589
- * @param res - 解析请求的响应对象,包含文件名和查询参数。
29590
- * @returns 返回文件的真实路径。
29591
- */
29592
- function getCssRealPath(res) {
29593
- if (typeof res.query.nativeStyle === "string" && res.query.nativeStyle) return changeFileExtension(res.filename, res.query.nativeStyle);
29594
- if (res.query.wxss) return changeFileExtension(res.filename, "wxss");
29595
- return res.filename;
29596
- }
29597
- //#endregion
29598
30249
  //#region src/plugins/css/styleOwnership.ts
29599
30250
  /** 在样式模块上保存实际消费的源文件,避免把仅用于失效的图边当作产物所有权。 */
29600
30251
  function createStyleSourceMeta(sources) {
@@ -29629,6 +30280,16 @@ const LEADING_BLANK_LINES_RE = /^(?:[ \t]*\r?\n)+/;
29629
30280
  const TAILWIND_CONTENT_HMR_NONCE_RE = /\n\/\* weapp-vite tailwind-content [^*\n]+ \*\/$/;
29630
30281
  const VITE_PREPROCESS_STYLE_RE = /\.(?:acss|css|less|sass|scss|styl|stylus|pcss|postcss|sss)$/;
29631
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
+ }
29632
30293
  const pendingOwnerStyleSources = /* @__PURE__ */ new WeakMap();
29633
30294
  function consumePendingOwnerStyleSources(ctx) {
29634
30295
  const sources = pendingOwnerStyleSources.get(ctx);
@@ -29756,7 +30417,8 @@ function emitCssAssetIfChanged(ctx, pluginCtx, bundle, fileName, source, options
29756
30417
  const cache = ctx.runtimeState?.css?.emittedSource;
29757
30418
  const existing = bundle[fileName];
29758
30419
  const forceEmit = hasTailwindContentDirtyReason(ctx) || hasManagedTailwindcssOutputMarker(source);
29759
- const emittedSource = appendTailwindContentHmrNonce(ctx, source);
30420
+ const resolvedSource = resolveViteStyleAssetPlaceholders(source, fileName, pluginCtx);
30421
+ const emittedSource = appendTailwindContentHmrNonce(ctx, resolvedSource);
29760
30422
  if (existing?.type === "asset") {
29761
30423
  const current = existing.source?.toString?.() ?? "";
29762
30424
  if (!forceEmit && isUnchangedDevHmrStyleAsset(ctx, normalizedFileName, current, emittedSource)) {
@@ -29764,17 +30426,17 @@ function emitCssAssetIfChanged(ctx, pluginCtx, bundle, fileName, source, options
29764
30426
  return false;
29765
30427
  }
29766
30428
  if (current !== emittedSource) existing.source = emittedSource;
29767
- cache?.set(normalizedFileName, source);
30429
+ cache?.set(normalizedFileName, resolvedSource);
29768
30430
  return true;
29769
30431
  }
29770
- if (!forceEmit && cache?.get(normalizedFileName) === source) return false;
30432
+ if (!forceEmit && cache?.get(normalizedFileName) === resolvedSource) return false;
29771
30433
  pluginCtx.emitFile({
29772
30434
  type: "asset",
29773
30435
  fileName,
29774
30436
  ...options?.originalFileName ? { originalFileName: options.originalFileName } : {},
29775
30437
  source: emittedSource
29776
30438
  });
29777
- cache?.set(normalizedFileName, source);
30439
+ cache?.set(normalizedFileName, resolvedSource);
29778
30440
  return true;
29779
30441
  }
29780
30442
  function injectSharedStyleImportsCached(css, modulePath, fileName, sharedStyles, configService, cache) {
@@ -29914,7 +30576,7 @@ async function handleBundleEntry(ctx, bundle, bundleKey, asset, configService, s
29914
30576
  const { css, dependencies } = await preprocessStyleSource(preprocessInput, preprocessId, resolvedConfig, { enabled: shouldPreprocess });
29915
30577
  syncCssImportDependencies(ctx, preprocessId, freshHmrStyleSourcePath ? preprocessInput : graphSource, dependencies);
29916
30578
  if (typeof this.addWatchFile === "function") for (const dependency of dependencies) this.addWatchFile(normalizeWatchPath(dependency));
29917
- const processedCss = await processCssWithCache(css, configService);
30579
+ const processedCss = resolveViteStyleAssetPlaceholders(await processCssWithCache(css, configService), fileName, this);
29918
30580
  if (fileName !== bundleKey) {
29919
30581
  delete bundle[bundleKey];
29920
30582
  emitCssAssetIfChanged(ctx, this, bundle, fileName, processedCss);
@@ -30612,6 +31274,74 @@ async function flushIndependentOutputs(ctx, subPackageMeta, emitAsset) {
30612
31274
  for (const output of outputs) for (const bundleOutput of getBundleOutputs(output)) emitAsset(toEmittedAsset(bundleOutput));
30613
31275
  }
30614
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
30615
31345
  //#region src/plugins/outputFinalizer.ts
30616
31346
  const PREPROCESSOR_STYLE_ASSET_RE = /\.(?:less|sass|scss|styl|stylus|pcss|postcss|sss)$/i;
30617
31347
  const TEMPLATE_ASSET_RE = /\.(?:wxml|axml|swan|ttml|jxml|qml|ksml|xhsml)$/i;
@@ -30784,8 +31514,9 @@ function pruneUnchangedDevHmrOutputs(ctx, bundle, rewriteOptions, options) {
30784
31514
  stabilizeWevuRuntimeChunkAccess(bundle);
30785
31515
  }
30786
31516
  for (const [fileName, output] of Object.entries(bundle)) {
30787
- const shouldForceEmitCurrentHmrChunk = isHmrBuild && output.type === "chunk" && (emittedChunkFileNames?.has(fileName) === true || emittedChunkFileNames?.has(output.fileName) === true);
30788
- 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) {
30789
31520
  delete bundle[fileName];
30790
31521
  continue;
30791
31522
  }
@@ -30841,6 +31572,7 @@ function createOutputFinalizerPlugin(ctx, subPackageMeta) {
30841
31572
  if (ctx.configService.platform === "weapp") analyzeGlassEaselBundle(ctx, outputBundle);
30842
31573
  normalizePreprocessorStyleAssetEntries(outputBundle, assetEntries.preprocessorStyleAssets, ctx.configService.outputExtensions?.wxss, assets.stage);
30843
31574
  normalizeTemplateAssetEntries(ctx, assetEntries.templateAssets, subPackageMeta);
31575
+ if (ctx.configService.platform === "alipay" || ctx.configService.platform === "tt") normalizeClassScopedAssets(outputBundle, ctx.configService.outputExtensions);
30844
31576
  pruneUnchangedDevHmrOutputs(ctx, outputBundle, wevuRuntimeRewriteOptions, {
30845
31577
  runtimeRewriteDone: true,
30846
31578
  preserveCompleteBundle
@@ -33106,7 +33838,7 @@ async function resolveAppShellForCompilation(ctx, pluginCtx) {
33106
33838
  if (!configService || !scanService || configService.weappLibConfig?.enabled) return;
33107
33839
  const appEntry = await scanService.loadAppEntry();
33108
33840
  if (!isAppVueFile(appEntry.path)) return;
33109
- const { descriptor } = await readAndParseSfc(appEntry.path, createReadAndParseSfcOptions(pluginCtx, configService));
33841
+ const { descriptor } = await readAndParseSfc$1(appEntry.path, createReadAndParseSfcOptions(pluginCtx, configService));
33110
33842
  if (!descriptor.template?.content.trim()) return;
33111
33843
  return resolveAppShellLayout(configService);
33112
33844
  }
@@ -33943,6 +34675,37 @@ function preflight(ctx) {
33943
34675
  return [createPluginPruner(), createEnvSynchronizer(ctx)];
33944
34676
  }
33945
34677
  //#endregion
34678
+ //#region src/plugins/tailwindcss/imports.ts
34679
+ /** 只判断样式导入链的所有权;解析、条件包装与转换仍由 Tailwind 编译器负责。 */
34680
+ async function findManagedStyleImports(code, filename, options) {
34681
+ const dependencies = /* @__PURE__ */ new Set();
34682
+ let managed = false;
34683
+ const visit = async (source, importer) => {
34684
+ if (!source.includes("@import")) return;
34685
+ const requests = [];
34686
+ postcss.parse(source, { from: importer }).walkAtRules("import", (rule) => {
34687
+ const node = valueParser(rule.params).nodes[0];
34688
+ const value = node?.type === "string" ? node.value : node?.type === "function" && node.value === "url" ? node.nodes[0]?.value : void 0;
34689
+ if (value && !/^(?:[a-z]+:|\/\/|#)/i.test(value)) requests.push(value);
34690
+ });
34691
+ for (const request of requests) {
34692
+ const resolved = await options.resolve(request, importer, { skipSelf: true });
34693
+ if (!resolved || resolved.external) continue;
34694
+ const sourcePath = getCssRealPath(parseRequest(resolved.id));
34695
+ const file = normalizeManagedTailwindcssEntryPath(path$1.resolve(path$1.dirname(importer), sourcePath));
34696
+ if (dependencies.has(file)) continue;
34697
+ dependencies.add(file);
34698
+ if (options.isManaged(file)) managed = true;
34699
+ else await visit(await fs$2.readFile(file, "utf8"), file);
34700
+ }
34701
+ };
34702
+ await visit(code, filename);
34703
+ return {
34704
+ managed,
34705
+ dependencies
34706
+ };
34707
+ }
34708
+ //#endregion
33946
34709
  //#region src/plugins/tailwindcss/vueStyle.ts
33947
34710
  /** 根据 SFC 外部样式的文件身份解析入口,避免依赖编译前后 CSS 文本一致。 */
33948
34711
  async function resolveVueStyleSource(request, resolve) {
@@ -34116,6 +34879,7 @@ function createTailwindcssPlugin(ctx) {
34116
34879
  const contextualSlots = /* @__PURE__ */ new Set();
34117
34880
  const dirtySlots = /* @__PURE__ */ new Set();
34118
34881
  const transformedSources = /* @__PURE__ */ new Map();
34882
+ const importedSources = /* @__PURE__ */ new Map();
34119
34883
  const previousEntrySources = /* @__PURE__ */ new Map();
34120
34884
  const resolvedEntryIndexes = /* @__PURE__ */ new Set();
34121
34885
  const loadedEntryIndexes = /* @__PURE__ */ new Set();
@@ -34242,8 +35006,8 @@ function createTailwindcssPlugin(ctx) {
34242
35006
  classSet: [],
34243
35007
  target: resolved.generatorTarget
34244
35008
  })];
34245
- const snapshot = compiler.mergeSnapshots(snapshots);
34246
- const seenEntries = /* @__PURE__ */ new Set();
35009
+ const snapshot = compiler.mergeSnapshots([...snapshots, ...Array.from(importedSources.values(), (source) => source.snapshot)]);
35010
+ const seenEntries = new Set(Array.from(importedSources.values()).flatMap((source) => source.entries));
34247
35011
  const styleExtension = ctx.configService.outputExtensions.wxss;
34248
35012
  const templateExtension = ctx.configService.outputExtensions.wxml;
34249
35013
  const scriptSourceMap = Boolean(resolvedConfig?.build.sourcemap);
@@ -34301,6 +35065,65 @@ function createTailwindcssPlugin(ctx) {
34301
35065
  applyOutputChunkTransform(output, transformed.code, transformed.map);
34302
35066
  }
34303
35067
  }
35068
+ function importedSourceKey(id) {
35069
+ const style = parseWeappVueStyleRequest(id);
35070
+ return style ? `${style.filename}?style=${style.index}` : id.split("?")[0];
35071
+ }
35072
+ async function transformImportedSource(code, id) {
35073
+ const style = parseWeappVueStyleRequest(id);
35074
+ const filename = requestSources.get(id) ?? style?.filename ?? normalizeFsResolvedId(id.split("?")[0], { stripLeadingNullByte: true });
35075
+ if (!style && !/\.(?:css|pcss|postcss)$/.test(filename)) return null;
35076
+ const query = new URLSearchParams(id.split("?")[1] ?? "");
35077
+ if (query.has("raw") || query.has("url")) return null;
35078
+ const imports = await findManagedStyleImports(code, filename, {
35079
+ resolve: this.resolve.bind(this),
35080
+ isManaged: (file) => isManagedTailwindcssEntry(ctx, file)
35081
+ });
35082
+ const key = importedSourceKey(id);
35083
+ if (!imports.managed) {
35084
+ const previous = importedSources.get(key);
35085
+ if (previous) {
35086
+ await (await getCompiler()).remove(previous.rootId);
35087
+ importedSources.delete(key);
35088
+ }
35089
+ return null;
35090
+ }
35091
+ const compiler = await getCompiler();
35092
+ const rootId = `${MANAGED_PLUGIN_NAME}:import:${key}`;
35093
+ const configuredSource = createTailwindV4SourceOptions(resolved, filename);
35094
+ const generated = await compiler.generate({
35095
+ id: rootId,
35096
+ target: resolved.generatorTarget,
35097
+ scanSources: true,
35098
+ sourceOptions: {
35099
+ ...configuredSource,
35100
+ cssEntries: [],
35101
+ cssSources: [...configuredSource.cssSources ?? [], {
35102
+ css: code,
35103
+ file: filename,
35104
+ base: path.dirname(filename),
35105
+ dependencies: [...imports.dependencies]
35106
+ }]
35107
+ },
35108
+ bareArbitraryValues: resolved.options.arbitraryValues?.bareArbitraryValues,
35109
+ styleOptions: typeof resolved.options.generator === "object" ? resolved.options.generator.styleOptions : void 0
35110
+ });
35111
+ importedSources.set(key, {
35112
+ rootId,
35113
+ snapshot: generated.snapshot,
35114
+ entries: [...imports.dependencies].flatMap((file) => {
35115
+ const index = parseManagedEntryIndex(file, entryIndex);
35116
+ return index === void 0 ? [] : [index];
35117
+ })
35118
+ });
35119
+ const dependencies = /* @__PURE__ */ new Set([...imports.dependencies, ...generated.dependencies]);
35120
+ for (const dependency of dependencies) this.addWatchFile(dependency);
35121
+ return {
35122
+ code: await stripResidualTailwindSourceDirectives((await compiler.transformCss(generated.rawCss, generated.snapshot, { isMainChunk: filename === path.resolve(ctx.configService.absoluteSrcRoot, "app.vue") })).css),
35123
+ map: null,
35124
+ meta: createStyleSourceMeta(dependencies)
35125
+ };
35126
+ }
34304
35127
  return [{
34305
35128
  name: MANAGED_PLUGIN_NAME,
34306
35129
  enforce: "pre",
@@ -34384,7 +35207,7 @@ function createTailwindcssPlugin(ctx) {
34384
35207
  if (resolved.options.generator === false || parseSidecarSourceRequest(id)?.dependencyOnly) return null;
34385
35208
  const sourceId = requestSources.get(id) ?? id;
34386
35209
  const entry = parseManagedEntryIndex(sourceId, entryIndex) ?? resolveAutoEntryIndex(sourceId, code);
34387
- if (entry === void 0) return null;
35210
+ if (entry === void 0) return code.includes("@import") || importedSources.has(importedSourceKey(id)) ? transformImportedSource.call(this, code, id) : null;
34388
35211
  const index = getSourceSlot(id, entry);
34389
35212
  dirtySlots.delete(index);
34390
35213
  loadedEntryIndexes.add(index);
@@ -34401,6 +35224,7 @@ function createTailwindcssPlugin(ctx) {
34401
35224
  };
34402
35225
  },
34403
35226
  shouldTransformCachedModule({ id }) {
35227
+ if (importedSources.has(importedSourceKey(id))) return true;
34404
35228
  const index = parseManagedEntryIndex(requestSources.get(id) ?? id, entryIndex);
34405
35229
  if (index !== void 0 && dirtySlots.has(getSourceSlot(id, index))) return true;
34406
35230
  },
@@ -35252,6 +36076,11 @@ function buildCompileVueFileOptions(ctx, pluginCtx, vuePath, isPage, isApp, conf
35252
36076
  const wevuMinify = isWevuMinifyEnabled(configService.weappViteConfig, configService.isDev);
35253
36077
  const jsonKind = isApp ? "app" : isPage ? "page" : "component";
35254
36078
  const sourceMap = isVueTransformSourceMapEnabled(configService);
36079
+ const stabilizeCssVarsRuntime = configService.isDev && resolveHmrRuntime({
36080
+ platform: configService.platform,
36081
+ configured: configService.weappViteConfig?.hmr?.runtime,
36082
+ compileHotReLoad: configService.projectPrivateConfig?.setting?.compileHotReLoad
36083
+ }) === "stateful-experimental";
35255
36084
  async function resolvePotentialVueSfcEntryId(candidate) {
35256
36085
  const trimmed = candidate?.trim();
35257
36086
  if (!trimmed) return;
@@ -35312,6 +36141,7 @@ function buildCompileVueFileOptions(ctx, pluginCtx, vuePath, isPage, isApp, conf
35312
36141
  isApp,
35313
36142
  skipComponentTransform: delegatesComponentRegistration,
35314
36143
  autoSetDataPick: isAutoSetDataPickEnabledWithPreset(configService.weappViteConfig),
36144
+ stabilizeCssVarsRuntime,
35315
36145
  bindingManifestSourceFile: resolveBindingManifestSourceFile(vuePath, configService),
35316
36146
  runtimeBindingManifest: configService.isDev ? "diagnostic" : "compact",
35317
36147
  pageLayout,
@@ -35386,7 +36216,7 @@ function createCompileVueFileOptions(ctx, pluginCtx, vuePath, isPage, isApp, con
35386
36216
  const appShellSignature = createCompilerAppShellSignature(isPage && !isApp ? resolvedAppShell : void 0);
35387
36217
  const cacheKey = getCompileVueFileOptionsCacheKey(vuePath, isPage, isApp, delegatesComponentRegistration, state.emitResolvedComponentEntries !== false, pageLayoutSignature, appShellSignature);
35388
36218
  const cached = state.compileOptionsCache?.get(cacheKey);
35389
- if (cached && compileOptionsOwners.get(cached) === pluginCtx) return cached;
36219
+ if (!configService.isDev && cached && compileOptionsOwners.get(cached) === pluginCtx) return cached;
35390
36220
  const created = buildCompileVueFileOptions(ctx, pluginCtx, vuePath, isPage, isApp, configService, state, delegatesComponentRegistration, pageLayout, appShell);
35391
36221
  compileOptionsOwners.set(created, pluginCtx);
35392
36222
  state.compileOptionsCache?.set(cacheKey, created);
@@ -35980,7 +36810,7 @@ async function refreshCompiledVueEntryCacheInDev(options) {
35980
36810
  }
35981
36811
  const currentStyleIndependentSignature = dirtyEntryId && filename.endsWith(".vue") && isVueStyleOnlyDirtyReasonSummary(ctx.runtimeState?.build?.hmr?.profile?.dirtyReasonSummary) ? resolveVueSfcStyleIndependentSignature(source, filename) : void 0;
35982
36812
  if (dirtyEntryId && filename.endsWith(".vue") && cached.styleIndependentSignature && currentStyleIndependentSignature && cached.styleIndependentSignature === currentStyleIndependentSignature && transformed.signature === cached.autoRoutesSignature && cached.source !== source) {
35983
- const { descriptor } = await readAndParseSfc(filename, {
36813
+ const { descriptor } = await readAndParseSfc$1(filename, {
35984
36814
  source,
35985
36815
  checkMtime: configService.isDev
35986
36816
  });
@@ -36270,7 +37100,7 @@ function emitAppShellAssetsIfNeeded(options) {
36270
37100
  //#endregion
36271
37101
  //#region src/plugins/vue/transform/bundle/emitCompiledEntry.ts
36272
37102
  function shouldReplaceAppScriptBundleEntry(options) {
36273
- if (!isAppVueFile(options.filename) || !options.isDev || !options.hasDevHmrEvent) return false;
37103
+ if (options.isBundledDev || !isAppVueFile(options.filename) || !options.isDev || !options.hasDevHmrEvent) return false;
36274
37104
  return true;
36275
37105
  }
36276
37106
  function hasUnresolvedModuleImportDeclaration(script) {
@@ -36305,7 +37135,8 @@ async function emitResolvedCompiledVueEntryAssets(options) {
36305
37135
  const shouldReplaceAppScript = shouldReplaceAppScriptBundleEntry({
36306
37136
  filename,
36307
37137
  isDev: configService.isDev,
36308
- hasDevHmrEvent: hmrState?.profile?.event !== void 0
37138
+ hasDevHmrEvent: hmrState?.profile?.event !== void 0,
37139
+ isBundledDev: state.isBundledDev
36309
37140
  });
36310
37141
  if (isAppVueFile(filename) && hasAppShellTemplate(result)) emitAppShellAssetsIfNeeded({
36311
37142
  bundle,
@@ -37107,6 +37938,7 @@ function createVueTransformPlugin(ctx, options = {}) {
37107
37938
  let appShell;
37108
37939
  let pageMatcher = null;
37109
37940
  let scanDirtySynced = false;
37941
+ let isBundledDev = false;
37110
37942
  const reExportResolutionCache = /* @__PURE__ */ new Map();
37111
37943
  const compileOptionsCache = /* @__PURE__ */ new Map();
37112
37944
  const componentMetaCache = /* @__PURE__ */ new Map();
@@ -37122,6 +37954,9 @@ function createVueTransformPlugin(ctx, options = {}) {
37122
37954
  }
37123
37955
  return {
37124
37956
  name: `${VUE_PLUGIN_NAME}:transform`,
37957
+ configResolved(config) {
37958
+ isBundledDev = config.command === "serve" && Boolean(config.experimental.bundledDev);
37959
+ },
37125
37960
  async buildStart() {
37126
37961
  scopedSlotModules.clear();
37127
37962
  emittedScopedSlotChunks.clear();
@@ -37165,7 +38000,7 @@ function createVueTransformPlugin(ctx, options = {}) {
37165
38000
  },
37166
38001
  scopedSlotModules,
37167
38002
  parseWeappVueStyleRequest: (id) => parseWeappVueStyleRequest(id) ?? null,
37168
- readAndParseSfc,
38003
+ readAndParseSfc: readAndParseSfc$1,
37169
38004
  createReadAndParseSfcOptions
37170
38005
  });
37171
38006
  },
@@ -37194,7 +38029,7 @@ function createVueTransformPlugin(ctx, options = {}) {
37194
38029
  scopedSlotModules,
37195
38030
  emittedScopedSlotChunks,
37196
38031
  classStyleRuntimeWarned,
37197
- readAndParseSfc,
38032
+ readAndParseSfc: readAndParseSfc$1,
37198
38033
  createReadAndParseSfcOptions
37199
38034
  });
37200
38035
  } finally {
@@ -37206,6 +38041,7 @@ function createVueTransformPlugin(ctx, options = {}) {
37206
38041
  async generateBundle(_options, bundle) {
37207
38042
  await emitVueBundleAssets(bundle, {
37208
38043
  ctx,
38044
+ isBundledDev,
37209
38045
  pluginCtx: this,
37210
38046
  compilationCache,
37211
38047
  appShell,
@@ -37773,9 +38609,13 @@ function mergeMiniprogram(options, ...configs) {
37773
38609
  }
37774
38610
  //#endregion
37775
38611
  //#region src/runtime/config/internal/merge/web.ts
37776
- function mergeWebPlugins(rawPlugins, webPlugin, runtimeProviderPlugin) {
38612
+ function mergeWebPlugins(rawPlugins, webPlugin, runtimeProviderPlugin, internalPlugins = []) {
37777
38613
  const remaining = [];
37778
- 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"));
37779
38619
  const collect = (option) => {
37780
38620
  if (!option) return;
37781
38621
  if (Array.isArray(option)) {
@@ -37790,6 +38630,7 @@ function mergeWebPlugins(rawPlugins, webPlugin, runtimeProviderPlugin) {
37790
38630
  return [
37791
38631
  runtimeProviderPlugin,
37792
38632
  webPlugin,
38633
+ ...internalPlugins,
37793
38634
  ...remaining
37794
38635
  ].filter(Boolean);
37795
38636
  }
@@ -37824,7 +38665,8 @@ function mergeWeb(options, ...configs) {
37824
38665
  hmrAcceptCode: resolveRuntimeProviderHmrFooter(runtimeProvider)
37825
38666
  }
37826
38667
  });
37827
- 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);
37828
38670
  inline.build ??= {};
37829
38671
  inline.build.outDir = web.outDir;
37830
38672
  inline.build.emptyOutDir ??= !isDev;
@@ -37940,6 +38782,7 @@ function createMergeFactories(options) {
37940
38782
  const subPackageRoots = Object.keys(configService.weappViteConfig?.subPackages ?? {});
37941
38783
  const sharedOutput = configService.options.chunksConfigured ? createSharedBuildOutput(configService, () => subPackageRoots, { runtime: "web" }) : void 0;
37942
38784
  return backend.driver.mergeConfig({ merge: (...backendConfigs) => mergeWeb({
38785
+ ctx,
37943
38786
  configService,
37944
38787
  config: currentOptions.config,
37945
38788
  web: currentOptions.weappWeb,
@@ -38560,7 +39403,7 @@ async function loadAppEntry(ctx, scanState) {
38560
39403
  const { path: appEntryPath } = appEntry;
38561
39404
  let configFromVue;
38562
39405
  if (!appConfigFile && vueAppPath) {
38563
- const { extractConfigFromVue } = await import("./file-BNDoQN7z.mjs");
39406
+ const { extractConfigFromVue } = await import("./file-BRwj-D25.mjs");
38564
39407
  configFromVue = await extractConfigFromVue(vueAppPath);
38565
39408
  if (configFromVue) appConfigFile = vueAppPath;
38566
39409
  }