weapp-vite 6.13.2 → 6.13.4

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,14 +1,13 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-twds-ZHy.mjs";
2
2
  import { n as applyWeappViteHostMeta } from "./pluginHost-SJdl15d3.mjs";
3
3
  import { n as configureLogger, r as logger_default } from "./logger-gutcwWKE.mjs";
4
- import { _ as templateExtensions, a as findJsEntry, c as findVueEntry, d as isTemplate, f as touch, g as supportedCssLangs, h as jsExtensions, i as findCssEntry, l as inlineAutoRoutesImports, m as configExtensions, n as extractConfigFromVue, o as findJsonEntry, s as findTemplateEntry, t as changeFileExtension, u as isJsOrTs, v as vueExtensions } from "./file-MiE605t6.mjs";
4
+ import { _ as templateExtensions, a as findJsEntry, c as findVueEntry, d as isTemplate, f as touch, g as supportedCssLangs, h as jsExtensions, i as findCssEntry, l as inlineAutoRoutesImports, m as configExtensions, n as extractConfigFromVue, o as findJsonEntry, s as findTemplateEntry, t as changeFileExtension, u as isJsOrTs, v as vueExtensions } from "./file-Cf3pf5w7.mjs";
5
5
  import { createRequire, isBuiltin } from "node:module";
6
- import { addExtension, defu, get, isEmptyObject, isObject, objectHash, removeExtension, removeExtensionDeep, set } from "@weapp-core/shared";
6
+ import { addExtension, defu, fs, get, isEmptyObject, isObject, objectHash, removeExtension, removeExtensionDeep, set } from "@weapp-core/shared";
7
7
  import { LRUCache } from "lru-cache";
8
8
  import path, { posix } from "pathe";
9
9
  import createDebug from "debug";
10
- import { normalize } from "node:path";
11
- import fs from "fs-extra";
10
+ import { normalize, relative, win32 } from "node:path";
12
11
  import { collectComponentPropsFromCode, collectRequireTokens, collectScriptSetupImportsFromCode, mayContainPlatformApiAccess, mayContainStaticRequireLiteral, parseJsLikeWithEngine, platformApiIdentifiers as platformApiIdentifiers$1 } from "@weapp-vite/ast";
13
12
  import { collectOnPageScrollPerformanceWarnings } from "@weapp-vite/ast/operations/onPageScroll";
14
13
  import { collectSetDataPickKeysFromTemplateCode } from "@weapp-vite/ast/operations/setDataPick";
@@ -237,8 +236,9 @@ function getAutoImportConfig(configService) {
237
236
  const weappConfig = configService.weappViteConfig;
238
237
  if (!weappConfig) return;
239
238
  const userConfigured = weappConfig.autoImportComponents ?? weappConfig.enhance?.autoImportComponents;
239
+ const enabledDefaults = createEnabledAutoImportComponents(configService);
240
240
  if (userConfigured === false) return;
241
- const normalizedConfig = userConfigured === true ? createEnabledAutoImportComponents(configService) : userConfigured;
241
+ const normalizedConfig = userConfigured === true ? enabledDefaults : userConfigured ? mergeAutoImportComponents(enabledDefaults, cloneAutoImportComponents(userConfigured), true) : void 0;
242
242
  const fallbackConfig = normalizedConfig === void 0 ? createDefaultAutoImportComponents(configService) : void 0;
243
243
  const baseConfig = cloneAutoImportComponents(normalizedConfig ?? fallbackConfig);
244
244
  const subPackageConfigs = weappConfig.subPackages;
@@ -1664,12 +1664,12 @@ function createVueComponentsDefinition(componentNames, getMetadata, options = {}
1664
1664
  "// oxlint-disable",
1665
1665
  "// ------",
1666
1666
  "// 由 weapp-vite autoImportComponents 生成",
1667
- "import type { ComponentOptionsMixin, DefineComponent, PublicProps } from 'wevu'",
1667
+ "import type { ComponentOptionsMixin, DefineComponent, PublicProps, WeappIntrinsicElementBaseAttributes } from 'wevu'",
1668
1668
  ...options.useTypedComponents ? ["import type { ComponentProp } from 'weapp-vite/typed-components'"] : [],
1669
1669
  "",
1670
1670
  "export {}",
1671
1671
  "",
1672
- "type WeappComponent<Props = Record<string, any>> = new (...args: any[]) => InstanceType<DefineComponent<{}, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {}, string, PublicProps, Props, {}>>",
1672
+ "type WeappComponent<Props = Record<string, any>> = new (...args: any[]) => InstanceType<DefineComponent<{}, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {}, string, PublicProps, Props & WeappIntrinsicElementBaseAttributes, {}>>",
1673
1673
  "type __WeappComponentImport<TModule, Fallback = {}> = 0 extends 1 & TModule ? Fallback : TModule extends { default: infer Component } ? Component & Fallback : Fallback",
1674
1674
  "",
1675
1675
  `declare module '${moduleName}' {`,
@@ -5248,9 +5248,13 @@ const SCRIPT_OR_DTS_EXTENSION_RE = /\.(?:[cm]?js|tsx?|jsx|d\.ts)$/;
5248
5248
  function createResolverHelpers(state) {
5249
5249
  const miniprogramDirCache = /* @__PURE__ */ new Map();
5250
5250
  const resolveCache = /* @__PURE__ */ new Map();
5251
+ const supportFileResolverComponents = /* @__PURE__ */ new Map();
5251
5252
  function getResolveCacheKey(componentName, importerBaseName) {
5252
5253
  return `${importerBaseName ?? ""}\0${componentName}`;
5253
5254
  }
5255
+ function getSupportFilesStrategy(resolver) {
5256
+ return resolver && typeof resolver.supportFilesStrategy === "string" ? resolver.supportFilesStrategy : "used";
5257
+ }
5254
5258
  function resolveWithResolver(resolver, componentName, baseName) {
5255
5259
  if (!resolver) return;
5256
5260
  const candidates = [componentName];
@@ -5326,11 +5330,28 @@ function createResolverHelpers(state) {
5326
5330
  } catch {}
5327
5331
  }
5328
5332
  function collectResolverComponents() {
5329
- return Object.fromEntries(state.resolvedResolverComponents);
5333
+ return Object.fromEntries([...state.resolvedResolverComponents, ...supportFileResolverComponents]);
5330
5334
  }
5331
5335
  function clearResolveCache() {
5332
5336
  resolveCache.clear();
5333
5337
  }
5338
+ function setSupportFileResolverComponents(components) {
5339
+ supportFileResolverComponents.clear();
5340
+ for (const [name, from] of Object.entries(components)) supportFileResolverComponents.set(name, from);
5341
+ }
5342
+ function clearSupportFileResolverComponents() {
5343
+ supportFileResolverComponents.clear();
5344
+ }
5345
+ function collectStaticResolverComponentsForSupportFiles() {
5346
+ const resolvers = getAutoImportConfig(state.ctx.configService)?.resolvers;
5347
+ if (!Array.isArray(resolvers)) return {};
5348
+ const allComponents = /* @__PURE__ */ new Map();
5349
+ for (const resolver of resolvers) {
5350
+ if (getSupportFilesStrategy(resolver) !== "full") continue;
5351
+ for (const [name, from] of Object.entries(resolver?.components ?? {})) allComponents.set(name, from);
5352
+ }
5353
+ return Object.fromEntries(allComponents);
5354
+ }
5334
5355
  function syncResolverComponentProps() {
5335
5356
  const resolverEntries = collectResolverComponents();
5336
5357
  state.resolverComponentsMapRef.value = resolverEntries;
@@ -5369,6 +5390,9 @@ function createResolverHelpers(state) {
5369
5390
  collectResolverComponents,
5370
5391
  clearResolveCache,
5371
5392
  syncResolverComponentProps,
5393
+ setSupportFileResolverComponents,
5394
+ clearSupportFileResolverComponents,
5395
+ collectStaticResolverComponentsForSupportFiles,
5372
5396
  resolveWithResolvers,
5373
5397
  resolveNavigationImport
5374
5398
  };
@@ -5503,6 +5527,27 @@ function createAutoImportService(ctx) {
5503
5527
  outputsHelpers.scheduleHtmlCustomDataWrite(removed || removedNames.length > 0);
5504
5528
  outputsHelpers.scheduleVueComponentsWrite(removed || removedNames.length > 0);
5505
5529
  },
5530
+ setSupportFileResolverComponents(components) {
5531
+ resolverHelpers.setSupportFileResolverComponents(components);
5532
+ outputsHelpers.scheduleManifestWrite(true);
5533
+ const typedSettings = getTypedComponentsSettings(ctx);
5534
+ const htmlSettings = getHtmlCustomDataSettings(ctx);
5535
+ const vueSettings = getVueComponentsSettings(ctx);
5536
+ if (typedSettings.enabled || htmlSettings.enabled) resolverHelpers.syncResolverComponentProps();
5537
+ if (typedSettings.enabled) outputsHelpers.scheduleTypedComponentsWrite(true);
5538
+ if (htmlSettings.enabled) outputsHelpers.scheduleHtmlCustomDataWrite(true);
5539
+ if (vueSettings.enabled) {
5540
+ resolverHelpers.syncResolverComponentProps();
5541
+ outputsHelpers.scheduleVueComponentsWrite(true);
5542
+ }
5543
+ },
5544
+ clearSupportFileResolverComponents() {
5545
+ resolverHelpers.clearSupportFileResolverComponents();
5546
+ resolverHelpers.syncResolverComponentProps();
5547
+ },
5548
+ collectStaticResolverComponentsForSupportFiles() {
5549
+ return resolverHelpers.collectStaticResolverComponentsForSupportFiles();
5550
+ },
5506
5551
  resolve(componentName, importerBaseName) {
5507
5552
  const local = registry.get(componentName);
5508
5553
  if (local) return local;
@@ -9918,7 +9963,7 @@ function asset(ctx) {
9918
9963
  const LEADING_DOT_SLASH_RE$2 = /^\.\//;
9919
9964
  const LEADING_SLASHES_RE$2 = /^\/+/;
9920
9965
  const GLOB_WILDCARD_RE = /[*?[{]/;
9921
- const TRAILING_SLASHES_RE$1 = /\/+$/;
9966
+ const TRAILING_SLASHES_RE$2 = /\/+$/;
9922
9967
  const AUTO_IMPORT_WATCHER_KEY = "__auto-import-vue-watcher__";
9923
9968
  const AUTO_IMPORT_CONFIG_SUFFIXES = configExtensions.map((ext) => `.${ext}`);
9924
9969
  const AUTO_IMPORT_JS_SUFFIXES = new Set(jsExtensions.map((ext) => `.${ext}`));
@@ -10024,7 +10069,7 @@ function registerAutoImportWatchTargets(state, globs, registrar, options = {}) {
10024
10069
  for (const pattern of globs ?? []) {
10025
10070
  const normalizedPattern = toPosixPath(pattern).replace(LEADING_DOT_SLASH_RE$2, "").replace(LEADING_SLASHES_RE$2, "");
10026
10071
  const wildcardIndex = normalizedPattern.search(GLOB_WILDCARD_RE);
10027
- const cleanedBase = (wildcardIndex >= 0 ? normalizedPattern.slice(0, wildcardIndex) : normalizedPattern).replace(TRAILING_SLASHES_RE$1, "");
10072
+ const cleanedBase = (wildcardIndex >= 0 ? normalizedPattern.slice(0, wildcardIndex) : normalizedPattern).replace(TRAILING_SLASHES_RE$2, "");
10028
10073
  if (!cleanedBase) continue;
10029
10074
  watchTargets.add(path.resolve(configService.absoluteSrcRoot, cleanedBase));
10030
10075
  }
@@ -10991,6 +11036,16 @@ function normalizeRouteRuleLayoutMeta(input) {
10991
11036
  disabled: record.disabled === true
10992
11037
  };
10993
11038
  }
11039
+ function compareRuleScore(left, right) {
11040
+ const maxLength = Math.max(left.length, right.length);
11041
+ for (let index = 0; index < maxLength; index += 1) {
11042
+ const leftValue = left[index] ?? 0;
11043
+ const rightValue = right[index] ?? 0;
11044
+ if (leftValue === rightValue) continue;
11045
+ return leftValue > rightValue ? 1 : -1;
11046
+ }
11047
+ return 0;
11048
+ }
10994
11049
  function resolveRouteRuleLayoutMeta(filename, configService) {
10995
11050
  const routeRules = configService.weappViteConfig?.routeRules;
10996
11051
  if (!routeRules) return;
@@ -11015,16 +11070,6 @@ function resolveRouteRuleLayoutMeta(filename, configService) {
11015
11070
  }
11016
11071
  return matched?.meta;
11017
11072
  }
11018
- function compareRuleScore(left, right) {
11019
- const maxLength = Math.max(left.length, right.length);
11020
- for (let index = 0; index < maxLength; index += 1) {
11021
- const leftValue = left[index] ?? 0;
11022
- const rightValue = right[index] ?? 0;
11023
- if (leftValue === rightValue) continue;
11024
- return leftValue > rightValue ? 1 : -1;
11025
- }
11026
- return 0;
11027
- }
11028
11073
  async function collectLayoutFiles(root) {
11029
11074
  const layoutMap = /* @__PURE__ */ new Map();
11030
11075
  const comparableRoot = normalizeComparablePath(root);
@@ -11435,1001 +11480,1032 @@ function emitNativeLayoutScriptChunkIfNeeded$1(options) {
11435
11480
  return true;
11436
11481
  }
11437
11482
  //#endregion
11438
- //#region src/plugins/hooks/useLoadEntry/loadEntry/emit.ts
11439
- const NON_VUE_PAGE_RE = /\.vue$|\.jsx$|\.tsx$/;
11440
- function prepareNormalizedEntries(options) {
11441
- const { entries, json, jsonPath, templatePath, id, skipOwnEntries, entriesMap, normalizeEntry, extendedLibManager, entryType, explicitEntryTypes } = options;
11442
- const filteredEntries = skipOwnEntries ? [] : entries.filter((entry) => !extendedLibManager.shouldIgnoreEntry(entry));
11443
- const normalizedEntries = skipOwnEntries ? [] : filteredEntries.map((entry) => normalizeEntry(entry, jsonPath));
11444
- if (!skipOwnEntries) for (const normalizedEntry of normalizedEntries) {
11445
- const resolvedEntryType = explicitEntryTypes?.get(normalizedEntry) ?? entryType ?? (json.component ? "component" : "page");
11446
- entriesMap.set(normalizedEntry, {
11447
- type: resolvedEntryType,
11448
- templatePath,
11449
- jsonPath,
11450
- json,
11451
- path: id
11452
- });
11453
- }
11454
- return normalizedEntries;
11483
+ //#region src/utils/wxmlScriptModule.ts
11484
+ const IMPORT_SJS_TAG_RE = /<import-sjs([\s\S]*?)>/g;
11485
+ const IMPORT_SJS_SRC_RE = /\bsrc\s*=\s*/g;
11486
+ const IMPORT_SJS_MODULE_RE = /\bmodule\s*=\s*/g;
11487
+ const DEFAULT_SCRIPT_MODULE_TAG_NAMES = ["wxs", "sjs"];
11488
+ const DEFAULT_SCRIPT_MODULE_TAG_BY_EXTENSION = Object.freeze({
11489
+ wxs: "wxs",
11490
+ sjs: "sjs"
11491
+ });
11492
+ const SCRIPT_MODULE_IMPORT_ATTRS = Object.freeze({
11493
+ "wxs": ["src"],
11494
+ "sjs": ["src"],
11495
+ "import-sjs": ["from"]
11496
+ });
11497
+ function resolveScriptModuleTagByPlatform(platform, scriptModuleExtension) {
11498
+ return getPlatformScriptModuleTag(platform, scriptModuleExtension);
11455
11499
  }
11456
- async function emitEntryOutput(options) {
11457
- const { pluginCtx, id, type, json: initialJson, jsonPath, templatePath, isPluginBuild, normalizedEntries, pluginResolvedRecords, pluginJsonPathForRegistration, pluginJsonForRegistration, resolveEntriesWithCache, entryResolveRoot, configService, wxmlService, resolvedEntryMap, loadedEntrySet, dirtyEntrySet, replaceLayoutDependencies, emitEntriesChunks, registerJsonAsset, existsCache, pathExistsTtlMs, debug, relativeCwdId, getTime } = options;
11458
- let json = initialJson;
11459
- async function emitNativeLayoutAssets(layoutBasePath) {
11460
- if (typeof pluginCtx.emitFile !== "function") return;
11461
- const resolvedOptions = resolveNativeLayoutOutputOptions({
11462
- configService,
11463
- layoutBasePath,
11464
- outputExtensions: configService.outputExtensions
11465
- });
11466
- if (!resolvedOptions) return;
11467
- const assets = await collectNativeLayoutAssets(layoutBasePath);
11468
- const emittedLayoutAssets = pluginCtx.__weappViteNativeLayoutAssets ?? (pluginCtx.__weappViteNativeLayoutAssets = /* @__PURE__ */ new Set());
11469
- if (assets.json) registerJsonAsset({
11470
- jsonPath: assets.json,
11471
- json: JSON.parse(await fs$1.readFile(assets.json, "utf8")),
11472
- type: "component"
11473
- });
11474
- const assetEntries = await resolveNativeLayoutStaticAssetEntries({
11475
- assets,
11476
- resolvedOptions,
11477
- readFile: fs$1.readFile
11478
- });
11479
- for (const asset of assetEntries) {
11480
- if (emittedLayoutAssets.has(asset.fileName)) continue;
11481
- emittedLayoutAssets.add(asset.fileName);
11482
- pluginCtx.emitFile({
11483
- type: "asset",
11484
- fileName: asset.fileName,
11485
- source: asset.source
11486
- });
11487
- }
11488
- emitNativeLayoutScriptChunkIfNeeded$1({
11489
- pluginCtx,
11490
- scriptId: assets.script,
11491
- fileName: `${resolvedOptions.relativeBase}.${resolvedOptions.scriptExtension}`
11492
- });
11493
- }
11494
- const shouldSkipEntries = Boolean(options.skipEntries);
11495
- const resolvedIds = shouldSkipEntries ? [] : normalizedEntries.length ? await resolveEntriesWithCache(pluginCtx, normalizedEntries, entryResolveRoot) : [];
11496
- debug?.(`resolvedIds ${relativeCwdId} 耗时 ${getTime()}`);
11497
- const pendingResolvedIds = [];
11498
- const combinedResolved = shouldSkipEntries ? [] : pluginResolvedRecords ? isPluginBuild ? pluginResolvedRecords : [...resolvedIds, ...pluginResolvedRecords] : resolvedIds;
11499
- const pluginEntrySet = shouldSkipEntries || !pluginResolvedRecords ? void 0 : new Set(pluginResolvedRecords.map((record) => record.entry));
11500
- for (const { entry, resolvedId } of combinedResolved) {
11501
- if (!resolvedId) {
11502
- if (pluginEntrySet?.has(entry)) logger_default.warn(`没有找到插件入口 \`${entry}\` 对应的脚本文件,请检查路径是否正确!`);
11503
- else logger_default.warn(`没有找到 \`${entry}\` 的入口文件,请检查路径是否正确!`);
11504
- continue;
11505
- }
11506
- const normalizedResolvedId = normalizeFsResolvedId(resolvedId.id);
11507
- if (normalizedResolvedId && !isSkippableResolvedId(normalizedResolvedId) && path.isAbsolute(normalizedResolvedId)) addNormalizedWatchFile(pluginCtx, normalizedResolvedId);
11508
- if (normalizedResolvedId && !isSkippableResolvedId(normalizedResolvedId)) resolvedEntryMap.set(normalizedResolvedId, resolvedId);
11509
- const isDirtyEntry = dirtyEntrySet.has(normalizedResolvedId);
11510
- if (!isDirtyEntry && loadedEntrySet.has(normalizedResolvedId)) continue;
11511
- pendingResolvedIds.push(resolvedId);
11512
- if (isDirtyEntry) dirtyEntrySet.delete(normalizedResolvedId);
11513
- }
11514
- if (pendingResolvedIds.length) await Promise.all(emitEntriesChunks.call(pluginCtx, pendingResolvedIds));
11515
- debug?.(`emitEntriesChunks ${relativeCwdId} 耗时 ${getTime()}`);
11516
- let code = await readFile$1(id, { checkMtime: configService.isDev });
11517
- if (type === "page" && templatePath && !NON_VUE_PAGE_RE.test(id)) {
11518
- replaceLayoutDependencies(id, []);
11519
- const layoutPlan = await resolvePageLayoutPlan(code, id, configService);
11520
- if (layoutPlan) {
11521
- const layoutDependencies = /* @__PURE__ */ new Set();
11522
- for (const file of await expandResolvedPageLayoutFiles(layoutPlan.layouts)) {
11523
- addNormalizedWatchFile(pluginCtx, file);
11524
- layoutDependencies.add(normalizeFsResolvedId(file));
11525
- }
11526
- replaceLayoutDependencies(id, layoutDependencies);
11527
- const nativeTemplate = await readFile$1(templatePath, { checkMtime: configService.isDev });
11528
- const transformed = applyPageLayoutPlanToNativePage({
11529
- script: code,
11530
- template: nativeTemplate,
11531
- config: JSON.stringify(json)
11532
- }, id, layoutPlan);
11533
- code = transformed.script ?? code;
11534
- if (transformed.config) json = JSON.parse(transformed.config);
11535
- if (transformed.template && wxmlService) {
11536
- const token = wxmlService.analyze(transformed.template);
11537
- wxmlService.tokenMap.set(templatePath, token);
11538
- wxmlService.setWxmlComponentsMap(templatePath, token.components);
11539
- }
11540
- for (const layout of layoutPlan.layouts) if (layout.kind === "native") await emitNativeLayoutAssets(layout.file);
11541
- }
11542
- code = injectNativePageLayoutRuntime(code, id, layoutPlan) ?? code;
11543
- }
11544
- if (!isPluginBuild || type !== "app") registerJsonAsset({
11545
- jsonPath,
11546
- json,
11547
- type
11548
- });
11549
- if (pluginJsonPathForRegistration && pluginJsonForRegistration) registerJsonAsset({
11550
- jsonPath: pluginJsonPathForRegistration,
11551
- json: pluginJsonForRegistration,
11552
- type: "plugin"
11553
- });
11554
- const styleImports = await collectStyleImports(pluginCtx, id, existsCache, pathExistsTtlMs);
11555
- debug?.(`loadEntry ${relativeCwdId} 耗时 ${getTime()}`);
11556
- if (styleImports.length === 0) return { code };
11557
- const ms = new MagicString(code);
11558
- for (const styleImport of styleImports) ms.prepend(`import '${styleImport}';\n`);
11559
- return { code: ms.toString() };
11500
+ function normalizeScriptModuleExtension(scriptModuleExtension) {
11501
+ if (!scriptModuleExtension) return;
11502
+ return scriptModuleExtension.startsWith(".") ? scriptModuleExtension.slice(1) : scriptModuleExtension;
11560
11503
  }
11561
- //#endregion
11562
- //#region src/plugins/hooks/useLoadEntry/loadEntry/resolve.ts
11563
- function createEntryResolver(configService) {
11564
- const entryResolutionCache = /* @__PURE__ */ new Map();
11565
- async function resolveEntryWithCache(pluginCtx, absPath) {
11566
- const normalized = path.normalize(absPath);
11567
- if (entryResolutionCache.has(normalized)) return entryResolutionCache.get(normalized) ?? null;
11568
- let resolvedSource = normalized;
11569
- if (!path.extname(normalized)) {
11570
- const matched = await resolveEntryPath(normalized, createCachedEntryResolveOptions(configService ?? {}, { kind: "default" }));
11571
- if (matched) resolvedSource = matched;
11572
- }
11573
- const resolvedId = await pluginCtx.resolve(resolvedSource) ?? null;
11574
- entryResolutionCache.set(normalized, resolvedId);
11575
- return resolvedId;
11576
- }
11577
- async function resolveEntriesWithCache(pluginCtx, entries, absoluteRoot) {
11578
- return Promise.all(entries.filter((entry) => !entry.includes(":")).map(async (entry) => {
11579
- return {
11580
- entry,
11581
- resolvedId: await resolveEntryWithCache(pluginCtx, path.resolve(absoluteRoot, entry))
11582
- };
11583
- }));
11584
- }
11585
- return {
11586
- resolveEntryWithCache,
11587
- resolveEntriesWithCache,
11588
- invalidate() {
11589
- entryResolutionCache.clear();
11590
- }
11591
- };
11504
+ function getDefaultScriptModuleTagByExtension(scriptModuleExtension) {
11505
+ if (!scriptModuleExtension) return "wxs";
11506
+ return DEFAULT_SCRIPT_MODULE_TAG_BY_EXTENSION[normalizeScriptModuleExtension(scriptModuleExtension)] ?? "wxs";
11592
11507
  }
11593
- //#endregion
11594
- //#region src/plugins/utils/vueSfc.ts
11595
- function createSfcResolveSrcOptions(pluginCtx, configService) {
11596
- return {
11597
- resolveId: async (source, importer) => {
11598
- if (typeof pluginCtx.resolve !== "function") return;
11599
- return (await pluginCtx.resolve(source, importer))?.id;
11600
- },
11601
- checkMtime: getSfcCheckMtime(configService)
11602
- };
11508
+ function resolveScriptModuleTagName(options) {
11509
+ if (options?.scriptModuleTag) return options.scriptModuleTag;
11510
+ return resolveScriptModuleTagByPlatform(options?.platform, options?.scriptModuleExtension) ?? getDefaultScriptModuleTagByExtension(options?.scriptModuleExtension);
11603
11511
  }
11604
- function createReadAndParseSfcOptions(pluginCtx, configService, options) {
11605
- const resolveCheckMtime = getSfcCheckMtime(configService);
11606
- return {
11607
- source: options?.source,
11608
- checkMtime: options?.checkMtime ?? resolveCheckMtime,
11609
- resolveSrc: createSfcResolveSrcOptions(pluginCtx, configService)
11610
- };
11512
+ function getDerivedScriptModuleTagNames() {
11513
+ return MINI_PROGRAM_PLATFORM_ADAPTERS.flatMap((adapter) => Object.values(adapter.scriptModuleTagByExtension ?? {})).filter((value) => typeof value === "string" && value.length > 0);
11514
+ }
11515
+ function getScriptModuleTagNames() {
11516
+ return [...new Set([...DEFAULT_SCRIPT_MODULE_TAG_NAMES, ...getDerivedScriptModuleTagNames()])];
11517
+ }
11518
+ function isScriptModuleTagName(tagName) {
11519
+ return typeof tagName === "string" && getScriptModuleTagNames().includes(tagName);
11520
+ }
11521
+ function getScriptModuleImportAttrs(tagName) {
11522
+ if (!tagName) return;
11523
+ return SCRIPT_MODULE_IMPORT_ATTRS[tagName];
11524
+ }
11525
+ function isScriptModuleImportAttr(tagName, attrName) {
11526
+ if (!tagName) return false;
11527
+ return getScriptModuleImportAttrs(tagName)?.includes(attrName) === true;
11528
+ }
11529
+ function shouldNormalizeScriptModuleAttributes(tagName) {
11530
+ return tagName === "import-sjs";
11531
+ }
11532
+ function normalizeImportSjsAttributes(source) {
11533
+ return source.replace(IMPORT_SJS_TAG_RE, (tag) => {
11534
+ return tag.replace(IMPORT_SJS_SRC_RE, "from=").replace(IMPORT_SJS_MODULE_RE, "name=");
11535
+ });
11611
11536
  }
11612
11537
  //#endregion
11613
- //#region src/plugins/vue/transform/usingComponentResolver.ts
11614
- const JS_LIKE_FILE_RE = /\.(?:[cm]?ts|[cm]?js)$/;
11615
- async function resolveUsingComponentReference(ctx, configService, reExportResolutionCache, importSource, importerFilename, info) {
11616
- const resolved = await ctx.resolve(importSource, importerFilename);
11617
- let clean = resolved?.id ? normalizeFsResolvedId(resolved.id) : void 0;
11618
- if ((!clean || !path.isAbsolute(clean)) && info?.fallbackRelativeImporterDir && importSource.startsWith(".")) clean = path.resolve(path.dirname(importerFilename), importSource);
11619
- if (!clean) return {
11620
- resolvedId: void 0,
11621
- from: void 0
11538
+ //#region src/wxs/utils.ts
11539
+ function normalizeWxsFilename(value, extension = "wxs") {
11540
+ const normalized = extension.startsWith(".") ? extension.slice(1) : extension;
11541
+ let filename = value;
11542
+ filename = filename.replace(/\.[jt]s$/i, "");
11543
+ filename = filename.replace(/\.(wxs|sjs)$/i, "");
11544
+ return addExtension(filename, `.${normalized}`);
11545
+ }
11546
+ //#endregion
11547
+ //#region src/wxs/index.ts
11548
+ function transformWxsCode(code, options) {
11549
+ const filename = options?.filename ?? "script.ts";
11550
+ const extension = options?.extension ?? "wxs";
11551
+ const importees = [];
11552
+ const maybePushImportee = (value) => {
11553
+ if (typeof value !== "string" || !value) return;
11554
+ importees.push({ source: value });
11622
11555
  };
11623
- if (isSkippableResolvedId(clean)) return {
11624
- resolvedId: void 0,
11625
- from: void 0
11556
+ const tryCollectArgument = (path) => {
11557
+ const node = path.node;
11558
+ if (t.isStringLiteral(node)) {
11559
+ maybePushImportee(node.value);
11560
+ return;
11561
+ }
11562
+ if (t.isTemplateLiteral(node) && node.expressions.length === 0) {
11563
+ maybePushImportee(node.quasis.map((q) => q.value.cooked ?? q.value.raw ?? "").join(""));
11564
+ return;
11565
+ }
11566
+ try {
11567
+ const evaluated = path.evaluate();
11568
+ if (evaluated.confident) maybePushImportee(evaluated.value);
11569
+ } catch {}
11626
11570
  };
11627
- if (path.isAbsolute(clean)) {
11628
- const resolvedEntry = await resolveEntryPath(clean, createCachedEntryResolveOptions(configService ?? {}, { kind: info?.kind ?? "default" }));
11629
- if (resolvedEntry) clean = resolvedEntry;
11630
- }
11631
- if (info?.kind === "named" && info.importedName && JS_LIKE_FILE_RE.test(clean)) {
11632
- const exportName = info.importedName;
11633
- const mapped = await resolveReExportedName(clean, exportName, {
11634
- astEngine: resolveAstEngine(configService.weappViteConfig),
11635
- cache: reExportResolutionCache,
11636
- maxDepth: 4,
11637
- readFile: (file) => readFile$1(file, { checkMtime: getReadFileCheckMtime(configService) }),
11638
- resolveId: async (source, importer) => {
11639
- const hop = await ctx.resolve(source, importer);
11640
- const hopId = hop?.id ? normalizeFsResolvedId(hop.id) : void 0;
11641
- if (isSkippableResolvedId(hopId)) return;
11642
- return hopId;
11643
- }
11644
- });
11645
- if (mapped) clean = mapped;
11646
- }
11647
11571
  return {
11648
- resolvedId: clean,
11649
- from: usingComponentFromResolvedFile(clean, configService)
11650
- };
11651
- }
11652
- async function resolveUsingComponentPath(ctx, configService, reExportResolutionCache, importSource, importerFilename, info) {
11653
- return (await resolveUsingComponentReference(ctx, configService, reExportResolutionCache, importSource, importerFilename, info)).from;
11654
- }
11655
- function createUsingComponentPathResolver(ctx, configService, reExportResolutionCache) {
11656
- return async (importSource, importerFilename, info) => {
11657
- return resolveUsingComponentPath(ctx, configService, reExportResolutionCache, importSource, importerFilename, info);
11572
+ result: babel.transformSync(code, {
11573
+ babelrc: false,
11574
+ configFile: false,
11575
+ presets: [["@babel/preset-env"], ["@babel/preset-typescript"]],
11576
+ filename,
11577
+ plugins: [{ visitor: {
11578
+ Directive: { enter(p) {
11579
+ p.remove();
11580
+ } },
11581
+ CallExpression: { enter(p) {
11582
+ const node = p.node;
11583
+ if (!t.isIdentifier(node.callee, { name: "require" })) return;
11584
+ if (node.arguments.length !== 1) return;
11585
+ tryCollectArgument(p.get("arguments.0"));
11586
+ const arg = node.arguments[0];
11587
+ if (t.isStringLiteral(arg)) arg.value = normalizeWxsFilename(arg.value, extension);
11588
+ } },
11589
+ ExpressionStatement(p) {
11590
+ const expression = p.node.expression;
11591
+ if (expression.type === "CallExpression" && expression.callee.type === "MemberExpression" && t.isIdentifier(expression.callee.object) && expression.callee.object.name === "Object" && t.isIdentifier(expression.callee.property) && expression.callee.property.name === "defineProperty" && expression.arguments.length >= 2 && t.isIdentifier(expression.arguments[0]) && expression.arguments[0].name === "exports" && t.isStringLiteral(expression.arguments[1]) && expression.arguments[1].value === "__esModule") p.remove();
11592
+ },
11593
+ NewExpression: { enter(p) {
11594
+ const node = p.node;
11595
+ if (t.isIdentifier(node.callee, { name: "RegExp" })) p.replaceWith(t.callExpression(t.identifier("getRegExp"), node.arguments));
11596
+ else if (t.isIdentifier(node.callee, { name: "Date" })) p.replaceWith(t.callExpression(t.identifier("getDate"), node.arguments));
11597
+ } },
11598
+ RegExpLiteral: { enter(p) {
11599
+ const args = [t.stringLiteral(p.node.pattern)];
11600
+ if (p.node.flags) args.push(t.stringLiteral(p.node.flags));
11601
+ p.replaceWith(t.callExpression(t.identifier("getRegExp"), args));
11602
+ } },
11603
+ MemberExpression: { enter(p) {
11604
+ const node = p.node;
11605
+ if (!t.isIdentifier(node.object, { name: "exports" })) return;
11606
+ const moduleExports = t.memberExpression(t.identifier("module"), t.identifier("exports"));
11607
+ p.replaceWith(t.memberExpression(moduleExports, node.property, node.computed, node.optional));
11608
+ } },
11609
+ ImportDeclaration: { enter(p) {
11610
+ maybePushImportee(p.node.source.value);
11611
+ } }
11612
+ } }]
11613
+ }),
11614
+ importees
11658
11615
  };
11659
11616
  }
11660
11617
  //#endregion
11661
- //#region src/plugins/hooks/useLoadEntry/loadEntry/template.ts
11662
- function collectVueTemplateComponentNames(template, filename) {
11663
- return collectVueTemplateTags(template, {
11664
- filename,
11665
- warnLabel: "自动 usingComponents",
11666
- shouldCollect: (tag) => VUE_COMPONENT_TAG_RE.test(tag)
11667
- });
11618
+ //#region src/wxml/handle.ts
11619
+ const handleCache = /* @__PURE__ */ new WeakMap();
11620
+ const inlineWxsTransformCache = /* @__PURE__ */ new Map();
11621
+ const INLINE_WXS_CACHE_LIMIT = 256;
11622
+ function createCacheKey$1(options) {
11623
+ const extension = options.scriptModuleExtension ?? "";
11624
+ const tag = options.scriptModuleTag ?? "";
11625
+ const templateExt = options.templateExtension ?? "";
11626
+ return `${options.removeComment ? 1 : 0}|${options.transformEvent ? 1 : 0}|${extension}|${tag}|${templateExt}`;
11668
11627
  }
11669
- function collectVueTemplateAutoImportTags(template, filename) {
11670
- return collectVueTemplateTags(template, {
11671
- filename,
11672
- warnLabel: "自动导入标签",
11673
- shouldCollect: isAutoImportCandidateTag
11674
- });
11628
+ function getCachedResult(data, cacheKey) {
11629
+ return handleCache.get(data)?.get(cacheKey);
11675
11630
  }
11676
- function collectScriptSetupImports(scriptSetup, templateComponentNames, options) {
11677
- return collectScriptSetupImportsFromCode(scriptSetup, templateComponentNames, options);
11631
+ function setCachedResult(data, cacheKey, result) {
11632
+ let cacheForToken = handleCache.get(data);
11633
+ if (!cacheForToken) {
11634
+ cacheForToken = /* @__PURE__ */ new Map();
11635
+ handleCache.set(data, cacheForToken);
11636
+ }
11637
+ cacheForToken.set(cacheKey, result);
11638
+ return result;
11678
11639
  }
11679
- async function scanTemplateEntry(pluginCtx, id, scanTemplateEntryFn, existsCache, ttlMs) {
11680
- return ensureTemplateScanned(pluginCtx, id, scanTemplateEntryFn, existsCache, ttlMs);
11640
+ function getCachedInlineWxsTransform(code, extension) {
11641
+ const key = `${extension}::${code}`;
11642
+ const cached = inlineWxsTransformCache.get(key);
11643
+ if (cached) {
11644
+ inlineWxsTransformCache.delete(key);
11645
+ inlineWxsTransformCache.set(key, cached);
11646
+ return cached;
11647
+ }
11648
+ const transformed = transformWxsCode(code, { extension });
11649
+ inlineWxsTransformCache.set(key, transformed);
11650
+ if (inlineWxsTransformCache.size > INLINE_WXS_CACHE_LIMIT) {
11651
+ const firstKey = inlineWxsTransformCache.keys().next().value;
11652
+ if (firstKey) inlineWxsTransformCache.delete(firstKey);
11653
+ }
11654
+ return transformed;
11681
11655
  }
11682
- async function applyScriptSetupUsingComponents(options) {
11683
- const { pluginCtx, vueEntryPath, templatePath, json, configService, wxmlService, reExportResolutionCache } = options;
11684
- try {
11685
- const { descriptor, errors } = await readAndParseSfc(vueEntryPath, { ...createReadAndParseSfcOptions(pluginCtx, configService) });
11686
- if (!errors?.length && descriptor?.template && !templatePath) {
11687
- const tags = collectVueTemplateAutoImportTags(descriptor.template.content, vueEntryPath);
11688
- if (tags.size) {
11689
- const components = Object.fromEntries(Array.from(tags, (tag) => [tag, [{
11690
- start: 0,
11691
- end: 0
11692
- }]]));
11693
- wxmlService?.setWxmlComponentsMap(vueEntryPath, components);
11694
- }
11695
- }
11696
- if (!errors?.length && descriptor?.scriptSetup && descriptor?.template) {
11697
- const templateComponentNames = collectVueTemplateComponentNames(descriptor.template.content, vueEntryPath);
11698
- if (templateComponentNames.size) {
11699
- const astEngine = resolveAstEngine(configService.weappViteConfig);
11700
- const imports = collectScriptSetupImports(descriptor.scriptSetup.content, templateComponentNames, { astEngine });
11701
- if (imports.length) {
11702
- const usingComponents = json && typeof json.usingComponents === "object" && json.usingComponents && !Array.isArray(json.usingComponents) ? json.usingComponents : {};
11703
- for (const { localName, importSource, importedName, kind } of imports) {
11704
- let { from } = await resolveUsingComponentReference(pluginCtx, configService, reExportResolutionCache, importSource, vueEntryPath, {
11705
- kind,
11706
- importedName,
11707
- fallbackRelativeImporterDir: true
11708
- });
11709
- if (!from && importSource.startsWith("/")) from = removeExtensionDeep(importSource);
11710
- if (!from) continue;
11711
- if (Reflect.has(usingComponents, localName) && usingComponents[localName] !== from) logger_default.warn(`[自动 usingComponents] 冲突:${vueEntryPath} 中 usingComponents['${localName}']='${usingComponents[localName]}' 将被 <script setup> 导入覆盖为 '${from}'`);
11712
- usingComponents[localName] = from;
11713
- }
11714
- json.usingComponents = usingComponents;
11715
- }
11716
- }
11656
+ function handleWxml(data, options) {
11657
+ const opts = defu(options, {
11658
+ removeComment: true,
11659
+ transformEvent: true,
11660
+ scriptModuleExtension: void 0,
11661
+ scriptModuleTag: void 0,
11662
+ templateExtension: void 0
11663
+ });
11664
+ const cacheKey = createCacheKey$1(opts);
11665
+ const cached = getCachedResult(data, cacheKey);
11666
+ if (cached) return cached;
11667
+ const { code, removalRanges = [], commentTokens = [], eventTokens = [], directiveTokens = [], tagNameTokens = [], inlineWxsTokens = [], removeWxsLangAttrTokens = [], scriptModuleTagTokens = [], wxsImportNormalizeTokens = [], templateImportNormalizeTokens = [], components, deps } = data;
11668
+ const normalizedScriptExtension = opts.scriptModuleExtension?.startsWith(".") ? opts.scriptModuleExtension.slice(1) : opts.scriptModuleExtension;
11669
+ const normalizedTemplateExtension = opts.templateExtension?.startsWith(".") ? opts.templateExtension.slice(1) : opts.templateExtension;
11670
+ const resolvedScriptTag = resolveScriptModuleTagName({
11671
+ scriptModuleExtension: normalizedScriptExtension,
11672
+ scriptModuleTag: opts.scriptModuleTag
11673
+ });
11674
+ const shouldNormalizeImports = wxsImportNormalizeTokens.length > 0;
11675
+ const shouldNormalizeTemplateImports = templateImportNormalizeTokens.length > 0 && normalizedTemplateExtension;
11676
+ const shouldRemoveLang = removeWxsLangAttrTokens.length > 0;
11677
+ const shouldTransformInlineWxs = inlineWxsTokens.length > 0;
11678
+ const shouldTransformEvents = opts.transformEvent && eventTokens.length > 0;
11679
+ const shouldTransformDirectives = directiveTokens.length > 0;
11680
+ const shouldTransformTagNames = tagNameTokens.length > 0;
11681
+ const shouldTransformScriptModuleTags = resolvedScriptTag !== "wxs" && scriptModuleTagTokens.length > 0;
11682
+ const shouldRemoveConditionals = removalRanges.length > 0;
11683
+ const shouldRemoveComments = opts.removeComment && commentTokens.length > 0;
11684
+ if (!shouldNormalizeImports && !shouldNormalizeTemplateImports && !shouldRemoveLang && !shouldTransformInlineWxs && !shouldTransformEvents && !shouldTransformDirectives && !shouldTransformTagNames && !shouldTransformScriptModuleTags && !shouldRemoveConditionals && !shouldRemoveComments) return setCachedResult(data, cacheKey, {
11685
+ code,
11686
+ components,
11687
+ deps
11688
+ });
11689
+ const ms = new MagicString(code);
11690
+ if (shouldNormalizeImports) for (const { start, end, value } of wxsImportNormalizeTokens) ms.update(start, end, normalizeWxsFilename(value, normalizedScriptExtension ?? "wxs"));
11691
+ if (shouldNormalizeTemplateImports) for (const { start, end, value } of templateImportNormalizeTokens) {
11692
+ let nextValue = changeFileExtension(value, normalizedTemplateExtension);
11693
+ if (value.startsWith("./") && !nextValue.startsWith("./") && !nextValue.startsWith("../") && !nextValue.startsWith("/")) nextValue = `./${nextValue}`;
11694
+ ms.update(start, end, nextValue);
11695
+ }
11696
+ if (shouldRemoveLang) for (const { start, end } of removeWxsLangAttrTokens) ms.update(start, end, "");
11697
+ if (shouldTransformInlineWxs) for (const { end, start, value } of inlineWxsTokens) {
11698
+ const { result } = getCachedInlineWxsTransform(value, normalizedScriptExtension ?? "wxs");
11699
+ if (result?.code) ms.update(start, end, `\n${result.code}`);
11700
+ }
11701
+ if (shouldTransformScriptModuleTags) {
11702
+ const visited = /* @__PURE__ */ new Set();
11703
+ for (const { start, end } of scriptModuleTagTokens) {
11704
+ const key = `${start}:${end}`;
11705
+ if (visited.has(key)) continue;
11706
+ visited.add(key);
11707
+ ms.update(start, end, resolvedScriptTag);
11717
11708
  }
11718
- } catch (error) {
11719
- const message = error instanceof Error ? error.message : String(error);
11720
- logger_default.warn(`[自动 usingComponents] 解析失败:${vueEntryPath}:${message}`);
11721
11709
  }
11710
+ if (shouldTransformEvents) for (const { end, start, value } of eventTokens) ms.update(start, end, value);
11711
+ if (shouldTransformDirectives) for (const { end, start, value } of directiveTokens) ms.update(start, end, value);
11712
+ if (shouldTransformTagNames) for (const { end, start, value } of tagNameTokens) ms.update(start, end, value);
11713
+ if (shouldRemoveConditionals) {
11714
+ for (const { start, end } of removalRanges) if (end > start) ms.remove(start, end);
11715
+ }
11716
+ if (shouldRemoveComments) for (const { end, start } of commentTokens) ms.remove(start, end);
11717
+ return setCachedResult(data, cacheKey, {
11718
+ code: shouldNormalizeScriptModuleAttributes(resolvedScriptTag) ? normalizeImportSjsAttributes(ms.toString()) : ms.toString(),
11719
+ components,
11720
+ deps
11721
+ });
11722
11722
  }
11723
- //#endregion
11724
- //#region src/plugins/hooks/useLoadEntry/loadEntry/index.ts
11725
- function createStopwatch() {
11726
- const start = performance$1.now();
11727
- return () => `${(performance$1.now() - start).toFixed(2)}ms`;
11728
- }
11729
- function createEntryLoader(options) {
11730
- const { ctx, entriesMap, loadedEntrySet, dirtyEntrySet, resolvedEntryMap, replaceLayoutDependencies, normalizeEntry, registerJsonAsset, scanTemplateEntry: scanTemplateEntryFn, emitEntriesChunks, applyAutoImports, extendedLibManager, debug } = options;
11731
- const isPluginBuild = (options.buildTarget ?? "app") === "plugin";
11732
- const { jsonService, configService, wxmlService } = ctx;
11733
- const existsCache = /* @__PURE__ */ new Map();
11734
- const pathExistsTtlMs = getPathExistsTtlMs(configService);
11735
- const reExportResolutionCache = /* @__PURE__ */ new Map();
11736
- const entryResolver = createEntryResolver(configService);
11737
- const appEntriesCache = {};
11738
- const appEntryOutputCache = {};
11739
- const emittedScriptlessVueLayoutJs = /* @__PURE__ */ new Set();
11740
- const scriptlessVueLayoutDecisionCache = /* @__PURE__ */ new Map();
11741
- let resolveCacheVersion = 0;
11742
- const shouldEmitScriptlessVueLayoutJs$1 = async (layoutFile) => {
11743
- const cached = scriptlessVueLayoutDecisionCache.get(layoutFile);
11744
- if (cached) return await cached;
11745
- const task = (async () => {
11746
- return shouldEmitScriptlessVueLayoutJs(await fs.readFile(layoutFile, "utf-8"), layoutFile);
11747
- })();
11748
- scriptlessVueLayoutDecisionCache.set(layoutFile, task);
11749
- try {
11750
- return await task;
11751
- } catch (error) {
11752
- scriptlessVueLayoutDecisionCache.delete(layoutFile);
11753
- throw error;
11754
- }
11723
+ //#endregion
11724
+ //#region src/plugins/utils/wxmlEmit.ts
11725
+ function resolveWxmlEmitContext(compiler) {
11726
+ const { wxmlService, configService, scanService } = compiler;
11727
+ if (!wxmlService || !configService || !scanService) throw new Error("emitWxmlAssets 需要先初始化 wxmlService、configService 和 scanService。");
11728
+ const { templateExtension, scriptModuleExtension } = resolveCompilerOutputExtensions(configService.outputExtensions);
11729
+ return {
11730
+ wxmlService,
11731
+ configService,
11732
+ scanService,
11733
+ templateExtension,
11734
+ scriptModuleExtension,
11735
+ scriptModuleTag: resolveScriptModuleTagName({
11736
+ platform: configService.platform,
11737
+ scriptModuleExtension
11738
+ })
11755
11739
  };
11756
- return Object.assign(async function loadEntry(id, type) {
11757
- existsCache.clear();
11758
- const stopwatch = debug ? createStopwatch() : void 0;
11759
- const getTime = () => stopwatch ? stopwatch() : "0.00ms";
11760
- const relativeCwdId = configService.relativeCwd(id);
11761
- const normalizedId = normalizeFsResolvedId(id);
11762
- const libConfig = configService.weappLibConfig;
11763
- const libEntry = libConfig?.enabled && normalizedId ? ctx.runtimeState.lib.entries.get(normalizedId) : void 0;
11764
- addNormalizedWatchFile(this, id);
11765
- const baseName = removeExtensionDeep(id);
11766
- const jsonEntry = await findJsonEntry(id);
11767
- let jsonPath = jsonEntry.path;
11768
- let hasJsonEntry = Boolean(jsonPath);
11769
- for (const prediction of jsonEntry.predictions) await addWatchTarget(this, prediction, existsCache, pathExistsTtlMs);
11770
- let json = {};
11771
- if (jsonPath) json = await jsonService.read(jsonPath);
11772
- else jsonPath = changeFileExtension(id, ".json");
11773
- const vueEntryPath = id.endsWith(".vue") ? id : await findVueEntry(removeExtensionDeep(id));
11774
- if (vueEntryPath) addNormalizedWatchFile(this, vueEntryPath);
11775
- if (!jsonEntry.path) {
11776
- if (vueEntryPath) {
11777
- const configFromVue = await extractConfigFromVue(vueEntryPath);
11778
- if (configFromVue && typeof configFromVue === "object") {
11779
- json = configFromVue;
11780
- hasJsonEntry = true;
11781
- }
11782
- }
11783
- }
11784
- const entries = [];
11785
- const explicitEntryTypes = /* @__PURE__ */ new Map();
11786
- let templatePath = "";
11787
- let entryTypeOverride;
11788
- let pluginResolvedRecords;
11789
- let pluginJsonPathForRegistration;
11790
- let pluginJsonForRegistration;
11791
- let appResult;
11792
- let shouldSkipAppEntries = false;
11793
- const nativeLayoutScriptEntries = /* @__PURE__ */ new Set();
11794
- const autoRoutesSignature = configService.isDev ? ctx.autoRoutesService?.getSignature?.() : void 0;
11795
- if (type === "app") {
11796
- appResult = await collectAppEntries({
11797
- pluginCtx: this,
11798
- id,
11799
- json,
11800
- ctx,
11801
- isPluginBuild,
11802
- registerJsonAsset,
11803
- existsCache,
11804
- pathExistsTtlMs,
11805
- normalizeEntry,
11806
- resolveEntryWithCache: entryResolver.resolveEntryWithCache,
11807
- extendedLibManager,
11808
- cache: appEntriesCache
11809
- });
11810
- entries.push(...appResult.entries);
11811
- if (get(json, "tabBar.custom")) explicitEntryTypes.set(normalizeEntry("custom-tab-bar/index", jsonPath), "component");
11812
- if (get(json, "appBar")) explicitEntryTypes.set(normalizeEntry("app-bar/index", jsonPath), "component");
11813
- pluginResolvedRecords = appResult.pluginResolvedRecords;
11814
- if (appResult.pluginEntryTypes?.length) for (const entryType of appResult.pluginEntryTypes) entriesMap.set(entryType.entry, {
11815
- type: entryType.type,
11816
- path: entryType.entry
11817
- });
11818
- pluginJsonPathForRegistration = appResult.pluginJsonPathForRegistration;
11819
- pluginJsonForRegistration = appResult.pluginJsonForRegistration;
11820
- shouldSkipAppEntries = Boolean(configService.isDev && !isPluginBuild && appResult.cacheHit && appEntryOutputCache.current && appEntryOutputCache.current.appSignature === appResult.appSignature && appEntryOutputCache.current.pluginSignature === appResult.pluginSignature && appEntryOutputCache.current.pluginJsonPath === appResult.pluginJsonPath && appEntryOutputCache.current.autoRoutesSignature === autoRoutesSignature && appEntryOutputCache.current.resolveCacheVersion === resolveCacheVersion);
11821
- } else {
11822
- templatePath = await scanTemplateEntry(this, id, scanTemplateEntryFn, existsCache, pathExistsTtlMs);
11823
- if (libEntry && libConfig) {
11824
- const componentJson = libConfig.componentJson ?? "auto";
11825
- const hasTemplate = Boolean(templatePath) || id.endsWith(".vue");
11826
- const styleEntry = await findCssEntry(baseName);
11827
- const hasStyle = Boolean(styleEntry.path);
11828
- const shouldTreatAsComponent = hasTemplate || hasStyle || Boolean(json?.component);
11829
- if (!hasJsonEntry && shouldTreatAsComponent) {
11830
- if (componentJson === true || componentJson === "auto" || typeof componentJson === "function") {
11831
- const extra = typeof componentJson === "function" ? componentJson({
11832
- name: libEntry.name,
11833
- input: libEntry.input
11834
- }) : void 0;
11835
- if (typeof componentJson === "function" && !isObject(extra)) throw new Error("`weapp.lib.componentJson` 必须返回对象。");
11836
- json = {
11837
- component: true,
11838
- ...isObject(extra) ? extra : {}
11839
- };
11840
- hasJsonEntry = true;
11841
- }
11842
- }
11843
- if (shouldTreatAsComponent) entryTypeOverride = "component";
11844
- }
11845
- if (vueEntryPath) {
11846
- await applyScriptSetupUsingComponents({
11847
- pluginCtx: this,
11848
- vueEntryPath,
11849
- templatePath,
11850
- json,
11851
- configService,
11852
- wxmlService,
11853
- reExportResolutionCache
11854
- });
11855
- if (type === "page") {
11856
- const layoutPlan = await resolvePageLayoutPlan(await fs.readFile(vueEntryPath, "utf-8"), vueEntryPath, configService);
11857
- if (layoutPlan) {
11858
- await addResolvedPageLayoutWatchFiles(this, layoutPlan.layouts);
11859
- await registerResolvedPageLayoutEntries({
11860
- layouts: layoutPlan.layouts,
11861
- entries,
11862
- explicitEntryTypes,
11863
- nativeScriptEntries: nativeLayoutScriptEntries,
11864
- normalizeEntry,
11865
- jsonPath
11866
- });
11867
- for (const layout of layoutPlan.layouts) {
11868
- if (layout.kind === "native") continue;
11869
- if (!layout.file.endsWith(".vue")) continue;
11870
- if (!await shouldEmitScriptlessVueLayoutJs$1(layout.file)) continue;
11871
- const relativeLayoutBase = configService.relativeOutputPath(removeExtensionDeep(layout.file));
11872
- if (!relativeLayoutBase || emittedScriptlessVueLayoutJs.has(relativeLayoutBase)) continue;
11873
- emittedScriptlessVueLayoutJs.add(relativeLayoutBase);
11874
- const { scriptExtension } = resolveCompilerOutputExtensions(configService.outputExtensions);
11875
- emitScriptlessComponentAsset(this, resolveScriptlessComponentFileName(relativeLayoutBase, scriptExtension));
11876
- }
11877
- }
11878
- }
11879
- }
11880
- await ctx.autoImportService?.awaitPendingRegistrations?.();
11881
- applyAutoImports(baseName, json);
11882
- const componentEntries = analyzeCommonJson(json);
11883
- entries.push(...componentEntries);
11884
- for (const componentEntry of componentEntries) explicitEntryTypes.set(normalizeEntry(componentEntry, jsonPath), "component");
11740
+ }
11741
+ function resolveWxmlEmitTargets(options) {
11742
+ const { compiler, subPackageMeta, buildTarget = "app" } = options;
11743
+ const { wxmlService, configService, scanService, templateExtension } = resolveWxmlEmitContext(compiler);
11744
+ return Array.from(wxmlService.tokenMap.entries()).filter(([id]) => isTemplate(id)).map(([id, token]) => {
11745
+ return {
11746
+ id,
11747
+ token,
11748
+ fileName: resolveRelativeOutputFileNameWithExtension(configService, id, templateExtension)
11749
+ };
11750
+ }).filter(({ id, fileName }) => {
11751
+ if (subPackageMeta) return fileName.startsWith(subPackageMeta.subPackage.root);
11752
+ if (buildTarget === "plugin") {
11753
+ const pluginRoot = configService.absolutePluginRoot;
11754
+ if (!pluginRoot) return false;
11755
+ return isPathInside(pluginRoot, id);
11885
11756
  }
11886
- const normalizedEntries = shouldSkipAppEntries ? [] : prepareNormalizedEntries({
11887
- entries,
11888
- json,
11889
- jsonPath,
11890
- templatePath,
11757
+ return scanService.isMainPackageFileName(fileName);
11758
+ });
11759
+ }
11760
+ function emitWxmlAssetFile(options) {
11761
+ const { runtime, id, fileName, token, deps, emittedCodeCache, scriptModuleExtension, scriptModuleTag, templateExtension } = options;
11762
+ runtime.addWatchFile?.(normalizeWatchPath(id));
11763
+ if (deps) for (const dep of deps) runtime.addWatchFile?.(normalizeWatchPath(dep));
11764
+ const result = handleWxml(token, {
11765
+ scriptModuleExtension,
11766
+ scriptModuleTag,
11767
+ templateExtension
11768
+ });
11769
+ if (emittedCodeCache.get(fileName) === result.code) return false;
11770
+ emittedCodeCache.set(fileName, result.code);
11771
+ runtime.emitFile({
11772
+ type: "asset",
11773
+ fileName,
11774
+ source: result.code
11775
+ });
11776
+ return true;
11777
+ }
11778
+ function emitWxmlAssetsWithCache(options) {
11779
+ const { runtime, compiler, subPackageMeta, emittedCodeCache, buildTarget = "app" } = options;
11780
+ const { wxmlService, templateExtension, scriptModuleExtension, scriptModuleTag } = resolveWxmlEmitContext(compiler);
11781
+ const currentPackageWxmls = resolveWxmlEmitTargets({
11782
+ compiler,
11783
+ subPackageMeta,
11784
+ buildTarget
11785
+ });
11786
+ const emittedFiles = [];
11787
+ for (const { id, fileName, token } of currentPackageWxmls) {
11788
+ emittedFiles.push(fileName);
11789
+ emitWxmlAssetFile({
11790
+ runtime,
11891
11791
  id,
11892
- skipOwnEntries: isPluginBuild && type === "app",
11893
- entriesMap,
11894
- normalizeEntry,
11895
- extendedLibManager,
11896
- entryType: entryTypeOverride,
11897
- explicitEntryTypes
11792
+ fileName,
11793
+ token,
11794
+ deps: wxmlService.depsMap.get(id),
11795
+ emittedCodeCache,
11796
+ scriptModuleExtension,
11797
+ scriptModuleTag,
11798
+ templateExtension
11898
11799
  });
11899
- markComponentEntries(entriesMap, nativeLayoutScriptEntries);
11900
- const entryResolveRoot = isPluginBuild && configService.absolutePluginRoot && isPathInside(configService.absolutePluginRoot, id) ? configService.absolutePluginRoot : configService.absoluteSrcRoot;
11901
- const result = await emitEntryOutput({
11902
- pluginCtx: this,
11903
- id,
11904
- type,
11905
- json,
11906
- jsonPath,
11800
+ }
11801
+ return emittedFiles;
11802
+ }
11803
+ function emitJsonAsset(runtime, fileName, source, extension = "json") {
11804
+ runtime.emitFile({
11805
+ type: "asset",
11806
+ fileName: changeFileExtension(fileName, extension),
11807
+ source
11808
+ });
11809
+ }
11810
+ //#endregion
11811
+ //#region src/plugins/hooks/useLoadEntry/loadEntry/emit.ts
11812
+ const NON_VUE_PAGE_RE = /\.vue$|\.jsx$|\.tsx$/;
11813
+ function prepareNormalizedEntries(options) {
11814
+ const { entries, json, jsonPath, templatePath, id, skipOwnEntries, entriesMap, normalizeEntry, extendedLibManager, entryType, explicitEntryTypes } = options;
11815
+ const filteredEntries = skipOwnEntries ? [] : entries.filter((entry) => !extendedLibManager.shouldIgnoreEntry(entry));
11816
+ const normalizedEntries = skipOwnEntries ? [] : filteredEntries.map((entry) => normalizeEntry(entry, jsonPath));
11817
+ if (!skipOwnEntries) for (const normalizedEntry of normalizedEntries) {
11818
+ const resolvedEntryType = explicitEntryTypes?.get(normalizedEntry) ?? entryType ?? (json.component ? "component" : "page");
11819
+ entriesMap.set(normalizedEntry, {
11820
+ type: resolvedEntryType,
11907
11821
  templatePath,
11908
- isPluginBuild,
11909
- normalizedEntries,
11910
- pluginResolvedRecords,
11911
- pluginJsonPathForRegistration,
11912
- pluginJsonForRegistration,
11913
- resolveEntriesWithCache: entryResolver.resolveEntriesWithCache,
11914
- entryResolveRoot,
11822
+ jsonPath,
11823
+ json,
11824
+ path: id
11825
+ });
11826
+ }
11827
+ return normalizedEntries;
11828
+ }
11829
+ async function emitEntryOutput(options) {
11830
+ const { pluginCtx, id, type, json: initialJson, jsonPath, templatePath, isPluginBuild, normalizedEntries, pluginResolvedRecords, pluginJsonPathForRegistration, pluginJsonForRegistration, resolveEntriesWithCache, entryResolveRoot, configService, wxmlService, resolvedEntryMap, loadedEntrySet, dirtyEntrySet, replaceLayoutDependencies, emitEntriesChunks, registerJsonAsset, existsCache, pathExistsTtlMs, debug, relativeCwdId, getTime, emittedWxmlCodeCache } = options;
11831
+ let json = initialJson;
11832
+ async function emitNativeLayoutAssets(layoutBasePath) {
11833
+ if (typeof pluginCtx.emitFile !== "function") return;
11834
+ const resolvedOptions = resolveNativeLayoutOutputOptions({
11915
11835
  configService,
11836
+ layoutBasePath,
11837
+ outputExtensions: configService.outputExtensions
11838
+ });
11839
+ if (!resolvedOptions) return;
11840
+ const assets = await collectNativeLayoutAssets(layoutBasePath);
11841
+ const emittedLayoutAssets = pluginCtx.__weappViteNativeLayoutAssets ?? (pluginCtx.__weappViteNativeLayoutAssets = /* @__PURE__ */ new Set());
11842
+ if (assets.json) registerJsonAsset({
11843
+ jsonPath: assets.json,
11844
+ json: JSON.parse(await fs$1.readFile(assets.json, "utf8")),
11845
+ type: "component"
11846
+ });
11847
+ const assetEntries = await resolveNativeLayoutStaticAssetEntries({
11848
+ assets,
11849
+ resolvedOptions,
11850
+ readFile: fs$1.readFile
11851
+ });
11852
+ const emittedCodeCache = emittedWxmlCodeCache ?? /* @__PURE__ */ new Map();
11853
+ const wxmlEmitContext = wxmlService ? resolveWxmlEmitContext({
11916
11854
  wxmlService,
11917
- resolvedEntryMap,
11918
- loadedEntrySet,
11919
- dirtyEntrySet,
11920
- replaceLayoutDependencies,
11921
- emitEntriesChunks,
11922
- registerJsonAsset,
11923
- existsCache,
11924
- pathExistsTtlMs,
11925
- debug,
11926
- relativeCwdId,
11927
- getTime,
11928
- skipEntries: shouldSkipAppEntries
11855
+ configService,
11856
+ scanService: { isMainPackageFileName: () => true }
11857
+ }) : void 0;
11858
+ for (const asset of assetEntries) {
11859
+ if (emittedLayoutAssets.has(asset.fileName)) continue;
11860
+ if (asset.kind === "template" && assets.template && wxmlService && wxmlEmitContext) {
11861
+ const token = wxmlService.analyze(asset.source);
11862
+ wxmlService.tokenMap.set(assets.template, token);
11863
+ const deps = wxmlService.collectDepsFromToken(assets.template, token.deps);
11864
+ await wxmlService.setDeps(assets.template, deps);
11865
+ wxmlService.setWxmlComponentsMap(assets.template, token.components);
11866
+ emitWxmlAssetFile({
11867
+ runtime: {
11868
+ addWatchFile: pluginCtx.addWatchFile?.bind(pluginCtx),
11869
+ emitFile: (payload) => pluginCtx.emitFile(payload)
11870
+ },
11871
+ id: assets.template,
11872
+ fileName: asset.fileName,
11873
+ token,
11874
+ deps: wxmlService.depsMap.get(assets.template),
11875
+ emittedCodeCache,
11876
+ scriptModuleExtension: wxmlEmitContext.scriptModuleExtension,
11877
+ scriptModuleTag: wxmlEmitContext.scriptModuleTag,
11878
+ templateExtension: wxmlEmitContext.templateExtension
11879
+ });
11880
+ emittedLayoutAssets.add(asset.fileName);
11881
+ continue;
11882
+ }
11883
+ emittedLayoutAssets.add(asset.fileName);
11884
+ pluginCtx.emitFile({
11885
+ type: "asset",
11886
+ fileName: asset.fileName,
11887
+ source: asset.source
11888
+ });
11889
+ }
11890
+ emitNativeLayoutScriptChunkIfNeeded$1({
11891
+ pluginCtx,
11892
+ scriptId: assets.script,
11893
+ fileName: `${resolvedOptions.relativeBase}.${resolvedOptions.scriptExtension}`
11929
11894
  });
11930
- if (type === "app" && !shouldSkipAppEntries && appResult) appEntryOutputCache.current = {
11931
- appSignature: appResult.appSignature,
11932
- pluginSignature: appResult.pluginSignature,
11933
- pluginJsonPath: appResult.pluginJsonPath,
11934
- autoRoutesSignature,
11935
- resolveCacheVersion
11936
- };
11937
- return result;
11938
- }, { invalidateResolveCache() {
11939
- entryResolver.invalidate();
11940
- scriptlessVueLayoutDecisionCache.clear();
11941
- resolveCacheVersion += 1;
11942
- appEntryOutputCache.current = void 0;
11943
- } });
11895
+ }
11896
+ const shouldSkipEntries = Boolean(options.skipEntries);
11897
+ const resolvedIds = shouldSkipEntries ? [] : normalizedEntries.length ? await resolveEntriesWithCache(pluginCtx, normalizedEntries, entryResolveRoot) : [];
11898
+ debug?.(`resolvedIds ${relativeCwdId} 耗时 ${getTime()}`);
11899
+ const pendingResolvedIds = [];
11900
+ const combinedResolved = shouldSkipEntries ? [] : pluginResolvedRecords ? isPluginBuild ? pluginResolvedRecords : [...resolvedIds, ...pluginResolvedRecords] : resolvedIds;
11901
+ const pluginEntrySet = shouldSkipEntries || !pluginResolvedRecords ? void 0 : new Set(pluginResolvedRecords.map((record) => record.entry));
11902
+ for (const { entry, resolvedId } of combinedResolved) {
11903
+ if (!resolvedId) {
11904
+ if (pluginEntrySet?.has(entry)) logger_default.warn(`没有找到插件入口 \`${entry}\` 对应的脚本文件,请检查路径是否正确!`);
11905
+ else logger_default.warn(`没有找到 \`${entry}\` 的入口文件,请检查路径是否正确!`);
11906
+ continue;
11907
+ }
11908
+ const normalizedResolvedId = normalizeFsResolvedId(resolvedId.id);
11909
+ if (normalizedResolvedId && !isSkippableResolvedId(normalizedResolvedId) && path.isAbsolute(normalizedResolvedId)) addNormalizedWatchFile(pluginCtx, normalizedResolvedId);
11910
+ if (normalizedResolvedId && !isSkippableResolvedId(normalizedResolvedId)) resolvedEntryMap.set(normalizedResolvedId, resolvedId);
11911
+ const isDirtyEntry = dirtyEntrySet.has(normalizedResolvedId);
11912
+ if (!isDirtyEntry && loadedEntrySet.has(normalizedResolvedId)) continue;
11913
+ pendingResolvedIds.push(resolvedId);
11914
+ if (isDirtyEntry) dirtyEntrySet.delete(normalizedResolvedId);
11915
+ }
11916
+ if (pendingResolvedIds.length) await Promise.all(emitEntriesChunks.call(pluginCtx, pendingResolvedIds));
11917
+ debug?.(`emitEntriesChunks ${relativeCwdId} 耗时 ${getTime()}`);
11918
+ let code = await readFile$1(id, { checkMtime: configService.isDev });
11919
+ if (type === "page" && templatePath && !NON_VUE_PAGE_RE.test(id)) {
11920
+ replaceLayoutDependencies(id, []);
11921
+ const layoutPlan = await resolvePageLayoutPlan(code, id, configService);
11922
+ if (layoutPlan) {
11923
+ const layoutDependencies = /* @__PURE__ */ new Set();
11924
+ for (const file of await expandResolvedPageLayoutFiles(layoutPlan.layouts)) {
11925
+ addNormalizedWatchFile(pluginCtx, file);
11926
+ layoutDependencies.add(normalizeFsResolvedId(file));
11927
+ }
11928
+ replaceLayoutDependencies(id, layoutDependencies);
11929
+ const nativeTemplate = await readFile$1(templatePath, { checkMtime: configService.isDev });
11930
+ const transformed = applyPageLayoutPlanToNativePage({
11931
+ script: code,
11932
+ template: nativeTemplate,
11933
+ config: JSON.stringify(json)
11934
+ }, id, layoutPlan);
11935
+ code = transformed.script ?? code;
11936
+ if (transformed.config) json = JSON.parse(transformed.config);
11937
+ if (transformed.template && wxmlService) {
11938
+ const token = wxmlService.analyze(transformed.template);
11939
+ wxmlService.tokenMap.set(templatePath, token);
11940
+ wxmlService.setDeps(templatePath, wxmlService.collectDepsFromToken(templatePath, token.deps));
11941
+ wxmlService.setWxmlComponentsMap(templatePath, token.components);
11942
+ }
11943
+ for (const layout of layoutPlan.layouts) if (layout.kind === "native") await emitNativeLayoutAssets(layout.file);
11944
+ }
11945
+ code = injectNativePageLayoutRuntime(code, id, layoutPlan) ?? code;
11946
+ }
11947
+ if (!isPluginBuild || type !== "app") registerJsonAsset({
11948
+ jsonPath,
11949
+ json,
11950
+ type
11951
+ });
11952
+ if (pluginJsonPathForRegistration && pluginJsonForRegistration) registerJsonAsset({
11953
+ jsonPath: pluginJsonPathForRegistration,
11954
+ json: pluginJsonForRegistration,
11955
+ type: "plugin"
11956
+ });
11957
+ const styleImports = await collectStyleImports(pluginCtx, id, existsCache, pathExistsTtlMs);
11958
+ debug?.(`loadEntry ${relativeCwdId} 耗时 ${getTime()}`);
11959
+ if (styleImports.length === 0) return { code };
11960
+ const ms = new MagicString(code);
11961
+ for (const styleImport of styleImports) ms.prepend(`import '${styleImport}';\n`);
11962
+ return { code: ms.toString() };
11944
11963
  }
11945
11964
  //#endregion
11946
- //#region src/plugins/hooks/useLoadEntry/normalizer.ts
11947
- const PLUGIN_PROTOCOL_RE = /plugin:\/\//;
11948
- const WINDOWS_PATH_SEPARATOR_RE = /\\/g;
11949
- function resolveImportee(importee, jsonPath, configService) {
11950
- let updated = importee;
11951
- if (jsonPath && Array.isArray(configService.aliasEntries)) {
11952
- const matchedEntry = configService.aliasEntries.find((entry) => matches(entry.find, importee));
11953
- if (matchedEntry) updated = importee.replace(matchedEntry.find, matchedEntry.replacement);
11965
+ //#region src/plugins/hooks/useLoadEntry/loadEntry/resolve.ts
11966
+ function createEntryResolver(configService) {
11967
+ const entryResolutionCache = /* @__PURE__ */ new Map();
11968
+ async function resolveEntryWithCache(pluginCtx, absPath) {
11969
+ const normalized = path.normalize(absPath);
11970
+ if (entryResolutionCache.has(normalized)) return entryResolutionCache.get(normalized) ?? null;
11971
+ let resolvedSource = normalized;
11972
+ if (!path.extname(normalized)) {
11973
+ const matched = await resolveEntryPath(normalized, createCachedEntryResolveOptions(configService ?? {}, { kind: "default" }));
11974
+ if (matched) resolvedSource = matched;
11975
+ }
11976
+ const resolvedId = await pluginCtx.resolve(resolvedSource) ?? null;
11977
+ entryResolutionCache.set(normalized, resolvedId);
11978
+ return resolvedId;
11954
11979
  }
11955
- const baseDir = jsonPath ? path.dirname(jsonPath) : configService.absoluteSrcRoot;
11956
- return path.resolve(baseDir, updated);
11957
- }
11958
- function createEntryNormalizer(configService) {
11959
- return function normalizeEntry(entry, jsonPath) {
11960
- if (PLUGIN_PROTOCOL_RE.test(entry)) return entry;
11961
- const normalizedEntry = normalizeNpmImportLookupPath(entry);
11962
- if (normalizedEntry && isObject(configService.packageJson.dependencies) && hasNpmDependencyPrefix(configService.packageJson.dependencies, normalizedEntry)) return `npm:${normalizedEntry}`;
11963
- if (entry.replace(WINDOWS_PATH_SEPARATOR_RE, "/").startsWith("/")) return normalizedEntry;
11964
- const normalized = resolveImportee(normalizedEntry, jsonPath, configService);
11965
- return configService.relativeAbsoluteSrcRoot(normalized);
11980
+ async function resolveEntriesWithCache(pluginCtx, entries, absoluteRoot) {
11981
+ return Promise.all(entries.filter((entry) => !entry.includes(":")).map(async (entry) => {
11982
+ return {
11983
+ entry,
11984
+ resolvedId: await resolveEntryWithCache(pluginCtx, path.resolve(absoluteRoot, entry))
11985
+ };
11986
+ }));
11987
+ }
11988
+ return {
11989
+ resolveEntryWithCache,
11990
+ resolveEntriesWithCache,
11991
+ invalidate() {
11992
+ entryResolutionCache.clear();
11993
+ }
11966
11994
  };
11967
11995
  }
11968
11996
  //#endregion
11969
- //#region src/plugins/hooks/useLoadEntry/template.ts
11970
- function createTemplateScanner(wxmlService, debug) {
11971
- return async function scanTemplateEntry(templateEntry) {
11972
- const start = performance$1.now();
11973
- const wxmlToken = await wxmlService.scan(templateEntry);
11974
- if (wxmlToken) {
11975
- const { components } = wxmlToken;
11976
- wxmlService.setWxmlComponentsMap(templateEntry, components);
11977
- }
11978
- debug?.(`scanTemplateEntry ${templateEntry} 耗时 ${(performance$1.now() - start).toFixed(2)}ms`);
11997
+ //#region src/plugins/utils/vueSfc.ts
11998
+ function createSfcResolveSrcOptions(pluginCtx, configService) {
11999
+ return {
12000
+ resolveId: async (source, importer) => {
12001
+ if (typeof pluginCtx.resolve !== "function") return;
12002
+ return (await pluginCtx.resolve(source, importer))?.id;
12003
+ },
12004
+ checkMtime: getSfcCheckMtime(configService)
12005
+ };
12006
+ }
12007
+ function createReadAndParseSfcOptions(pluginCtx, configService, options) {
12008
+ const resolveCheckMtime = getSfcCheckMtime(configService);
12009
+ return {
12010
+ source: options?.source,
12011
+ checkMtime: options?.checkMtime ?? resolveCheckMtime,
12012
+ resolveSrc: createSfcResolveSrcOptions(pluginCtx, configService)
11979
12013
  };
11980
12014
  }
11981
12015
  //#endregion
11982
- //#region src/plugins/hooks/useLoadEntry/index.ts
11983
- function useLoadEntry(ctx, options) {
11984
- const debug = createDebugger("weapp-vite:load-entry");
11985
- const buildTarget = options?.buildTarget ?? "app";
11986
- const entriesMap = /* @__PURE__ */ new Map();
11987
- const loadedEntrySet = /* @__PURE__ */ new Set();
11988
- const dirtyEntrySet = /* @__PURE__ */ new Set();
11989
- const dirtyEntryReasons = /* @__PURE__ */ new Map();
11990
- const resolvedEntryMap = /* @__PURE__ */ new Map();
11991
- const layoutEntryDependents = /* @__PURE__ */ new Map();
11992
- const entryLayoutDependencies = /* @__PURE__ */ new Map();
11993
- const jsonEmitManager = createJsonEmitManager(ctx.configService);
11994
- const registerJsonAsset = jsonEmitManager.register.bind(jsonEmitManager);
11995
- const normalizeEntry = createEntryNormalizer(ctx.configService);
11996
- const scanTemplateEntry = createTemplateScanner(ctx.wxmlService, debug);
11997
- const emitEntriesChunks = createChunkEmitter(ctx.configService, loadedEntrySet, debug);
11998
- const loadEntry = createEntryLoader({
11999
- ctx,
12000
- entriesMap,
12001
- loadedEntrySet,
12002
- dirtyEntrySet,
12003
- resolvedEntryMap,
12004
- replaceLayoutDependencies(entryId, dependencies) {
12005
- const previousDependencies = entryLayoutDependencies.get(entryId);
12006
- if (previousDependencies) for (const dependency of previousDependencies) {
12007
- const dependents = layoutEntryDependents.get(dependency);
12008
- if (!dependents) continue;
12009
- dependents.delete(entryId);
12010
- if (dependents.size === 0) layoutEntryDependents.delete(dependency);
12011
- }
12012
- const normalizedDependencies = new Set(dependencies);
12013
- if (normalizedDependencies.size === 0) {
12014
- entryLayoutDependencies.delete(entryId);
12015
- return;
12016
- }
12017
- entryLayoutDependencies.set(entryId, normalizedDependencies);
12018
- for (const dependency of normalizedDependencies) {
12019
- let dependents = layoutEntryDependents.get(dependency);
12020
- if (!dependents) {
12021
- dependents = /* @__PURE__ */ new Set();
12022
- layoutEntryDependents.set(dependency, dependents);
12023
- }
12024
- dependents.add(entryId);
12025
- }
12026
- },
12027
- normalizeEntry,
12028
- registerJsonAsset,
12029
- scanTemplateEntry,
12030
- emitEntriesChunks,
12031
- applyAutoImports: createAutoImportAugmenter(ctx.autoImportService, ctx.wxmlService),
12032
- extendedLibManager: createExtendedLibManager(),
12033
- buildTarget,
12034
- debug
12035
- });
12036
- const hmrSharedChunksMode = options?.hmr?.sharedChunks ?? "auto";
12037
- const hmrSharedChunkImporters = options?.hmr?.sharedChunkImporters;
12038
- return {
12039
- loadEntry,
12040
- entriesMap,
12041
- loadedEntrySet,
12042
- dirtyEntrySet,
12043
- resolvedEntryMap,
12044
- layoutEntryDependents,
12045
- jsonEmitFilesMap: jsonEmitManager.map,
12046
- normalizeEntry,
12047
- markEntryDirty(entryId, reason = "direct") {
12048
- dirtyEntrySet.add(entryId);
12049
- dirtyEntryReasons.set(entryId, reason);
12050
- loadedEntrySet.delete(entryId);
12051
- },
12052
- async emitDirtyEntries() {
12053
- if (!dirtyEntrySet.size) {
12054
- options?.hmr?.setDidEmitAllEntries?.(false);
12055
- options?.hmr?.setLastEmittedEntries?.(/* @__PURE__ */ new Set());
12056
- return;
12057
- }
12058
- const dirtyCount = dirtyEntrySet.size;
12059
- const pendingEntryIds = resolvePendingEntryIds({
12060
- isDev: Boolean(ctx.configService?.isDev),
12061
- mode: hmrSharedChunksMode,
12062
- resolvedEntryMap,
12063
- dirtyEntrySet,
12064
- dirtyEntryReasons,
12065
- sharedChunkImporters: hmrSharedChunkImporters,
12066
- subPackageRoots: new Set(ctx.scanService?.subPackageMap?.keys?.() ?? []),
12067
- relativeAbsoluteSrcRoot: ctx.configService.relativeAbsoluteSrcRoot.bind(ctx.configService)
12068
- });
12069
- const pending = [];
12070
- const shouldEmitAllEntries = pendingEntryIds.size > 0 && pendingEntryIds.size === resolvedEntryMap.size;
12071
- options?.hmr?.setDidEmitAllEntries?.(shouldEmitAllEntries);
12072
- options?.hmr?.setLastEmittedEntries?.(new Set(pendingEntryIds));
12073
- for (const entryId of pendingEntryIds) {
12074
- const resolvedId = resolvedEntryMap.get(entryId);
12075
- if (!resolvedId) continue;
12076
- pending.push(resolvedId);
12077
- dirtyEntrySet.delete(entryId);
12078
- dirtyEntryReasons.delete(entryId);
12079
- }
12080
- if (debug) debug(`hmr emit dirty=${dirtyCount} resolved=${resolvedEntryMap.size} emitAll=${shouldEmitAllEntries} pending=${pending.length}`);
12081
- if (pending.length) await Promise.all(emitEntriesChunks.call(this, pending));
12082
- }
12016
+ //#region src/plugins/vue/transform/usingComponentResolver.ts
12017
+ const JS_LIKE_FILE_RE = /\.(?:[cm]?ts|[cm]?js)$/;
12018
+ async function resolveUsingComponentReference(ctx, configService, reExportResolutionCache, importSource, importerFilename, info) {
12019
+ const resolved = await ctx.resolve(importSource, importerFilename);
12020
+ let clean = resolved?.id ? normalizeFsResolvedId(resolved.id) : void 0;
12021
+ if ((!clean || !path.isAbsolute(clean)) && info?.fallbackRelativeImporterDir && importSource.startsWith(".")) clean = path.resolve(path.dirname(importerFilename), importSource);
12022
+ if (!clean) return {
12023
+ resolvedId: void 0,
12024
+ from: void 0
12083
12025
  };
12084
- }
12085
- function resolvePendingEntryIds(options) {
12086
- const pending = new Set(options.dirtyEntrySet);
12087
- if (options.mode === "full") return new Set(options.resolvedEntryMap.keys());
12088
- if (!options.isDev || options.mode === "off") return pending;
12089
- if (!options.sharedChunkImporters?.size) return pending;
12090
- for (const importers of options.sharedChunkImporters.values()) {
12091
- if (importers.size <= 1) continue;
12092
- let hasDependencyDrivenImporter = false;
12093
- let hasDirectDirtyImporter = false;
12094
- for (const importer of importers) {
12095
- if (options.dirtyEntrySet.has(importer) && options.dirtyEntryReasons.get(importer) === "dependency") {
12096
- hasDependencyDrivenImporter = true;
12097
- break;
12026
+ if (isSkippableResolvedId(clean)) return {
12027
+ resolvedId: void 0,
12028
+ from: void 0
12029
+ };
12030
+ if (path.isAbsolute(clean)) {
12031
+ const resolvedEntry = await resolveEntryPath(clean, createCachedEntryResolveOptions(configService ?? {}, { kind: info?.kind ?? "default" }));
12032
+ if (resolvedEntry) clean = resolvedEntry;
12033
+ }
12034
+ if (info?.kind === "named" && info.importedName && JS_LIKE_FILE_RE.test(clean)) {
12035
+ const exportName = info.importedName;
12036
+ const mapped = await resolveReExportedName(clean, exportName, {
12037
+ astEngine: resolveAstEngine(configService.weappViteConfig),
12038
+ cache: reExportResolutionCache,
12039
+ maxDepth: 4,
12040
+ readFile: (file) => readFile$1(file, { checkMtime: getReadFileCheckMtime(configService) }),
12041
+ resolveId: async (source, importer) => {
12042
+ const hop = await ctx.resolve(source, importer);
12043
+ const hopId = hop?.id ? normalizeFsResolvedId(hop.id) : void 0;
12044
+ if (isSkippableResolvedId(hopId)) return;
12045
+ return hopId;
12098
12046
  }
12099
- if (options.dirtyEntrySet.has(importer) && options.dirtyEntryReasons.get(importer) === "direct") hasDirectDirtyImporter = true;
12100
- }
12101
- if (!hasDependencyDrivenImporter && !hasDirectDirtyImporter) continue;
12102
- for (const importer of importers) pending.add(importer);
12047
+ });
12048
+ if (mapped) clean = mapped;
12103
12049
  }
12104
- return pending;
12105
- }
12106
- //#endregion
12107
- //#region src/utils/wxmlScriptModule.ts
12108
- const IMPORT_SJS_TAG_RE = /<import-sjs([\s\S]*?)>/g;
12109
- const IMPORT_SJS_SRC_RE = /\bsrc\s*=\s*/g;
12110
- const IMPORT_SJS_MODULE_RE = /\bmodule\s*=\s*/g;
12111
- const DEFAULT_SCRIPT_MODULE_TAG_NAMES = ["wxs", "sjs"];
12112
- const DEFAULT_SCRIPT_MODULE_TAG_BY_EXTENSION = Object.freeze({
12113
- wxs: "wxs",
12114
- sjs: "sjs"
12115
- });
12116
- const SCRIPT_MODULE_IMPORT_ATTRS = Object.freeze({
12117
- "wxs": ["src"],
12118
- "sjs": ["src"],
12119
- "import-sjs": ["from"]
12120
- });
12121
- function resolveScriptModuleTagByPlatform(platform, scriptModuleExtension) {
12122
- return getPlatformScriptModuleTag(platform, scriptModuleExtension);
12050
+ return {
12051
+ resolvedId: clean,
12052
+ from: usingComponentFromResolvedFile(clean, configService)
12053
+ };
12123
12054
  }
12124
- function normalizeScriptModuleExtension(scriptModuleExtension) {
12125
- if (!scriptModuleExtension) return;
12126
- return scriptModuleExtension.startsWith(".") ? scriptModuleExtension.slice(1) : scriptModuleExtension;
12055
+ async function resolveUsingComponentPath(ctx, configService, reExportResolutionCache, importSource, importerFilename, info) {
12056
+ return (await resolveUsingComponentReference(ctx, configService, reExportResolutionCache, importSource, importerFilename, info)).from;
12127
12057
  }
12128
- function getDefaultScriptModuleTagByExtension(scriptModuleExtension) {
12129
- if (!scriptModuleExtension) return "wxs";
12130
- return DEFAULT_SCRIPT_MODULE_TAG_BY_EXTENSION[normalizeScriptModuleExtension(scriptModuleExtension)] ?? "wxs";
12058
+ function createUsingComponentPathResolver(ctx, configService, reExportResolutionCache) {
12059
+ return async (importSource, importerFilename, info) => {
12060
+ return resolveUsingComponentPath(ctx, configService, reExportResolutionCache, importSource, importerFilename, info);
12061
+ };
12131
12062
  }
12132
- function resolveScriptModuleTagName(options) {
12133
- if (options?.scriptModuleTag) return options.scriptModuleTag;
12134
- return resolveScriptModuleTagByPlatform(options?.platform, options?.scriptModuleExtension) ?? getDefaultScriptModuleTagByExtension(options?.scriptModuleExtension);
12063
+ //#endregion
12064
+ //#region src/plugins/hooks/useLoadEntry/loadEntry/template.ts
12065
+ function collectVueTemplateComponentNames(template, filename) {
12066
+ return collectVueTemplateTags(template, {
12067
+ filename,
12068
+ warnLabel: "自动 usingComponents",
12069
+ shouldCollect: (tag) => VUE_COMPONENT_TAG_RE.test(tag)
12070
+ });
12135
12071
  }
12136
- function getDerivedScriptModuleTagNames() {
12137
- return MINI_PROGRAM_PLATFORM_ADAPTERS.flatMap((adapter) => Object.values(adapter.scriptModuleTagByExtension ?? {})).filter((value) => typeof value === "string" && value.length > 0);
12072
+ function collectVueTemplateAutoImportTags(template, filename) {
12073
+ return collectVueTemplateTags(template, {
12074
+ filename,
12075
+ warnLabel: "自动导入标签",
12076
+ shouldCollect: isAutoImportCandidateTag
12077
+ });
12138
12078
  }
12139
- function getScriptModuleTagNames() {
12140
- return [...new Set([...DEFAULT_SCRIPT_MODULE_TAG_NAMES, ...getDerivedScriptModuleTagNames()])];
12079
+ function collectScriptSetupImports(scriptSetup, templateComponentNames, options) {
12080
+ return collectScriptSetupImportsFromCode(scriptSetup, templateComponentNames, options);
12141
12081
  }
12142
- function isScriptModuleTagName(tagName) {
12143
- return typeof tagName === "string" && getScriptModuleTagNames().includes(tagName);
12082
+ async function scanTemplateEntry(pluginCtx, id, scanTemplateEntryFn, existsCache, ttlMs) {
12083
+ return ensureTemplateScanned(pluginCtx, id, scanTemplateEntryFn, existsCache, ttlMs);
12144
12084
  }
12145
- function getScriptModuleImportAttrs(tagName) {
12146
- if (!tagName) return;
12147
- return SCRIPT_MODULE_IMPORT_ATTRS[tagName];
12085
+ async function applyScriptSetupUsingComponents(options) {
12086
+ const { pluginCtx, vueEntryPath, templatePath, json, configService, wxmlService, reExportResolutionCache } = options;
12087
+ try {
12088
+ const { descriptor, errors } = await readAndParseSfc(vueEntryPath, { ...createReadAndParseSfcOptions(pluginCtx, configService) });
12089
+ if (!errors?.length && descriptor?.template && !templatePath) {
12090
+ const tags = collectVueTemplateAutoImportTags(descriptor.template.content, vueEntryPath);
12091
+ if (tags.size) {
12092
+ const components = Object.fromEntries(Array.from(tags, (tag) => [tag, [{
12093
+ start: 0,
12094
+ end: 0
12095
+ }]]));
12096
+ wxmlService?.setWxmlComponentsMap(vueEntryPath, components);
12097
+ }
12098
+ }
12099
+ if (!errors?.length && descriptor?.scriptSetup && descriptor?.template) {
12100
+ const templateComponentNames = collectVueTemplateComponentNames(descriptor.template.content, vueEntryPath);
12101
+ if (templateComponentNames.size) {
12102
+ const astEngine = resolveAstEngine(configService.weappViteConfig);
12103
+ const imports = collectScriptSetupImports(descriptor.scriptSetup.content, templateComponentNames, { astEngine });
12104
+ if (imports.length) {
12105
+ const usingComponents = json && typeof json.usingComponents === "object" && json.usingComponents && !Array.isArray(json.usingComponents) ? json.usingComponents : {};
12106
+ for (const { localName, importSource, importedName, kind } of imports) {
12107
+ let { from } = await resolveUsingComponentReference(pluginCtx, configService, reExportResolutionCache, importSource, vueEntryPath, {
12108
+ kind,
12109
+ importedName,
12110
+ fallbackRelativeImporterDir: true
12111
+ });
12112
+ if (!from && importSource.startsWith("/")) from = removeExtensionDeep(importSource);
12113
+ if (!from) continue;
12114
+ if (Reflect.has(usingComponents, localName) && usingComponents[localName] !== from) logger_default.warn(`[自动 usingComponents] 冲突:${vueEntryPath} 中 usingComponents['${localName}']='${usingComponents[localName]}' 将被 <script setup> 导入覆盖为 '${from}'`);
12115
+ usingComponents[localName] = from;
12116
+ }
12117
+ json.usingComponents = usingComponents;
12118
+ }
12119
+ }
12120
+ }
12121
+ } catch (error) {
12122
+ const message = error instanceof Error ? error.message : String(error);
12123
+ logger_default.warn(`[自动 usingComponents] 解析失败:${vueEntryPath}:${message}`);
12124
+ }
12148
12125
  }
12149
- function isScriptModuleImportAttr(tagName, attrName) {
12150
- if (!tagName) return false;
12151
- return getScriptModuleImportAttrs(tagName)?.includes(attrName) === true;
12126
+ //#endregion
12127
+ //#region src/plugins/hooks/useLoadEntry/loadEntry/index.ts
12128
+ function createStopwatch() {
12129
+ const start = performance$1.now();
12130
+ return () => `${(performance$1.now() - start).toFixed(2)}ms`;
12152
12131
  }
12153
- function shouldNormalizeScriptModuleAttributes(tagName) {
12154
- return tagName === "import-sjs";
12155
- }
12156
- function normalizeImportSjsAttributes(source) {
12157
- return source.replace(IMPORT_SJS_TAG_RE, (tag) => {
12158
- return tag.replace(IMPORT_SJS_SRC_RE, "from=").replace(IMPORT_SJS_MODULE_RE, "name=");
12159
- });
12160
- }
12161
- //#endregion
12162
- //#region src/wxs/utils.ts
12163
- function normalizeWxsFilename(value, extension = "wxs") {
12164
- const normalized = extension.startsWith(".") ? extension.slice(1) : extension;
12165
- let filename = value;
12166
- filename = filename.replace(/\.[jt]s$/i, "");
12167
- filename = filename.replace(/\.(wxs|sjs)$/i, "");
12168
- return addExtension(filename, `.${normalized}`);
12169
- }
12170
- //#endregion
12171
- //#region src/wxs/index.ts
12172
- function transformWxsCode(code, options) {
12173
- const filename = options?.filename ?? "script.ts";
12174
- const extension = options?.extension ?? "wxs";
12175
- const importees = [];
12176
- const maybePushImportee = (value) => {
12177
- if (typeof value !== "string" || !value) return;
12178
- importees.push({ source: value });
12179
- };
12180
- const tryCollectArgument = (path) => {
12181
- const node = path.node;
12182
- if (t.isStringLiteral(node)) {
12183
- maybePushImportee(node.value);
12184
- return;
12185
- }
12186
- if (t.isTemplateLiteral(node) && node.expressions.length === 0) {
12187
- maybePushImportee(node.quasis.map((q) => q.value.cooked ?? q.value.raw ?? "").join(""));
12188
- return;
12189
- }
12132
+ function createEntryLoader(options) {
12133
+ const { ctx, entriesMap, loadedEntrySet, dirtyEntrySet, resolvedEntryMap, replaceLayoutDependencies, normalizeEntry, registerJsonAsset, scanTemplateEntry: scanTemplateEntryFn, emitEntriesChunks, applyAutoImports, extendedLibManager, debug } = options;
12134
+ const isPluginBuild = (options.buildTarget ?? "app") === "plugin";
12135
+ const { jsonService, configService, wxmlService } = ctx;
12136
+ const existsCache = /* @__PURE__ */ new Map();
12137
+ const pathExistsTtlMs = getPathExistsTtlMs(configService);
12138
+ const reExportResolutionCache = /* @__PURE__ */ new Map();
12139
+ const entryResolver = createEntryResolver(configService);
12140
+ const appEntriesCache = {};
12141
+ const appEntryOutputCache = {};
12142
+ const emittedScriptlessVueLayoutJs = /* @__PURE__ */ new Set();
12143
+ const scriptlessVueLayoutDecisionCache = /* @__PURE__ */ new Map();
12144
+ let resolveCacheVersion = 0;
12145
+ const shouldEmitScriptlessVueLayoutJs$1 = async (layoutFile) => {
12146
+ const cached = scriptlessVueLayoutDecisionCache.get(layoutFile);
12147
+ if (cached) return await cached;
12148
+ const task = (async () => {
12149
+ return shouldEmitScriptlessVueLayoutJs(await fs.readFile(layoutFile, "utf-8"), layoutFile);
12150
+ })();
12151
+ scriptlessVueLayoutDecisionCache.set(layoutFile, task);
12190
12152
  try {
12191
- const evaluated = path.evaluate();
12192
- if (evaluated.confident) maybePushImportee(evaluated.value);
12193
- } catch {}
12194
- };
12195
- return {
12196
- result: babel.transformSync(code, {
12197
- babelrc: false,
12198
- configFile: false,
12199
- presets: [["@babel/preset-env"], ["@babel/preset-typescript"]],
12200
- filename,
12201
- plugins: [{ visitor: {
12202
- Directive: { enter(p) {
12203
- p.remove();
12204
- } },
12205
- CallExpression: { enter(p) {
12206
- const node = p.node;
12207
- if (!t.isIdentifier(node.callee, { name: "require" })) return;
12208
- if (node.arguments.length !== 1) return;
12209
- tryCollectArgument(p.get("arguments.0"));
12210
- const arg = node.arguments[0];
12211
- if (t.isStringLiteral(arg)) arg.value = normalizeWxsFilename(arg.value, extension);
12212
- } },
12213
- ExpressionStatement(p) {
12214
- const expression = p.node.expression;
12215
- if (expression.type === "CallExpression" && expression.callee.type === "MemberExpression" && t.isIdentifier(expression.callee.object) && expression.callee.object.name === "Object" && t.isIdentifier(expression.callee.property) && expression.callee.property.name === "defineProperty" && expression.arguments.length >= 2 && t.isIdentifier(expression.arguments[0]) && expression.arguments[0].name === "exports" && t.isStringLiteral(expression.arguments[1]) && expression.arguments[1].value === "__esModule") p.remove();
12216
- },
12217
- NewExpression: { enter(p) {
12218
- const node = p.node;
12219
- if (t.isIdentifier(node.callee, { name: "RegExp" })) p.replaceWith(t.callExpression(t.identifier("getRegExp"), node.arguments));
12220
- else if (t.isIdentifier(node.callee, { name: "Date" })) p.replaceWith(t.callExpression(t.identifier("getDate"), node.arguments));
12221
- } },
12222
- RegExpLiteral: { enter(p) {
12223
- const args = [t.stringLiteral(p.node.pattern)];
12224
- if (p.node.flags) args.push(t.stringLiteral(p.node.flags));
12225
- p.replaceWith(t.callExpression(t.identifier("getRegExp"), args));
12226
- } },
12227
- MemberExpression: { enter(p) {
12228
- const node = p.node;
12229
- if (!t.isIdentifier(node.object, { name: "exports" })) return;
12230
- const moduleExports = t.memberExpression(t.identifier("module"), t.identifier("exports"));
12231
- p.replaceWith(t.memberExpression(moduleExports, node.property, node.computed, node.optional));
12232
- } },
12233
- ImportDeclaration: { enter(p) {
12234
- maybePushImportee(p.node.source.value);
12235
- } }
12236
- } }]
12237
- }),
12238
- importees
12153
+ return await task;
12154
+ } catch (error) {
12155
+ scriptlessVueLayoutDecisionCache.delete(layoutFile);
12156
+ throw error;
12157
+ }
12239
12158
  };
12240
- }
12241
- //#endregion
12242
- //#region src/wxml/handle.ts
12243
- const handleCache = /* @__PURE__ */ new WeakMap();
12244
- const inlineWxsTransformCache = /* @__PURE__ */ new Map();
12245
- const INLINE_WXS_CACHE_LIMIT = 256;
12246
- function createCacheKey$1(options) {
12247
- const extension = options.scriptModuleExtension ?? "";
12248
- const tag = options.scriptModuleTag ?? "";
12249
- const templateExt = options.templateExtension ?? "";
12250
- return `${options.removeComment ? 1 : 0}|${options.transformEvent ? 1 : 0}|${extension}|${tag}|${templateExt}`;
12251
- }
12252
- function getCachedResult(data, cacheKey) {
12253
- return handleCache.get(data)?.get(cacheKey);
12254
- }
12255
- function setCachedResult(data, cacheKey, result) {
12256
- let cacheForToken = handleCache.get(data);
12257
- if (!cacheForToken) {
12258
- cacheForToken = /* @__PURE__ */ new Map();
12259
- handleCache.set(data, cacheForToken);
12260
- }
12261
- cacheForToken.set(cacheKey, result);
12262
- return result;
12263
- }
12264
- function getCachedInlineWxsTransform(code, extension) {
12265
- const key = `${extension}::${code}`;
12266
- const cached = inlineWxsTransformCache.get(key);
12267
- if (cached) {
12268
- inlineWxsTransformCache.delete(key);
12269
- inlineWxsTransformCache.set(key, cached);
12270
- return cached;
12271
- }
12272
- const transformed = transformWxsCode(code, { extension });
12273
- inlineWxsTransformCache.set(key, transformed);
12274
- if (inlineWxsTransformCache.size > INLINE_WXS_CACHE_LIMIT) {
12275
- const firstKey = inlineWxsTransformCache.keys().next().value;
12276
- if (firstKey) inlineWxsTransformCache.delete(firstKey);
12277
- }
12278
- return transformed;
12279
- }
12280
- function handleWxml(data, options) {
12281
- const opts = defu(options, {
12282
- removeComment: true,
12283
- transformEvent: true,
12284
- scriptModuleExtension: void 0,
12285
- scriptModuleTag: void 0,
12286
- templateExtension: void 0
12287
- });
12288
- const cacheKey = createCacheKey$1(opts);
12289
- const cached = getCachedResult(data, cacheKey);
12290
- if (cached) return cached;
12291
- const { code, removalRanges = [], commentTokens = [], eventTokens = [], directiveTokens = [], tagNameTokens = [], inlineWxsTokens = [], removeWxsLangAttrTokens = [], scriptModuleTagTokens = [], wxsImportNormalizeTokens = [], templateImportNormalizeTokens = [], components, deps } = data;
12292
- const normalizedScriptExtension = opts.scriptModuleExtension?.startsWith(".") ? opts.scriptModuleExtension.slice(1) : opts.scriptModuleExtension;
12293
- const normalizedTemplateExtension = opts.templateExtension?.startsWith(".") ? opts.templateExtension.slice(1) : opts.templateExtension;
12294
- const resolvedScriptTag = resolveScriptModuleTagName({
12295
- scriptModuleExtension: normalizedScriptExtension,
12296
- scriptModuleTag: opts.scriptModuleTag
12297
- });
12298
- const shouldNormalizeImports = wxsImportNormalizeTokens.length > 0;
12299
- const shouldNormalizeTemplateImports = templateImportNormalizeTokens.length > 0 && normalizedTemplateExtension;
12300
- const shouldRemoveLang = removeWxsLangAttrTokens.length > 0;
12301
- const shouldTransformInlineWxs = inlineWxsTokens.length > 0;
12302
- const shouldTransformEvents = opts.transformEvent && eventTokens.length > 0;
12303
- const shouldTransformDirectives = directiveTokens.length > 0;
12304
- const shouldTransformTagNames = tagNameTokens.length > 0;
12305
- const shouldTransformScriptModuleTags = resolvedScriptTag !== "wxs" && scriptModuleTagTokens.length > 0;
12306
- const shouldRemoveConditionals = removalRanges.length > 0;
12307
- const shouldRemoveComments = opts.removeComment && commentTokens.length > 0;
12308
- if (!shouldNormalizeImports && !shouldNormalizeTemplateImports && !shouldRemoveLang && !shouldTransformInlineWxs && !shouldTransformEvents && !shouldTransformDirectives && !shouldTransformTagNames && !shouldTransformScriptModuleTags && !shouldRemoveConditionals && !shouldRemoveComments) return setCachedResult(data, cacheKey, {
12309
- code,
12310
- components,
12311
- deps
12312
- });
12313
- const ms = new MagicString(code);
12314
- if (shouldNormalizeImports) for (const { start, end, value } of wxsImportNormalizeTokens) ms.update(start, end, normalizeWxsFilename(value, normalizedScriptExtension ?? "wxs"));
12315
- if (shouldNormalizeTemplateImports) for (const { start, end, value } of templateImportNormalizeTokens) {
12316
- let nextValue = changeFileExtension(value, normalizedTemplateExtension);
12317
- if (value.startsWith("./") && !nextValue.startsWith("./") && !nextValue.startsWith("../") && !nextValue.startsWith("/")) nextValue = `./${nextValue}`;
12318
- ms.update(start, end, nextValue);
12319
- }
12320
- if (shouldRemoveLang) for (const { start, end } of removeWxsLangAttrTokens) ms.update(start, end, "");
12321
- if (shouldTransformInlineWxs) for (const { end, start, value } of inlineWxsTokens) {
12322
- const { result } = getCachedInlineWxsTransform(value, normalizedScriptExtension ?? "wxs");
12323
- if (result?.code) ms.update(start, end, `\n${result.code}`);
12324
- }
12325
- if (shouldTransformScriptModuleTags) {
12326
- const visited = /* @__PURE__ */ new Set();
12327
- for (const { start, end } of scriptModuleTagTokens) {
12328
- const key = `${start}:${end}`;
12329
- if (visited.has(key)) continue;
12330
- visited.add(key);
12331
- ms.update(start, end, resolvedScriptTag);
12159
+ return Object.assign(async function loadEntry(id, type) {
12160
+ existsCache.clear();
12161
+ const stopwatch = debug ? createStopwatch() : void 0;
12162
+ const getTime = () => stopwatch ? stopwatch() : "0.00ms";
12163
+ const relativeCwdId = configService.relativeCwd(id);
12164
+ const normalizedId = normalizeFsResolvedId(id);
12165
+ const libConfig = configService.weappLibConfig;
12166
+ const libEntry = libConfig?.enabled && normalizedId ? ctx.runtimeState.lib.entries.get(normalizedId) : void 0;
12167
+ addNormalizedWatchFile(this, id);
12168
+ const baseName = removeExtensionDeep(id);
12169
+ const jsonEntry = await findJsonEntry(id);
12170
+ let jsonPath = jsonEntry.path;
12171
+ let hasJsonEntry = Boolean(jsonPath);
12172
+ for (const prediction of jsonEntry.predictions) await addWatchTarget(this, prediction, existsCache, pathExistsTtlMs);
12173
+ let json = {};
12174
+ if (jsonPath) json = await jsonService.read(jsonPath);
12175
+ else jsonPath = changeFileExtension(id, ".json");
12176
+ const vueEntryPath = id.endsWith(".vue") ? id : await findVueEntry(removeExtensionDeep(id));
12177
+ if (vueEntryPath) addNormalizedWatchFile(this, vueEntryPath);
12178
+ if (!jsonEntry.path) {
12179
+ if (vueEntryPath) {
12180
+ const configFromVue = await extractConfigFromVue(vueEntryPath);
12181
+ if (configFromVue && typeof configFromVue === "object") {
12182
+ json = configFromVue;
12183
+ hasJsonEntry = true;
12184
+ }
12185
+ }
12332
12186
  }
12333
- }
12334
- if (shouldTransformEvents) for (const { end, start, value } of eventTokens) ms.update(start, end, value);
12335
- if (shouldTransformDirectives) for (const { end, start, value } of directiveTokens) ms.update(start, end, value);
12336
- if (shouldTransformTagNames) for (const { end, start, value } of tagNameTokens) ms.update(start, end, value);
12337
- if (shouldRemoveConditionals) {
12338
- for (const { start, end } of removalRanges) if (end > start) ms.remove(start, end);
12339
- }
12340
- if (shouldRemoveComments) for (const { end, start } of commentTokens) ms.remove(start, end);
12341
- return setCachedResult(data, cacheKey, {
12342
- code: shouldNormalizeScriptModuleAttributes(resolvedScriptTag) ? normalizeImportSjsAttributes(ms.toString()) : ms.toString(),
12343
- components,
12344
- deps
12345
- });
12187
+ const entries = [];
12188
+ const explicitEntryTypes = /* @__PURE__ */ new Map();
12189
+ let templatePath = "";
12190
+ let entryTypeOverride;
12191
+ let pluginResolvedRecords;
12192
+ let pluginJsonPathForRegistration;
12193
+ let pluginJsonForRegistration;
12194
+ let appResult;
12195
+ let shouldSkipAppEntries = false;
12196
+ const nativeLayoutScriptEntries = /* @__PURE__ */ new Set();
12197
+ const autoRoutesSignature = configService.isDev ? ctx.autoRoutesService?.getSignature?.() : void 0;
12198
+ if (type === "app") {
12199
+ appResult = await collectAppEntries({
12200
+ pluginCtx: this,
12201
+ id,
12202
+ json,
12203
+ ctx,
12204
+ isPluginBuild,
12205
+ registerJsonAsset,
12206
+ existsCache,
12207
+ pathExistsTtlMs,
12208
+ normalizeEntry,
12209
+ resolveEntryWithCache: entryResolver.resolveEntryWithCache,
12210
+ extendedLibManager,
12211
+ cache: appEntriesCache
12212
+ });
12213
+ entries.push(...appResult.entries);
12214
+ if (get(json, "tabBar.custom")) explicitEntryTypes.set(normalizeEntry("custom-tab-bar/index", jsonPath), "component");
12215
+ if (get(json, "appBar")) explicitEntryTypes.set(normalizeEntry("app-bar/index", jsonPath), "component");
12216
+ pluginResolvedRecords = appResult.pluginResolvedRecords;
12217
+ if (appResult.pluginEntryTypes?.length) for (const entryType of appResult.pluginEntryTypes) entriesMap.set(entryType.entry, {
12218
+ type: entryType.type,
12219
+ path: entryType.entry
12220
+ });
12221
+ pluginJsonPathForRegistration = appResult.pluginJsonPathForRegistration;
12222
+ pluginJsonForRegistration = appResult.pluginJsonForRegistration;
12223
+ shouldSkipAppEntries = Boolean(configService.isDev && !isPluginBuild && appResult.cacheHit && appEntryOutputCache.current && appEntryOutputCache.current.appSignature === appResult.appSignature && appEntryOutputCache.current.pluginSignature === appResult.pluginSignature && appEntryOutputCache.current.pluginJsonPath === appResult.pluginJsonPath && appEntryOutputCache.current.autoRoutesSignature === autoRoutesSignature && appEntryOutputCache.current.resolveCacheVersion === resolveCacheVersion);
12224
+ } else {
12225
+ templatePath = await scanTemplateEntry(this, id, scanTemplateEntryFn, existsCache, pathExistsTtlMs);
12226
+ if (libEntry && libConfig) {
12227
+ const componentJson = libConfig.componentJson ?? "auto";
12228
+ const hasTemplate = Boolean(templatePath) || id.endsWith(".vue");
12229
+ const styleEntry = await findCssEntry(baseName);
12230
+ const hasStyle = Boolean(styleEntry.path);
12231
+ const shouldTreatAsComponent = hasTemplate || hasStyle || Boolean(json?.component);
12232
+ if (!hasJsonEntry && shouldTreatAsComponent) {
12233
+ if (componentJson === true || componentJson === "auto" || typeof componentJson === "function") {
12234
+ const extra = typeof componentJson === "function" ? componentJson({
12235
+ name: libEntry.name,
12236
+ input: libEntry.input
12237
+ }) : void 0;
12238
+ if (typeof componentJson === "function" && !isObject(extra)) throw new Error("`weapp.lib.componentJson` 必须返回对象。");
12239
+ json = {
12240
+ component: true,
12241
+ ...isObject(extra) ? extra : {}
12242
+ };
12243
+ hasJsonEntry = true;
12244
+ }
12245
+ }
12246
+ if (shouldTreatAsComponent) entryTypeOverride = "component";
12247
+ }
12248
+ if (vueEntryPath) {
12249
+ await applyScriptSetupUsingComponents({
12250
+ pluginCtx: this,
12251
+ vueEntryPath,
12252
+ templatePath,
12253
+ json,
12254
+ configService,
12255
+ wxmlService,
12256
+ reExportResolutionCache
12257
+ });
12258
+ if (type === "page") {
12259
+ const layoutPlan = await resolvePageLayoutPlan(await fs.readFile(vueEntryPath, "utf-8"), vueEntryPath, configService);
12260
+ if (layoutPlan) {
12261
+ await addResolvedPageLayoutWatchFiles(this, layoutPlan.layouts);
12262
+ await registerResolvedPageLayoutEntries({
12263
+ layouts: layoutPlan.layouts,
12264
+ entries,
12265
+ explicitEntryTypes,
12266
+ nativeScriptEntries: nativeLayoutScriptEntries,
12267
+ normalizeEntry,
12268
+ jsonPath
12269
+ });
12270
+ for (const layout of layoutPlan.layouts) {
12271
+ if (layout.kind === "native") continue;
12272
+ if (!layout.file.endsWith(".vue")) continue;
12273
+ if (!await shouldEmitScriptlessVueLayoutJs$1(layout.file)) continue;
12274
+ const relativeLayoutBase = configService.relativeOutputPath(removeExtensionDeep(layout.file));
12275
+ if (!relativeLayoutBase || emittedScriptlessVueLayoutJs.has(relativeLayoutBase)) continue;
12276
+ emittedScriptlessVueLayoutJs.add(relativeLayoutBase);
12277
+ const { scriptExtension } = resolveCompilerOutputExtensions(configService.outputExtensions);
12278
+ emitScriptlessComponentAsset(this, resolveScriptlessComponentFileName(relativeLayoutBase, scriptExtension));
12279
+ }
12280
+ }
12281
+ }
12282
+ }
12283
+ await ctx.autoImportService?.awaitPendingRegistrations?.();
12284
+ applyAutoImports(baseName, json);
12285
+ const componentEntries = analyzeCommonJson(json);
12286
+ entries.push(...componentEntries);
12287
+ for (const componentEntry of componentEntries) explicitEntryTypes.set(normalizeEntry(componentEntry, jsonPath), "component");
12288
+ }
12289
+ const normalizedEntries = shouldSkipAppEntries ? [] : prepareNormalizedEntries({
12290
+ entries,
12291
+ json,
12292
+ jsonPath,
12293
+ templatePath,
12294
+ id,
12295
+ skipOwnEntries: isPluginBuild && type === "app",
12296
+ entriesMap,
12297
+ normalizeEntry,
12298
+ extendedLibManager,
12299
+ entryType: entryTypeOverride,
12300
+ explicitEntryTypes
12301
+ });
12302
+ markComponentEntries(entriesMap, nativeLayoutScriptEntries);
12303
+ const entryResolveRoot = isPluginBuild && configService.absolutePluginRoot && isPathInside(configService.absolutePluginRoot, id) ? configService.absolutePluginRoot : configService.absoluteSrcRoot;
12304
+ const result = await emitEntryOutput({
12305
+ pluginCtx: this,
12306
+ id,
12307
+ type,
12308
+ json,
12309
+ jsonPath,
12310
+ templatePath,
12311
+ isPluginBuild,
12312
+ normalizedEntries,
12313
+ pluginResolvedRecords,
12314
+ pluginJsonPathForRegistration,
12315
+ pluginJsonForRegistration,
12316
+ resolveEntriesWithCache: entryResolver.resolveEntriesWithCache,
12317
+ entryResolveRoot,
12318
+ configService,
12319
+ wxmlService,
12320
+ resolvedEntryMap,
12321
+ loadedEntrySet,
12322
+ dirtyEntrySet,
12323
+ replaceLayoutDependencies,
12324
+ emitEntriesChunks,
12325
+ registerJsonAsset,
12326
+ existsCache,
12327
+ pathExistsTtlMs,
12328
+ debug,
12329
+ relativeCwdId,
12330
+ getTime,
12331
+ emittedWxmlCodeCache: ctx.runtimeState?.wxml?.emittedCode,
12332
+ skipEntries: shouldSkipAppEntries
12333
+ });
12334
+ if (type === "app" && !shouldSkipAppEntries && appResult) appEntryOutputCache.current = {
12335
+ appSignature: appResult.appSignature,
12336
+ pluginSignature: appResult.pluginSignature,
12337
+ pluginJsonPath: appResult.pluginJsonPath,
12338
+ autoRoutesSignature,
12339
+ resolveCacheVersion
12340
+ };
12341
+ return result;
12342
+ }, { invalidateResolveCache() {
12343
+ entryResolver.invalidate();
12344
+ scriptlessVueLayoutDecisionCache.clear();
12345
+ resolveCacheVersion += 1;
12346
+ appEntryOutputCache.current = void 0;
12347
+ } });
12346
12348
  }
12347
12349
  //#endregion
12348
- //#region src/plugins/utils/wxmlEmit.ts
12349
- function resolveWxmlEmitContext(compiler) {
12350
- const { wxmlService, configService, scanService } = compiler;
12351
- if (!wxmlService || !configService || !scanService) throw new Error("emitWxmlAssets 需要先初始化 wxmlService、configService 和 scanService。");
12352
- const { templateExtension, scriptModuleExtension } = resolveCompilerOutputExtensions(configService.outputExtensions);
12353
- return {
12354
- wxmlService,
12355
- configService,
12356
- scanService,
12357
- templateExtension,
12358
- scriptModuleExtension,
12359
- scriptModuleTag: resolveScriptModuleTagName({
12360
- platform: configService.platform,
12361
- scriptModuleExtension
12362
- })
12350
+ //#region src/plugins/hooks/useLoadEntry/normalizer.ts
12351
+ const PLUGIN_PROTOCOL_RE = /plugin:\/\//;
12352
+ const WINDOWS_PATH_SEPARATOR_RE = /\\/g;
12353
+ function resolveImportee(importee, jsonPath, configService) {
12354
+ let updated = importee;
12355
+ if (jsonPath && Array.isArray(configService.aliasEntries)) {
12356
+ const matchedEntry = configService.aliasEntries.find((entry) => matches(entry.find, importee));
12357
+ if (matchedEntry) updated = importee.replace(matchedEntry.find, matchedEntry.replacement);
12358
+ }
12359
+ const baseDir = jsonPath ? path.dirname(jsonPath) : configService.absoluteSrcRoot;
12360
+ return path.resolve(baseDir, updated);
12361
+ }
12362
+ function createEntryNormalizer(configService) {
12363
+ return function normalizeEntry(entry, jsonPath) {
12364
+ if (PLUGIN_PROTOCOL_RE.test(entry)) return entry;
12365
+ const normalizedEntry = normalizeNpmImportLookupPath(entry);
12366
+ if (normalizedEntry && isObject(configService.packageJson.dependencies) && hasNpmDependencyPrefix(configService.packageJson.dependencies, normalizedEntry)) return `npm:${normalizedEntry}`;
12367
+ if (entry.replace(WINDOWS_PATH_SEPARATOR_RE, "/").startsWith("/")) return normalizedEntry;
12368
+ const normalized = resolveImportee(normalizedEntry, jsonPath, configService);
12369
+ return configService.relativeAbsoluteSrcRoot(normalized);
12363
12370
  };
12364
12371
  }
12365
- function resolveWxmlEmitTargets(options) {
12366
- const { compiler, subPackageMeta, buildTarget = "app" } = options;
12367
- const { wxmlService, configService, scanService, templateExtension } = resolveWxmlEmitContext(compiler);
12368
- return Array.from(wxmlService.tokenMap.entries()).map(([id, token]) => {
12369
- return {
12370
- id,
12371
- token,
12372
- fileName: resolveRelativeOutputFileNameWithExtension(configService, id, templateExtension)
12373
- };
12374
- }).filter(({ id, fileName }) => {
12375
- if (subPackageMeta) return fileName.startsWith(subPackageMeta.subPackage.root);
12376
- if (buildTarget === "plugin") {
12377
- const pluginRoot = configService.absolutePluginRoot;
12378
- if (!pluginRoot) return false;
12379
- return isPathInside(pluginRoot, id);
12372
+ //#endregion
12373
+ //#region src/plugins/hooks/useLoadEntry/template.ts
12374
+ function createTemplateScanner(wxmlService, debug) {
12375
+ return async function scanTemplateEntry(templateEntry) {
12376
+ const start = performance$1.now();
12377
+ const wxmlToken = await wxmlService.scan(templateEntry);
12378
+ if (wxmlToken) {
12379
+ const { components } = wxmlToken;
12380
+ wxmlService.setWxmlComponentsMap(templateEntry, components);
12380
12381
  }
12381
- return scanService.isMainPackageFileName(fileName);
12382
- });
12382
+ debug?.(`scanTemplateEntry ${templateEntry} 耗时 ${(performance$1.now() - start).toFixed(2)}ms`);
12383
+ };
12383
12384
  }
12384
- function emitWxmlAssetFile(options) {
12385
- const { runtime, id, fileName, token, deps, emittedCodeCache, scriptModuleExtension, scriptModuleTag, templateExtension } = options;
12386
- runtime.addWatchFile?.(normalizeWatchPath(id));
12387
- if (deps) for (const dep of deps) runtime.addWatchFile?.(normalizeWatchPath(dep));
12388
- const result = handleWxml(token, {
12389
- scriptModuleExtension,
12390
- scriptModuleTag,
12391
- templateExtension
12392
- });
12393
- if (emittedCodeCache.get(fileName) === result.code) return false;
12394
- emittedCodeCache.set(fileName, result.code);
12395
- runtime.emitFile({
12396
- type: "asset",
12397
- fileName,
12398
- source: result.code
12385
+ //#endregion
12386
+ //#region src/plugins/hooks/useLoadEntry/index.ts
12387
+ function useLoadEntry(ctx, options) {
12388
+ const debug = createDebugger("weapp-vite:load-entry");
12389
+ const buildTarget = options?.buildTarget ?? "app";
12390
+ const entriesMap = /* @__PURE__ */ new Map();
12391
+ const loadedEntrySet = /* @__PURE__ */ new Set();
12392
+ const dirtyEntrySet = /* @__PURE__ */ new Set();
12393
+ const dirtyEntryReasons = /* @__PURE__ */ new Map();
12394
+ const resolvedEntryMap = /* @__PURE__ */ new Map();
12395
+ const layoutEntryDependents = /* @__PURE__ */ new Map();
12396
+ const entryLayoutDependencies = /* @__PURE__ */ new Map();
12397
+ const jsonEmitManager = createJsonEmitManager(ctx.configService);
12398
+ const registerJsonAsset = jsonEmitManager.register.bind(jsonEmitManager);
12399
+ const normalizeEntry = createEntryNormalizer(ctx.configService);
12400
+ const scanTemplateEntry = createTemplateScanner(ctx.wxmlService, debug);
12401
+ const emitEntriesChunks = createChunkEmitter(ctx.configService, loadedEntrySet, debug);
12402
+ const loadEntry = createEntryLoader({
12403
+ ctx,
12404
+ entriesMap,
12405
+ loadedEntrySet,
12406
+ dirtyEntrySet,
12407
+ resolvedEntryMap,
12408
+ replaceLayoutDependencies(entryId, dependencies) {
12409
+ const previousDependencies = entryLayoutDependencies.get(entryId);
12410
+ if (previousDependencies) for (const dependency of previousDependencies) {
12411
+ const dependents = layoutEntryDependents.get(dependency);
12412
+ if (!dependents) continue;
12413
+ dependents.delete(entryId);
12414
+ if (dependents.size === 0) layoutEntryDependents.delete(dependency);
12415
+ }
12416
+ const normalizedDependencies = new Set(dependencies);
12417
+ if (normalizedDependencies.size === 0) {
12418
+ entryLayoutDependencies.delete(entryId);
12419
+ return;
12420
+ }
12421
+ entryLayoutDependencies.set(entryId, normalizedDependencies);
12422
+ for (const dependency of normalizedDependencies) {
12423
+ let dependents = layoutEntryDependents.get(dependency);
12424
+ if (!dependents) {
12425
+ dependents = /* @__PURE__ */ new Set();
12426
+ layoutEntryDependents.set(dependency, dependents);
12427
+ }
12428
+ dependents.add(entryId);
12429
+ }
12430
+ },
12431
+ normalizeEntry,
12432
+ registerJsonAsset,
12433
+ scanTemplateEntry,
12434
+ emitEntriesChunks,
12435
+ applyAutoImports: createAutoImportAugmenter(ctx.autoImportService, ctx.wxmlService),
12436
+ extendedLibManager: createExtendedLibManager(),
12437
+ buildTarget,
12438
+ debug
12399
12439
  });
12400
- return true;
12440
+ const hmrSharedChunksMode = options?.hmr?.sharedChunks ?? "auto";
12441
+ const hmrSharedChunkImporters = options?.hmr?.sharedChunkImporters;
12442
+ return {
12443
+ loadEntry,
12444
+ entriesMap,
12445
+ loadedEntrySet,
12446
+ dirtyEntrySet,
12447
+ resolvedEntryMap,
12448
+ layoutEntryDependents,
12449
+ jsonEmitFilesMap: jsonEmitManager.map,
12450
+ normalizeEntry,
12451
+ markEntryDirty(entryId, reason = "direct") {
12452
+ dirtyEntrySet.add(entryId);
12453
+ dirtyEntryReasons.set(entryId, reason);
12454
+ loadedEntrySet.delete(entryId);
12455
+ },
12456
+ async emitDirtyEntries() {
12457
+ if (!dirtyEntrySet.size) {
12458
+ options?.hmr?.setDidEmitAllEntries?.(false);
12459
+ options?.hmr?.setLastEmittedEntries?.(/* @__PURE__ */ new Set());
12460
+ return;
12461
+ }
12462
+ const dirtyCount = dirtyEntrySet.size;
12463
+ const pendingEntryIds = resolvePendingEntryIds({
12464
+ isDev: Boolean(ctx.configService?.isDev),
12465
+ mode: hmrSharedChunksMode,
12466
+ resolvedEntryMap,
12467
+ dirtyEntrySet,
12468
+ dirtyEntryReasons,
12469
+ sharedChunkImporters: hmrSharedChunkImporters,
12470
+ subPackageRoots: new Set(ctx.scanService?.subPackageMap?.keys?.() ?? []),
12471
+ relativeAbsoluteSrcRoot: ctx.configService.relativeAbsoluteSrcRoot.bind(ctx.configService)
12472
+ });
12473
+ const pending = [];
12474
+ const shouldEmitAllEntries = pendingEntryIds.size > 0 && pendingEntryIds.size === resolvedEntryMap.size;
12475
+ options?.hmr?.setDidEmitAllEntries?.(shouldEmitAllEntries);
12476
+ options?.hmr?.setLastEmittedEntries?.(new Set(pendingEntryIds));
12477
+ for (const entryId of pendingEntryIds) {
12478
+ const resolvedId = resolvedEntryMap.get(entryId);
12479
+ if (!resolvedId) continue;
12480
+ pending.push(resolvedId);
12481
+ dirtyEntrySet.delete(entryId);
12482
+ dirtyEntryReasons.delete(entryId);
12483
+ }
12484
+ if (debug) debug(`hmr emit dirty=${dirtyCount} resolved=${resolvedEntryMap.size} emitAll=${shouldEmitAllEntries} pending=${pending.length}`);
12485
+ if (pending.length) await Promise.all(emitEntriesChunks.call(this, pending));
12486
+ }
12487
+ };
12401
12488
  }
12402
- function emitWxmlAssetsWithCache(options) {
12403
- const { runtime, compiler, subPackageMeta, emittedCodeCache, buildTarget = "app" } = options;
12404
- const { wxmlService, templateExtension, scriptModuleExtension, scriptModuleTag } = resolveWxmlEmitContext(compiler);
12405
- const currentPackageWxmls = resolveWxmlEmitTargets({
12406
- compiler,
12407
- subPackageMeta,
12408
- buildTarget
12409
- });
12410
- const emittedFiles = [];
12411
- for (const { id, fileName, token } of currentPackageWxmls) {
12412
- emittedFiles.push(fileName);
12413
- emitWxmlAssetFile({
12414
- runtime,
12415
- id,
12416
- fileName,
12417
- token,
12418
- deps: wxmlService.depsMap.get(id),
12419
- emittedCodeCache,
12420
- scriptModuleExtension,
12421
- scriptModuleTag,
12422
- templateExtension
12423
- });
12489
+ function resolvePendingEntryIds(options) {
12490
+ const pending = new Set(options.dirtyEntrySet);
12491
+ if (options.mode === "full") return new Set(options.resolvedEntryMap.keys());
12492
+ if (!options.isDev || options.mode === "off") return pending;
12493
+ if (!options.sharedChunkImporters?.size) return pending;
12494
+ for (const importers of options.sharedChunkImporters.values()) {
12495
+ if (importers.size <= 1) continue;
12496
+ let hasDependencyDrivenImporter = false;
12497
+ let hasDirectDirtyImporter = false;
12498
+ for (const importer of importers) {
12499
+ if (options.dirtyEntrySet.has(importer) && options.dirtyEntryReasons.get(importer) === "dependency") {
12500
+ hasDependencyDrivenImporter = true;
12501
+ break;
12502
+ }
12503
+ if (options.dirtyEntrySet.has(importer) && options.dirtyEntryReasons.get(importer) === "direct") hasDirectDirtyImporter = true;
12504
+ }
12505
+ if (!hasDependencyDrivenImporter && !hasDirectDirtyImporter) continue;
12506
+ for (const importer of importers) pending.add(importer);
12424
12507
  }
12425
- return emittedFiles;
12426
- }
12427
- function emitJsonAsset(runtime, fileName, source, extension = "json") {
12428
- runtime.emitFile({
12429
- type: "asset",
12430
- fileName: changeFileExtension(fileName, extension),
12431
- source
12432
- });
12508
+ return pending;
12433
12509
  }
12434
12510
  //#endregion
12435
12511
  //#region src/plugins/core/helpers/bundle.ts
@@ -13986,11 +14062,20 @@ function invalidateSharedStyleCache() {
13986
14062
  //#region src/plugins/utils/invalidateEntry/shared.ts
13987
14063
  const watchedCssExts = new Set(supportedCssLangs.map((ext) => `.${ext}`));
13988
14064
  const watchedTemplateExts = new Set(templateExtensions.map((ext) => `.${ext}`));
14065
+ const watchedScriptModuleExts = new Set([
14066
+ ".wxs",
14067
+ ".sjs",
14068
+ ".wxs.ts",
14069
+ ".wxs.js",
14070
+ ".sjs.ts",
14071
+ ".sjs.js"
14072
+ ]);
13989
14073
  const configSuffixes$1 = configExtensions.map((ext) => `.${ext}`);
13990
14074
  const sidecarSuffixes = [
13991
14075
  ...configSuffixes$1,
13992
14076
  ...watchedCssExts,
13993
- ...watchedTemplateExts
14077
+ ...watchedTemplateExts,
14078
+ ...watchedScriptModuleExts
13994
14079
  ];
13995
14080
  const defaultIgnoredDirNames = new Set([
13996
14081
  "node_modules",
@@ -14164,15 +14249,26 @@ async function invalidateEntryForSidecar(ctx, filePath, event = "update") {
14164
14249
  if (configSuffix) scriptBasePath = filePath.slice(0, -configSuffix.length);
14165
14250
  else if (ext && watchedCssExts.has(ext)) scriptBasePath = filePath.slice(0, -ext.length);
14166
14251
  else if (ext && watchedTemplateExts.has(ext)) scriptBasePath = filePath.slice(0, -ext.length);
14167
- if (!scriptBasePath) return;
14252
+ const isScriptModuleSidecar = Array.from(watchedScriptModuleExts).some((suffix) => normalizedPath.endsWith(suffix));
14253
+ if (!scriptBasePath && !isScriptModuleSidecar) return;
14168
14254
  const touchedTargets = /* @__PURE__ */ new Set();
14169
14255
  const touchedScripts = /* @__PURE__ */ new Set();
14170
- const primaryScript = await findJsEntry(scriptBasePath);
14171
- if (primaryScript.path) touchedScripts.add(primaryScript.path);
14172
- if (!primaryScript.path && ext && watchedCssExts.has(ext)) {
14173
- const { importers, scripts } = await collectAffectedScriptsAndImporters(ctx, normalizedPath);
14256
+ if (isScriptModuleSidecar || ext && watchedTemplateExts.has(ext)) {
14257
+ const importers = ctx.wxmlService?.getImporters(normalizedPath) ?? /* @__PURE__ */ new Set();
14174
14258
  for (const importer of importers) touchedTargets.add(importer);
14175
- for (const script of scripts) touchedScripts.add(script);
14259
+ }
14260
+ if (scriptBasePath) {
14261
+ const primaryScript = await findJsEntry(scriptBasePath);
14262
+ if (primaryScript.path) touchedScripts.add(primaryScript.path);
14263
+ else if (ext && watchedTemplateExts.has(ext)) {
14264
+ const primaryVueEntry = await findVueEntry(scriptBasePath);
14265
+ if (primaryVueEntry) touchedTargets.add(primaryVueEntry);
14266
+ }
14267
+ if (!primaryScript.path && ext && watchedCssExts.has(ext)) {
14268
+ const { importers, scripts } = await collectAffectedScriptsAndImporters(ctx, normalizedPath);
14269
+ for (const importer of importers) touchedTargets.add(importer);
14270
+ for (const script of scripts) touchedScripts.add(script);
14271
+ }
14176
14272
  }
14177
14273
  const isCssSidecar = Boolean(ext && watchedCssExts.has(ext));
14178
14274
  const isTemplateSidecar = Boolean(ext && watchedTemplateExts.has(ext));
@@ -14185,7 +14281,7 @@ async function invalidateEntryForSidecar(ctx, filePath, event = "update") {
14185
14281
  await touch(script);
14186
14282
  } catch {}
14187
14283
  if (!touchedTargets.size && !touchedScripts.size) {
14188
- if (event === "create" && (isCssSidecar || isTemplateSidecar)) logger_default.info(`[sidecar:${event}] ${relativeSource} 新增,但未找到引用方,等待后续关联`);
14284
+ if (event === "create" && (isCssSidecar || isTemplateSidecar || isScriptModuleSidecar)) logger_default.info(`[sidecar:${event}] ${relativeSource} 新增,但未找到引用方,等待后续关联`);
14189
14285
  return;
14190
14286
  }
14191
14287
  const touchedList = [];
@@ -14210,9 +14306,12 @@ function ensureSidecarWatcher(ctx, rootDir) {
14210
14306
  if (!isSidecarFile(filePath)) return;
14211
14307
  const ext = path.extname(filePath);
14212
14308
  const isCssFile = Boolean(ext && watchedCssExts.has(ext));
14309
+ const isTemplateFile = Boolean(ext && watchedTemplateExts.has(ext));
14310
+ const isScriptModuleFile = Array.from(watchedScriptModuleExts).some((suffix) => filePath.endsWith(suffix));
14311
+ const hasReverseImporters = Boolean(isTemplateFile || isScriptModuleFile) && (ctx.wxmlService?.getImporters(filePath).size ?? 0) > 0;
14213
14312
  if (isCssFile && (event === "create" || event === "update")) extractCssImportDependencies(ctx, filePath);
14214
14313
  const isDeleteEvent = event === "delete";
14215
- if (event === "create" && ready || isDeleteEvent) {
14314
+ if (event === "create" && ready || isDeleteEvent || event === "update" && hasReverseImporters) {
14216
14315
  (async () => {
14217
14316
  await invalidateEntryForSidecar(ctx, filePath, event);
14218
14317
  if (isCssFile && isDeleteEvent) cleanupCssImporterGraph(ctx, filePath);
@@ -14224,7 +14323,8 @@ function ensureSidecarWatcher(ctx, rootDir) {
14224
14323
  const patterns = [
14225
14324
  ...configExtensions.map((ext) => path.join(absRoot, `**/*.${ext}`)),
14226
14325
  ...supportedCssLangs.map((ext) => path.join(absRoot, `**/*.${ext}`)),
14227
- ...templateExtensions.map((ext) => path.join(absRoot, `**/*.${ext}`))
14326
+ ...templateExtensions.map((ext) => path.join(absRoot, `**/*.${ext}`)),
14327
+ ...Array.from(watchedScriptModuleExts).map((ext) => path.join(absRoot, `**/*${ext}`))
14228
14328
  ];
14229
14329
  const ignoredMatcher = createSidecarIgnoredMatcher(ctx, absRoot);
14230
14330
  const watcher = chokidar.watch(patterns, createSidecarWatchOptions(ctx.configService, {
@@ -14647,8 +14747,9 @@ function injectSharedStyleImports(css, modulePath, fileName, sharedStyles, confi
14647
14747
  }
14648
14748
  //#endregion
14649
14749
  //#region src/plugins/css.ts
14750
+ const LEADING_BLANK_LINES_RE = /^(?:[ \t]*\r?\n)+/;
14650
14751
  function stripLeadingBlankLines(code) {
14651
- return code.replace(/^(?:[ \t]*\r?\n)+/, "");
14752
+ return code.replace(LEADING_BLANK_LINES_RE, "");
14652
14753
  }
14653
14754
  async function handleBundleEntry(bundle, bundleKey, asset, configService, sharedStyles, emitted) {
14654
14755
  if (asset.type !== "asset") return;
@@ -14847,6 +14948,7 @@ function registerVueTemplateToken(ctx, filename, template) {
14847
14948
  try {
14848
14949
  const token = wxmlService.analyze(template);
14849
14950
  wxmlService.tokenMap.set(filename, token);
14951
+ wxmlService.setDeps(filename, wxmlService.collectDepsFromToken(filename, token.deps));
14850
14952
  wxmlService.setWxmlComponentsMap(filename, token.components);
14851
14953
  } catch {}
14852
14954
  }
@@ -18806,10 +18908,10 @@ function createDependenciesCache(ctx) {
18806
18908
  }
18807
18909
  //#endregion
18808
18910
  //#region src/runtime/npmPlugin/relations.ts
18809
- const TRAILING_SLASHES_RE = /\/+$/;
18911
+ const TRAILING_SLASHES_RE$1 = /\/+$/;
18810
18912
  const EMPTY_VALUE_RE = /^$/;
18811
18913
  function normalizeRelativeDir(value) {
18812
- const normalized = toPosixPath(value).replace(TRAILING_SLASHES_RE, "");
18914
+ const normalized = toPosixPath(value).replace(TRAILING_SLASHES_RE$1, "");
18813
18915
  return (normalized.startsWith("./") ? normalized.slice(2) : normalized).replace(EMPTY_VALUE_RE, ".");
18814
18916
  }
18815
18917
  function resolvePlatformProjectRoot(configService) {
@@ -18859,6 +18961,8 @@ function getPackNpmRelationList(ctx) {
18859
18961
  //#endregion
18860
18962
  //#region src/runtime/npmPlugin/service.ts
18861
18963
  const LEADING_SLASHES_RE = /^\/+/;
18964
+ const WINDOWS_PATH_RE = /\\|^[A-Z]:[\\/]/i;
18965
+ const TRAILING_SLASHES_RE = /\/+$/;
18862
18966
  function matchDependencyName(patterns, dep) {
18863
18967
  return patterns.some((pattern) => {
18864
18968
  if (typeof pattern === "string") return pattern === dep;
@@ -18876,6 +18980,13 @@ function matchDependencyPath(patterns, value) {
18876
18980
  return pattern.test(value);
18877
18981
  });
18878
18982
  }
18983
+ function resolveCopyFilterRelativePath(sourceRoot, sourcePath) {
18984
+ const normalizedRoot = normalizePath$1(sourceRoot).replace(TRAILING_SLASHES_RE, "");
18985
+ const normalizedPath = normalizePath$1(sourcePath);
18986
+ if (normalizedPath === normalizedRoot) return "";
18987
+ if (normalizedPath.startsWith(`${normalizedRoot}/`)) return normalizedPath.slice(normalizedRoot.length + 1);
18988
+ return toPosixPath(WINDOWS_PATH_RE.test(sourceRoot) || WINDOWS_PATH_RE.test(sourcePath) ? win32.relative(sourceRoot, sourcePath) : relative(sourceRoot, sourcePath));
18989
+ }
18879
18990
  function resolveTargetDependencies(allDependencies, patterns) {
18880
18991
  if (patterns === false) return [];
18881
18992
  if (!Array.isArray(patterns)) return allDependencies;
@@ -18974,7 +19085,7 @@ function createNpmService(ctx) {
18974
19085
  overwrite: true,
18975
19086
  filter: (src) => {
18976
19087
  if (Array.isArray(meta.subPackage.dependencies)) {
18977
- const relPath = toPosixPath(path.relative(sourceOutDir, src));
19088
+ const relPath = resolveCopyFilterRelativePath(sourceOutDir, String(src));
18978
19089
  if (relPath === "") return true;
18979
19090
  return matchDependencyPath(meta.subPackage.dependencies, relPath);
18980
19091
  }
@@ -19187,6 +19298,7 @@ function createRuntimeState() {
19187
19298
  },
19188
19299
  wxml: {
19189
19300
  depsMap: /* @__PURE__ */ new Map(),
19301
+ importerMap: /* @__PURE__ */ new Map(),
19190
19302
  tokenMap: /* @__PURE__ */ new Map(),
19191
19303
  componentsMap: /* @__PURE__ */ new Map(),
19192
19304
  cache: new FileCache(),
@@ -19195,6 +19307,7 @@ function createRuntimeState() {
19195
19307
  scan: {
19196
19308
  subPackageMap: /* @__PURE__ */ new Map(),
19197
19309
  independentSubPackageMap: /* @__PURE__ */ new Map(),
19310
+ warnedMessages: /* @__PURE__ */ new Set(),
19198
19311
  isDirty: true,
19199
19312
  independentDirtyRoots: /* @__PURE__ */ new Set(),
19200
19313
  pluginJsonPath: void 0
@@ -19499,7 +19612,12 @@ function resolveScanJsonEntryBasename(appDirname, location, fallbackName) {
19499
19612
  }
19500
19613
  function createScanService(ctx) {
19501
19614
  const scanState = ctx.runtimeState.scan;
19502
- const { subPackageMap, independentSubPackageMap, independentDirtyRoots } = scanState;
19615
+ const { subPackageMap, independentSubPackageMap, independentDirtyRoots, warnedMessages } = scanState;
19616
+ function warnOnce(message) {
19617
+ if (warnedMessages.has(message)) return;
19618
+ warnedMessages.add(message);
19619
+ logger_default.warn(message);
19620
+ }
19503
19621
  function mergeAutoRoutePages(pages, routePages) {
19504
19622
  if (routePages.length === 0) return pages;
19505
19623
  const existingPages = Array.isArray(pages) ? pages.filter((page) => typeof page === "string" && page.length > 0) : [];
@@ -19572,12 +19690,12 @@ function createScanService(ctx) {
19572
19690
  const vueAppPath = await findVueEntry(appBasename);
19573
19691
  let configFromVue;
19574
19692
  if (!appConfigFile && vueAppPath) {
19575
- const { extractConfigFromVue } = await import("./file-MiE605t6.mjs").then((n) => n.r);
19693
+ const { extractConfigFromVue } = await import("./file-Cf3pf5w7.mjs").then((n) => n.r);
19576
19694
  configFromVue = await extractConfigFromVue(vueAppPath);
19577
19695
  if (configFromVue) appConfigFile = vueAppPath;
19578
19696
  }
19579
- if (appEntryPath && vueAppPath) logger_default.warn(`[app] 检测到 ${path.basename(appEntryPath)} 与 ${path.basename(vueAppPath)} 同时存在,当前将优先使用 ${path.basename(appEntryPath)} 作为应用入口,${path.basename(vueAppPath)} 将被忽略。`);
19580
- if (discoveredAppConfigFile && vueAppPath) logger_default.warn(`[app] 检测到 ${path.basename(discoveredAppConfigFile)} 与 ${path.basename(vueAppPath)} 同时存在,当前将优先使用 ${path.basename(discoveredAppConfigFile)} 作为应用配置来源,${path.basename(vueAppPath)} 中的 app 配置不会生效。`);
19697
+ if (appEntryPath && vueAppPath) warnOnce(`[app] 检测到 ${path.basename(appEntryPath)} 与 ${path.basename(vueAppPath)} 同时存在,当前将优先使用 ${path.basename(appEntryPath)} 作为应用入口,${path.basename(vueAppPath)} 将被忽略。`);
19698
+ if (discoveredAppConfigFile && vueAppPath) warnOnce(`[app] 检测到 ${path.basename(discoveredAppConfigFile)} 与 ${path.basename(vueAppPath)} 同时存在,当前将优先使用 ${path.basename(discoveredAppConfigFile)} 作为应用配置来源,${path.basename(vueAppPath)} 中的 app 配置不会生效。`);
19581
19699
  if (ctx.configService.absolutePluginRoot) {
19582
19700
  const { path: pluginConfigFile } = await findJsonEntry(resolveScanPluginBasename(ctx.configService.absolutePluginRoot));
19583
19701
  if (pluginConfigFile) {
@@ -19635,10 +19753,12 @@ function createScanService(ctx) {
19635
19753
  const metas = [];
19636
19754
  const independentSubPackages = [...json.subPackages ?? [], ...json.subpackages ?? []];
19637
19755
  for (const subPackage of independentSubPackages) {
19638
- const subPackageConfig = configService.weappViteConfig?.subPackages?.[subPackage.root];
19639
- const npmSubPackageConfig = configService.weappViteConfig?.npm?.subPackages?.[subPackage.root];
19756
+ const normalizedRoot = subPackage.root ? normalizeRoot(subPackage.root) : void 0;
19757
+ const subPackageConfig = normalizedRoot ? configService.weappViteConfig?.subPackages?.[normalizedRoot] : void 0;
19758
+ const npmSubPackageConfig = normalizedRoot ? configService.weappViteConfig?.npm?.subPackages?.[normalizedRoot] : void 0;
19640
19759
  const resolvedSubPackage = {
19641
19760
  ...subPackage,
19761
+ ...normalizedRoot ? { root: normalizedRoot } : {},
19642
19762
  dependencies: npmSubPackageConfig?.dependencies,
19643
19763
  inlineConfig: subPackageConfig?.inlineConfig
19644
19764
  };
@@ -19650,11 +19770,11 @@ function createScanService(ctx) {
19650
19770
  meta.styleEntries = normalizeSubPackageStyleEntries(subPackageConfig?.styles, resolvedSubPackage, configService);
19651
19771
  meta.watchSharedStyles = subPackageConfig?.watchSharedStyles ?? true;
19652
19772
  metas.push(meta);
19653
- if (subPackage.root) {
19654
- subPackageMap.set(subPackage.root, meta);
19773
+ if (normalizedRoot) {
19774
+ subPackageMap.set(normalizedRoot, meta);
19655
19775
  if (subPackage.independent) {
19656
- independentSubPackageMap.set(subPackage.root, meta);
19657
- if (scanState.isDirty) independentDirtyRoots.add(subPackage.root);
19776
+ independentSubPackageMap.set(normalizedRoot, meta);
19777
+ if (scanState.isDirty) independentDirtyRoots.add(normalizedRoot);
19658
19778
  }
19659
19779
  }
19660
19780
  }
@@ -19665,8 +19785,9 @@ function createScanService(ctx) {
19665
19785
  throw new Error(`在 ${configService.absoluteSrcRoot} 目录下没有找到 \`app.json\`, 请确保你初始化了小程序项目,或者在 \`vite.config.ts\` 中设置的正确的 \`weapp.srcRoot\` 配置路径 `);
19666
19786
  }
19667
19787
  function isMainPackageFileName(fileName) {
19788
+ const normalizedFileName = toPosixPath(fileName);
19668
19789
  return [...independentSubPackageMap.keys()].every((root) => {
19669
- return !fileName.startsWith(root);
19790
+ return !normalizedFileName.startsWith(root);
19670
19791
  });
19671
19792
  }
19672
19793
  return {
@@ -19710,7 +19831,8 @@ function createScanService(ctx) {
19710
19831
  },
19711
19832
  markIndependentDirty(root) {
19712
19833
  if (!root) return;
19713
- if (independentSubPackageMap.has(root)) independentDirtyRoots.add(root);
19834
+ const normalizedRoot = normalizeRoot(root);
19835
+ if (independentSubPackageMap.has(normalizedRoot)) independentDirtyRoots.add(normalizedRoot);
19714
19836
  },
19715
19837
  drainIndependentDirtyRoots() {
19716
19838
  const roots = [...independentDirtyRoots];
@@ -19839,17 +19961,49 @@ function createWebServicePlugin(ctx) {
19839
19961
  //#endregion
19840
19962
  //#region src/runtime/wxmlPlugin.ts
19841
19963
  function createWxmlService(ctx) {
19842
- const { depsMap, tokenMap, componentsMap, cache, emittedCode } = ctx.runtimeState.wxml;
19964
+ const { depsMap, importerMap, tokenMap, componentsMap, cache, emittedCode } = ctx.runtimeState.wxml;
19965
+ function linkImporter(dep, importer) {
19966
+ let importers = importerMap.get(dep);
19967
+ if (!importers) {
19968
+ importers = /* @__PURE__ */ new Set();
19969
+ importerMap.set(dep, importers);
19970
+ }
19971
+ importers.add(importer);
19972
+ }
19973
+ function unlinkImporter(dep, importer) {
19974
+ const importers = importerMap.get(dep);
19975
+ if (!importers) return;
19976
+ importers.delete(importer);
19977
+ if (importers.size === 0) importerMap.delete(dep);
19978
+ }
19979
+ async function setDeps(filepath, deps = []) {
19980
+ const nextDeps = new Set(deps);
19981
+ const previousDeps = depsMap.get(filepath) ?? /* @__PURE__ */ new Set();
19982
+ for (const previousDep of previousDeps) if (!nextDeps.has(previousDep)) unlinkImporter(previousDep, filepath);
19983
+ for (const dep of nextDeps) linkImporter(dep, filepath);
19984
+ depsMap.set(filepath, nextDeps);
19985
+ await Promise.all(Array.from(nextDeps).filter((dep) => isTemplate(dep)).map((dep) => {
19986
+ return scan(dep);
19987
+ }));
19988
+ }
19843
19989
  async function addDeps(filepath, deps = []) {
19844
- if (!depsMap.has(filepath)) {
19845
- const set = /* @__PURE__ */ new Set();
19846
- for (const dep of deps) set.add(dep);
19847
- depsMap.set(filepath, set);
19848
- await Promise.all(deps.map((dep) => scan(dep)));
19849
- } else {
19850
- const setRef = depsMap.get(filepath);
19851
- if (setRef) for (const dep of deps) setRef.add(dep);
19852
- }
19990
+ await setDeps(filepath, [...depsMap.get(filepath) ?? /* @__PURE__ */ new Set(), ...deps]);
19991
+ }
19992
+ function resolveDepPath(filepath, value) {
19993
+ const configService = requireConfigService(ctx, "解析 WXML 依赖前必须初始化 configService。");
19994
+ const dirname = path.dirname(filepath);
19995
+ if (value.startsWith("/")) return path.resolve(configService.absoluteSrcRoot, value.slice(1));
19996
+ return path.resolve(dirname, value);
19997
+ }
19998
+ function collectDepsFromToken(filepath, deps = []) {
19999
+ return deps.filter((dep) => {
20000
+ if (!dep.value) return false;
20001
+ if (isTemplateImportTag(dep.tagName)) return isTemplate(dep.value);
20002
+ return isScriptModuleTagName(dep.tagName);
20003
+ }).map((dep) => resolveDepPath(filepath, dep.value));
20004
+ }
20005
+ function getImporters(filepath) {
20006
+ return new Set(importerMap.get(filepath) ?? []);
19853
20007
  }
19854
20008
  function getAllDeps() {
19855
20009
  const set = /* @__PURE__ */ new Set();
@@ -19863,6 +20017,7 @@ function createWxmlService(ctx) {
19863
20017
  const currentRoot = ctx.configService?.currentSubPackageRoot;
19864
20018
  if (!currentRoot) {
19865
20019
  depsMap.clear();
20020
+ importerMap.clear();
19866
20021
  tokenMap.clear();
19867
20022
  componentsMap.clear();
19868
20023
  cache.cache.clear();
@@ -19876,14 +20031,20 @@ function createWxmlService(ctx) {
19876
20031
  };
19877
20032
  for (const key of Array.from(depsMap.keys())) {
19878
20033
  if (shouldClear(key)) {
20034
+ const depSet = depsMap.get(key);
20035
+ if (depSet) for (const dep of depSet) unlinkImporter(dep, key);
19879
20036
  depsMap.delete(key);
19880
20037
  continue;
19881
20038
  }
19882
20039
  const depSet = depsMap.get(key);
19883
20040
  if (depSet) {
19884
- for (const dep of Array.from(depSet)) if (shouldClear(dep)) depSet.delete(dep);
20041
+ for (const dep of Array.from(depSet)) if (shouldClear(dep)) {
20042
+ unlinkImporter(dep, key);
20043
+ depSet.delete(dep);
20044
+ }
19885
20045
  }
19886
20046
  }
20047
+ for (const key of Array.from(importerMap.keys())) if (shouldClear(key)) importerMap.delete(key);
19887
20048
  for (const key of Array.from(tokenMap.keys())) if (shouldClear(key)) tokenMap.delete(key);
19888
20049
  for (const key of Array.from(componentsMap.keys())) if (shouldClear(key)) componentsMap.delete(key);
19889
20050
  for (const key of Array.from(cache.cache.keys())) if (shouldClear(key)) cache.delete(key);
@@ -19924,14 +20085,10 @@ function createWxmlService(ctx) {
19924
20085
  return cached;
19925
20086
  }
19926
20087
  }
19927
- const dirname = path.dirname(filepath);
19928
20088
  const res = analyze(await fs.readFile(filepath, "utf8"));
19929
20089
  tokenMap.set(filepath, res);
19930
20090
  cache.set(filepath, res);
19931
- await addDeps(filepath, res.deps.filter((x) => isTemplateImportTag(x.tagName) && isTemplate(x.value)).map((x) => {
19932
- if (x.value.startsWith("/")) return path.resolve(configService.absoluteSrcRoot, x.value.slice(1));
19933
- else return path.resolve(dirname, x.value);
19934
- }));
20091
+ await setDeps(filepath, collectDepsFromToken(filepath, res.deps));
19935
20092
  return res;
19936
20093
  }
19937
20094
  function setWxmlComponentsMap(absPath, components) {
@@ -19939,9 +20096,13 @@ function createWxmlService(ctx) {
19939
20096
  }
19940
20097
  return {
19941
20098
  depsMap,
20099
+ importerMap,
19942
20100
  tokenMap,
19943
20101
  wxmlComponentsMap: componentsMap,
19944
20102
  addDeps,
20103
+ setDeps,
20104
+ collectDepsFromToken,
20105
+ getImporters,
19945
20106
  getAllDeps,
19946
20107
  clearAll,
19947
20108
  analyze,
@@ -20335,7 +20496,12 @@ async function syncProjectSupportFiles(ctx) {
20335
20496
  } else if (!shouldBootstrapAutoImportWithoutGlobs(autoImportConfig)) {}
20336
20497
  const templateTags = await collectAutoImportTemplateTags(ctx);
20337
20498
  for (const { tag, importerBaseName } of templateTags) ctx.autoImportService.resolve(tag, importerBaseName);
20338
- await ctx.autoImportService.awaitManifestWrites();
20499
+ ctx.autoImportService.setSupportFileResolverComponents(ctx.autoImportService.collectStaticResolverComponentsForSupportFiles());
20500
+ try {
20501
+ await ctx.autoImportService.awaitManifestWrites();
20502
+ } finally {
20503
+ ctx.autoImportService.clearSupportFileResolverComponents();
20504
+ }
20339
20505
  }
20340
20506
  return { managedTsconfigChanged };
20341
20507
  }