weapp-vite 6.13.3 → 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-BAUXs16l.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";
@@ -1665,12 +1664,12 @@ function createVueComponentsDefinition(componentNames, getMetadata, options = {}
1665
1664
  "// oxlint-disable",
1666
1665
  "// ------",
1667
1666
  "// 由 weapp-vite autoImportComponents 生成",
1668
- "import type { ComponentOptionsMixin, DefineComponent, PublicProps } from 'wevu'",
1667
+ "import type { ComponentOptionsMixin, DefineComponent, PublicProps, WeappIntrinsicElementBaseAttributes } from 'wevu'",
1669
1668
  ...options.useTypedComponents ? ["import type { ComponentProp } from 'weapp-vite/typed-components'"] : [],
1670
1669
  "",
1671
1670
  "export {}",
1672
1671
  "",
1673
- "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, {}>>",
1674
1673
  "type __WeappComponentImport<TModule, Fallback = {}> = 0 extends 1 & TModule ? Fallback : TModule extends { default: infer Component } ? Component & Fallback : Fallback",
1675
1674
  "",
1676
1675
  `declare module '${moduleName}' {`,
@@ -9964,7 +9963,7 @@ function asset(ctx) {
9964
9963
  const LEADING_DOT_SLASH_RE$2 = /^\.\//;
9965
9964
  const LEADING_SLASHES_RE$2 = /^\/+/;
9966
9965
  const GLOB_WILDCARD_RE = /[*?[{]/;
9967
- const TRAILING_SLASHES_RE$1 = /\/+$/;
9966
+ const TRAILING_SLASHES_RE$2 = /\/+$/;
9968
9967
  const AUTO_IMPORT_WATCHER_KEY = "__auto-import-vue-watcher__";
9969
9968
  const AUTO_IMPORT_CONFIG_SUFFIXES = configExtensions.map((ext) => `.${ext}`);
9970
9969
  const AUTO_IMPORT_JS_SUFFIXES = new Set(jsExtensions.map((ext) => `.${ext}`));
@@ -10070,7 +10069,7 @@ function registerAutoImportWatchTargets(state, globs, registrar, options = {}) {
10070
10069
  for (const pattern of globs ?? []) {
10071
10070
  const normalizedPattern = toPosixPath(pattern).replace(LEADING_DOT_SLASH_RE$2, "").replace(LEADING_SLASHES_RE$2, "");
10072
10071
  const wildcardIndex = normalizedPattern.search(GLOB_WILDCARD_RE);
10073
- 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, "");
10074
10073
  if (!cleanedBase) continue;
10075
10074
  watchTargets.add(path.resolve(configService.absoluteSrcRoot, cleanedBase));
10076
10075
  }
@@ -11037,6 +11036,16 @@ function normalizeRouteRuleLayoutMeta(input) {
11037
11036
  disabled: record.disabled === true
11038
11037
  };
11039
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
+ }
11040
11049
  function resolveRouteRuleLayoutMeta(filename, configService) {
11041
11050
  const routeRules = configService.weappViteConfig?.routeRules;
11042
11051
  if (!routeRules) return;
@@ -11061,16 +11070,6 @@ function resolveRouteRuleLayoutMeta(filename, configService) {
11061
11070
  }
11062
11071
  return matched?.meta;
11063
11072
  }
11064
- function compareRuleScore(left, right) {
11065
- const maxLength = Math.max(left.length, right.length);
11066
- for (let index = 0; index < maxLength; index += 1) {
11067
- const leftValue = left[index] ?? 0;
11068
- const rightValue = right[index] ?? 0;
11069
- if (leftValue === rightValue) continue;
11070
- return leftValue > rightValue ? 1 : -1;
11071
- }
11072
- return 0;
11073
- }
11074
11073
  async function collectLayoutFiles(root) {
11075
11074
  const layoutMap = /* @__PURE__ */ new Map();
11076
11075
  const comparableRoot = normalizeComparablePath(root);
@@ -11481,331 +11480,689 @@ function emitNativeLayoutScriptChunkIfNeeded$1(options) {
11481
11480
  return true;
11482
11481
  }
11483
11482
  //#endregion
11484
- //#region src/plugins/hooks/useLoadEntry/loadEntry/emit.ts
11485
- const NON_VUE_PAGE_RE = /\.vue$|\.jsx$|\.tsx$/;
11486
- function prepareNormalizedEntries(options) {
11487
- const { entries, json, jsonPath, templatePath, id, skipOwnEntries, entriesMap, normalizeEntry, extendedLibManager, entryType, explicitEntryTypes } = options;
11488
- const filteredEntries = skipOwnEntries ? [] : entries.filter((entry) => !extendedLibManager.shouldIgnoreEntry(entry));
11489
- const normalizedEntries = skipOwnEntries ? [] : filteredEntries.map((entry) => normalizeEntry(entry, jsonPath));
11490
- if (!skipOwnEntries) for (const normalizedEntry of normalizedEntries) {
11491
- const resolvedEntryType = explicitEntryTypes?.get(normalizedEntry) ?? entryType ?? (json.component ? "component" : "page");
11492
- entriesMap.set(normalizedEntry, {
11493
- type: resolvedEntryType,
11494
- templatePath,
11495
- jsonPath,
11496
- json,
11497
- path: id
11498
- });
11499
- }
11500
- 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);
11501
11499
  }
11502
- async function emitEntryOutput(options) {
11503
- 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;
11504
- let json = initialJson;
11505
- async function emitNativeLayoutAssets(layoutBasePath) {
11506
- if (typeof pluginCtx.emitFile !== "function") return;
11507
- const resolvedOptions = resolveNativeLayoutOutputOptions({
11508
- configService,
11509
- layoutBasePath,
11510
- outputExtensions: configService.outputExtensions
11511
- });
11512
- if (!resolvedOptions) return;
11513
- const assets = await collectNativeLayoutAssets(layoutBasePath);
11514
- const emittedLayoutAssets = pluginCtx.__weappViteNativeLayoutAssets ?? (pluginCtx.__weappViteNativeLayoutAssets = /* @__PURE__ */ new Set());
11515
- if (assets.json) registerJsonAsset({
11516
- jsonPath: assets.json,
11517
- json: JSON.parse(await fs$1.readFile(assets.json, "utf8")),
11518
- type: "component"
11519
- });
11520
- const assetEntries = await resolveNativeLayoutStaticAssetEntries({
11521
- assets,
11522
- resolvedOptions,
11523
- readFile: fs$1.readFile
11524
- });
11525
- for (const asset of assetEntries) {
11526
- if (emittedLayoutAssets.has(asset.fileName)) continue;
11527
- emittedLayoutAssets.add(asset.fileName);
11528
- pluginCtx.emitFile({
11529
- type: "asset",
11530
- fileName: asset.fileName,
11531
- source: asset.source
11532
- });
11533
- }
11534
- emitNativeLayoutScriptChunkIfNeeded$1({
11535
- pluginCtx,
11536
- scriptId: assets.script,
11537
- fileName: `${resolvedOptions.relativeBase}.${resolvedOptions.scriptExtension}`
11538
- });
11539
- }
11540
- const shouldSkipEntries = Boolean(options.skipEntries);
11541
- const resolvedIds = shouldSkipEntries ? [] : normalizedEntries.length ? await resolveEntriesWithCache(pluginCtx, normalizedEntries, entryResolveRoot) : [];
11542
- debug?.(`resolvedIds ${relativeCwdId} 耗时 ${getTime()}`);
11543
- const pendingResolvedIds = [];
11544
- const combinedResolved = shouldSkipEntries ? [] : pluginResolvedRecords ? isPluginBuild ? pluginResolvedRecords : [...resolvedIds, ...pluginResolvedRecords] : resolvedIds;
11545
- const pluginEntrySet = shouldSkipEntries || !pluginResolvedRecords ? void 0 : new Set(pluginResolvedRecords.map((record) => record.entry));
11546
- for (const { entry, resolvedId } of combinedResolved) {
11547
- if (!resolvedId) {
11548
- if (pluginEntrySet?.has(entry)) logger_default.warn(`没有找到插件入口 \`${entry}\` 对应的脚本文件,请检查路径是否正确!`);
11549
- else logger_default.warn(`没有找到 \`${entry}\` 的入口文件,请检查路径是否正确!`);
11550
- continue;
11551
- }
11552
- const normalizedResolvedId = normalizeFsResolvedId(resolvedId.id);
11553
- if (normalizedResolvedId && !isSkippableResolvedId(normalizedResolvedId) && path.isAbsolute(normalizedResolvedId)) addNormalizedWatchFile(pluginCtx, normalizedResolvedId);
11554
- if (normalizedResolvedId && !isSkippableResolvedId(normalizedResolvedId)) resolvedEntryMap.set(normalizedResolvedId, resolvedId);
11555
- const isDirtyEntry = dirtyEntrySet.has(normalizedResolvedId);
11556
- if (!isDirtyEntry && loadedEntrySet.has(normalizedResolvedId)) continue;
11557
- pendingResolvedIds.push(resolvedId);
11558
- if (isDirtyEntry) dirtyEntrySet.delete(normalizedResolvedId);
11559
- }
11560
- if (pendingResolvedIds.length) await Promise.all(emitEntriesChunks.call(pluginCtx, pendingResolvedIds));
11561
- debug?.(`emitEntriesChunks ${relativeCwdId} 耗时 ${getTime()}`);
11562
- let code = await readFile$1(id, { checkMtime: configService.isDev });
11563
- if (type === "page" && templatePath && !NON_VUE_PAGE_RE.test(id)) {
11564
- replaceLayoutDependencies(id, []);
11565
- const layoutPlan = await resolvePageLayoutPlan(code, id, configService);
11566
- if (layoutPlan) {
11567
- const layoutDependencies = /* @__PURE__ */ new Set();
11568
- for (const file of await expandResolvedPageLayoutFiles(layoutPlan.layouts)) {
11569
- addNormalizedWatchFile(pluginCtx, file);
11570
- layoutDependencies.add(normalizeFsResolvedId(file));
11571
- }
11572
- replaceLayoutDependencies(id, layoutDependencies);
11573
- const nativeTemplate = await readFile$1(templatePath, { checkMtime: configService.isDev });
11574
- const transformed = applyPageLayoutPlanToNativePage({
11575
- script: code,
11576
- template: nativeTemplate,
11577
- config: JSON.stringify(json)
11578
- }, id, layoutPlan);
11579
- code = transformed.script ?? code;
11580
- if (transformed.config) json = JSON.parse(transformed.config);
11581
- if (transformed.template && wxmlService) {
11582
- const token = wxmlService.analyze(transformed.template);
11583
- wxmlService.tokenMap.set(templatePath, token);
11584
- wxmlService.setWxmlComponentsMap(templatePath, token.components);
11585
- }
11586
- for (const layout of layoutPlan.layouts) if (layout.kind === "native") await emitNativeLayoutAssets(layout.file);
11587
- }
11588
- code = injectNativePageLayoutRuntime(code, id, layoutPlan) ?? code;
11589
- }
11590
- if (!isPluginBuild || type !== "app") registerJsonAsset({
11591
- jsonPath,
11592
- json,
11593
- type
11594
- });
11595
- if (pluginJsonPathForRegistration && pluginJsonForRegistration) registerJsonAsset({
11596
- jsonPath: pluginJsonPathForRegistration,
11597
- json: pluginJsonForRegistration,
11598
- type: "plugin"
11500
+ function normalizeScriptModuleExtension(scriptModuleExtension) {
11501
+ if (!scriptModuleExtension) return;
11502
+ return scriptModuleExtension.startsWith(".") ? scriptModuleExtension.slice(1) : scriptModuleExtension;
11503
+ }
11504
+ function getDefaultScriptModuleTagByExtension(scriptModuleExtension) {
11505
+ if (!scriptModuleExtension) return "wxs";
11506
+ return DEFAULT_SCRIPT_MODULE_TAG_BY_EXTENSION[normalizeScriptModuleExtension(scriptModuleExtension)] ?? "wxs";
11507
+ }
11508
+ function resolveScriptModuleTagName(options) {
11509
+ if (options?.scriptModuleTag) return options.scriptModuleTag;
11510
+ return resolveScriptModuleTagByPlatform(options?.platform, options?.scriptModuleExtension) ?? getDefaultScriptModuleTagByExtension(options?.scriptModuleExtension);
11511
+ }
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=");
11599
11535
  });
11600
- const styleImports = await collectStyleImports(pluginCtx, id, existsCache, pathExistsTtlMs);
11601
- debug?.(`loadEntry ${relativeCwdId} 耗时 ${getTime()}`);
11602
- if (styleImports.length === 0) return { code };
11603
- const ms = new MagicString(code);
11604
- for (const styleImport of styleImports) ms.prepend(`import '${styleImport}';\n`);
11605
- return { code: ms.toString() };
11606
11536
  }
11607
11537
  //#endregion
11608
- //#region src/plugins/hooks/useLoadEntry/loadEntry/resolve.ts
11609
- function createEntryResolver(configService) {
11610
- const entryResolutionCache = /* @__PURE__ */ new Map();
11611
- async function resolveEntryWithCache(pluginCtx, absPath) {
11612
- const normalized = path.normalize(absPath);
11613
- if (entryResolutionCache.has(normalized)) return entryResolutionCache.get(normalized) ?? null;
11614
- let resolvedSource = normalized;
11615
- if (!path.extname(normalized)) {
11616
- const matched = await resolveEntryPath(normalized, createCachedEntryResolveOptions(configService ?? {}, { kind: "default" }));
11617
- if (matched) resolvedSource = matched;
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 });
11555
+ };
11556
+ const tryCollectArgument = (path) => {
11557
+ const node = path.node;
11558
+ if (t.isStringLiteral(node)) {
11559
+ maybePushImportee(node.value);
11560
+ return;
11618
11561
  }
11619
- const resolvedId = await pluginCtx.resolve(resolvedSource) ?? null;
11620
- entryResolutionCache.set(normalized, resolvedId);
11621
- return resolvedId;
11622
- }
11623
- async function resolveEntriesWithCache(pluginCtx, entries, absoluteRoot) {
11624
- return Promise.all(entries.filter((entry) => !entry.includes(":")).map(async (entry) => {
11625
- return {
11626
- entry,
11627
- resolvedId: await resolveEntryWithCache(pluginCtx, path.resolve(absoluteRoot, entry))
11628
- };
11629
- }));
11630
- }
11631
- return {
11632
- resolveEntryWithCache,
11633
- resolveEntriesWithCache,
11634
- invalidate() {
11635
- entryResolutionCache.clear();
11562
+ if (t.isTemplateLiteral(node) && node.expressions.length === 0) {
11563
+ maybePushImportee(node.quasis.map((q) => q.value.cooked ?? q.value.raw ?? "").join(""));
11564
+ return;
11636
11565
  }
11566
+ try {
11567
+ const evaluated = path.evaluate();
11568
+ if (evaluated.confident) maybePushImportee(evaluated.value);
11569
+ } catch {}
11637
11570
  };
11638
- }
11639
- //#endregion
11640
- //#region src/plugins/utils/vueSfc.ts
11641
- function createSfcResolveSrcOptions(pluginCtx, configService) {
11642
11571
  return {
11643
- resolveId: async (source, importer) => {
11644
- if (typeof pluginCtx.resolve !== "function") return;
11645
- return (await pluginCtx.resolve(source, importer))?.id;
11646
- },
11647
- checkMtime: getSfcCheckMtime(configService)
11648
- };
11649
- }
11650
- function createReadAndParseSfcOptions(pluginCtx, configService, options) {
11651
- const resolveCheckMtime = getSfcCheckMtime(configService);
11652
- return {
11653
- source: options?.source,
11654
- checkMtime: options?.checkMtime ?? resolveCheckMtime,
11655
- resolveSrc: createSfcResolveSrcOptions(pluginCtx, configService)
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
11656
11615
  };
11657
11616
  }
11658
11617
  //#endregion
11659
- //#region src/plugins/vue/transform/usingComponentResolver.ts
11660
- const JS_LIKE_FILE_RE = /\.(?:[cm]?ts|[cm]?js)$/;
11661
- async function resolveUsingComponentReference(ctx, configService, reExportResolutionCache, importSource, importerFilename, info) {
11662
- const resolved = await ctx.resolve(importSource, importerFilename);
11663
- let clean = resolved?.id ? normalizeFsResolvedId(resolved.id) : void 0;
11664
- if ((!clean || !path.isAbsolute(clean)) && info?.fallbackRelativeImporterDir && importSource.startsWith(".")) clean = path.resolve(path.dirname(importerFilename), importSource);
11665
- if (!clean) return {
11666
- resolvedId: void 0,
11667
- from: void 0
11668
- };
11669
- if (isSkippableResolvedId(clean)) return {
11670
- resolvedId: void 0,
11671
- from: void 0
11672
- };
11673
- if (path.isAbsolute(clean)) {
11674
- const resolvedEntry = await resolveEntryPath(clean, createCachedEntryResolveOptions(configService ?? {}, { kind: info?.kind ?? "default" }));
11675
- if (resolvedEntry) clean = resolvedEntry;
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}`;
11627
+ }
11628
+ function getCachedResult(data, cacheKey) {
11629
+ return handleCache.get(data)?.get(cacheKey);
11630
+ }
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);
11676
11636
  }
11677
- if (info?.kind === "named" && info.importedName && JS_LIKE_FILE_RE.test(clean)) {
11678
- const exportName = info.importedName;
11679
- const mapped = await resolveReExportedName(clean, exportName, {
11680
- astEngine: resolveAstEngine(configService.weappViteConfig),
11681
- cache: reExportResolutionCache,
11682
- maxDepth: 4,
11683
- readFile: (file) => readFile$1(file, { checkMtime: getReadFileCheckMtime(configService) }),
11684
- resolveId: async (source, importer) => {
11685
- const hop = await ctx.resolve(source, importer);
11686
- const hopId = hop?.id ? normalizeFsResolvedId(hop.id) : void 0;
11687
- if (isSkippableResolvedId(hopId)) return;
11688
- return hopId;
11689
- }
11690
- });
11691
- if (mapped) clean = mapped;
11637
+ cacheForToken.set(cacheKey, result);
11638
+ return result;
11639
+ }
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;
11692
11647
  }
11693
- return {
11694
- resolvedId: clean,
11695
- from: usingComponentFromResolvedFile(clean, configService)
11696
- };
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;
11697
11655
  }
11698
- async function resolveUsingComponentPath(ctx, configService, reExportResolutionCache, importSource, importerFilename, info) {
11699
- return (await resolveUsingComponentReference(ctx, configService, reExportResolutionCache, importSource, importerFilename, info)).from;
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);
11708
+ }
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
+ });
11700
11722
  }
11701
- function createUsingComponentPathResolver(ctx, configService, reExportResolutionCache) {
11702
- return async (importSource, importerFilename, info) => {
11703
- return resolveUsingComponentPath(ctx, configService, reExportResolutionCache, importSource, importerFilename, info);
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
+ })
11704
11739
  };
11705
11740
  }
11706
- //#endregion
11707
- //#region src/plugins/hooks/useLoadEntry/loadEntry/template.ts
11708
- function collectVueTemplateComponentNames(template, filename) {
11709
- return collectVueTemplateTags(template, {
11710
- filename,
11711
- warnLabel: "自动 usingComponents",
11712
- shouldCollect: (tag) => VUE_COMPONENT_TAG_RE.test(tag)
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);
11756
+ }
11757
+ return scanService.isMainPackageFileName(fileName);
11713
11758
  });
11714
11759
  }
11715
- function collectVueTemplateAutoImportTags(template, filename) {
11716
- return collectVueTemplateTags(template, {
11717
- filename,
11718
- warnLabel: "自动导入标签",
11719
- shouldCollect: isAutoImportCandidateTag
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
11720
11775
  });
11776
+ return true;
11721
11777
  }
11722
- function collectScriptSetupImports(scriptSetup, templateComponentNames, options) {
11723
- return collectScriptSetupImportsFromCode(scriptSetup, templateComponentNames, options);
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,
11791
+ id,
11792
+ fileName,
11793
+ token,
11794
+ deps: wxmlService.depsMap.get(id),
11795
+ emittedCodeCache,
11796
+ scriptModuleExtension,
11797
+ scriptModuleTag,
11798
+ templateExtension
11799
+ });
11800
+ }
11801
+ return emittedFiles;
11724
11802
  }
11725
- async function scanTemplateEntry(pluginCtx, id, scanTemplateEntryFn, existsCache, ttlMs) {
11726
- return ensureTemplateScanned(pluginCtx, id, scanTemplateEntryFn, existsCache, ttlMs);
11803
+ function emitJsonAsset(runtime, fileName, source, extension = "json") {
11804
+ runtime.emitFile({
11805
+ type: "asset",
11806
+ fileName: changeFileExtension(fileName, extension),
11807
+ source
11808
+ });
11727
11809
  }
11728
- async function applyScriptSetupUsingComponents(options) {
11729
- const { pluginCtx, vueEntryPath, templatePath, json, configService, wxmlService, reExportResolutionCache } = options;
11730
- try {
11731
- const { descriptor, errors } = await readAndParseSfc(vueEntryPath, { ...createReadAndParseSfcOptions(pluginCtx, configService) });
11732
- if (!errors?.length && descriptor?.template && !templatePath) {
11733
- const tags = collectVueTemplateAutoImportTags(descriptor.template.content, vueEntryPath);
11734
- if (tags.size) {
11735
- const components = Object.fromEntries(Array.from(tags, (tag) => [tag, [{
11736
- start: 0,
11737
- end: 0
11738
- }]]));
11739
- wxmlService?.setWxmlComponentsMap(vueEntryPath, components);
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,
11821
+ templatePath,
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({
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({
11854
+ wxmlService,
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;
11740
11882
  }
11883
+ emittedLayoutAssets.add(asset.fileName);
11884
+ pluginCtx.emitFile({
11885
+ type: "asset",
11886
+ fileName: asset.fileName,
11887
+ source: asset.source
11888
+ });
11741
11889
  }
11742
- if (!errors?.length && descriptor?.scriptSetup && descriptor?.template) {
11743
- const templateComponentNames = collectVueTemplateComponentNames(descriptor.template.content, vueEntryPath);
11744
- if (templateComponentNames.size) {
11745
- const astEngine = resolveAstEngine(configService.weappViteConfig);
11746
- const imports = collectScriptSetupImports(descriptor.scriptSetup.content, templateComponentNames, { astEngine });
11747
- if (imports.length) {
11748
- const usingComponents = json && typeof json.usingComponents === "object" && json.usingComponents && !Array.isArray(json.usingComponents) ? json.usingComponents : {};
11749
- for (const { localName, importSource, importedName, kind } of imports) {
11750
- let { from } = await resolveUsingComponentReference(pluginCtx, configService, reExportResolutionCache, importSource, vueEntryPath, {
11751
- kind,
11752
- importedName,
11753
- fallbackRelativeImporterDir: true
11754
- });
11755
- if (!from && importSource.startsWith("/")) from = removeExtensionDeep(importSource);
11756
- if (!from) continue;
11757
- if (Reflect.has(usingComponents, localName) && usingComponents[localName] !== from) logger_default.warn(`[自动 usingComponents] 冲突:${vueEntryPath} 中 usingComponents['${localName}']='${usingComponents[localName]}' 将被 <script setup> 导入覆盖为 '${from}'`);
11758
- usingComponents[localName] = from;
11759
- }
11760
- json.usingComponents = usingComponents;
11761
- }
11890
+ emitNativeLayoutScriptChunkIfNeeded$1({
11891
+ pluginCtx,
11892
+ scriptId: assets.script,
11893
+ fileName: `${resolvedOptions.relativeBase}.${resolvedOptions.scriptExtension}`
11894
+ });
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);
11762
11942
  }
11943
+ for (const layout of layoutPlan.layouts) if (layout.kind === "native") await emitNativeLayoutAssets(layout.file);
11763
11944
  }
11764
- } catch (error) {
11765
- const message = error instanceof Error ? error.message : String(error);
11766
- logger_default.warn(`[自动 usingComponents] 解析失败:${vueEntryPath}:${message}`);
11945
+ code = injectNativePageLayoutRuntime(code, id, layoutPlan) ?? code;
11767
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() };
11768
11963
  }
11769
11964
  //#endregion
11770
- //#region src/plugins/hooks/useLoadEntry/loadEntry/index.ts
11771
- function createStopwatch() {
11772
- const start = performance$1.now();
11773
- return () => `${(performance$1.now() - start).toFixed(2)}ms`;
11774
- }
11775
- function createEntryLoader(options) {
11776
- const { ctx, entriesMap, loadedEntrySet, dirtyEntrySet, resolvedEntryMap, replaceLayoutDependencies, normalizeEntry, registerJsonAsset, scanTemplateEntry: scanTemplateEntryFn, emitEntriesChunks, applyAutoImports, extendedLibManager, debug } = options;
11777
- const isPluginBuild = (options.buildTarget ?? "app") === "plugin";
11778
- const { jsonService, configService, wxmlService } = ctx;
11779
- const existsCache = /* @__PURE__ */ new Map();
11780
- const pathExistsTtlMs = getPathExistsTtlMs(configService);
11781
- const reExportResolutionCache = /* @__PURE__ */ new Map();
11782
- const entryResolver = createEntryResolver(configService);
11783
- const appEntriesCache = {};
11784
- const appEntryOutputCache = {};
11785
- const emittedScriptlessVueLayoutJs = /* @__PURE__ */ new Set();
11786
- const scriptlessVueLayoutDecisionCache = /* @__PURE__ */ new Map();
11787
- let resolveCacheVersion = 0;
11788
- const shouldEmitScriptlessVueLayoutJs$1 = async (layoutFile) => {
11789
- const cached = scriptlessVueLayoutDecisionCache.get(layoutFile);
11790
- if (cached) return await cached;
11791
- const task = (async () => {
11792
- return shouldEmitScriptlessVueLayoutJs(await fs.readFile(layoutFile, "utf-8"), layoutFile);
11793
- })();
11794
- scriptlessVueLayoutDecisionCache.set(layoutFile, task);
11795
- try {
11796
- return await task;
11797
- } catch (error) {
11798
- scriptlessVueLayoutDecisionCache.delete(layoutFile);
11799
- throw error;
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;
11979
+ }
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();
11800
11993
  }
11801
11994
  };
11802
- return Object.assign(async function loadEntry(id, type) {
11803
- existsCache.clear();
11804
- const stopwatch = debug ? createStopwatch() : void 0;
11805
- const getTime = () => stopwatch ? stopwatch() : "0.00ms";
11806
- const relativeCwdId = configService.relativeCwd(id);
11807
- const normalizedId = normalizeFsResolvedId(id);
11808
- const libConfig = configService.weappLibConfig;
11995
+ }
11996
+ //#endregion
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)
12013
+ };
12014
+ }
12015
+ //#endregion
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
12025
+ };
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;
12046
+ }
12047
+ });
12048
+ if (mapped) clean = mapped;
12049
+ }
12050
+ return {
12051
+ resolvedId: clean,
12052
+ from: usingComponentFromResolvedFile(clean, configService)
12053
+ };
12054
+ }
12055
+ async function resolveUsingComponentPath(ctx, configService, reExportResolutionCache, importSource, importerFilename, info) {
12056
+ return (await resolveUsingComponentReference(ctx, configService, reExportResolutionCache, importSource, importerFilename, info)).from;
12057
+ }
12058
+ function createUsingComponentPathResolver(ctx, configService, reExportResolutionCache) {
12059
+ return async (importSource, importerFilename, info) => {
12060
+ return resolveUsingComponentPath(ctx, configService, reExportResolutionCache, importSource, importerFilename, info);
12061
+ };
12062
+ }
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
+ });
12071
+ }
12072
+ function collectVueTemplateAutoImportTags(template, filename) {
12073
+ return collectVueTemplateTags(template, {
12074
+ filename,
12075
+ warnLabel: "自动导入标签",
12076
+ shouldCollect: isAutoImportCandidateTag
12077
+ });
12078
+ }
12079
+ function collectScriptSetupImports(scriptSetup, templateComponentNames, options) {
12080
+ return collectScriptSetupImportsFromCode(scriptSetup, templateComponentNames, options);
12081
+ }
12082
+ async function scanTemplateEntry(pluginCtx, id, scanTemplateEntryFn, existsCache, ttlMs) {
12083
+ return ensureTemplateScanned(pluginCtx, id, scanTemplateEntryFn, existsCache, ttlMs);
12084
+ }
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
+ }
12125
+ }
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`;
12131
+ }
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);
12152
+ try {
12153
+ return await task;
12154
+ } catch (error) {
12155
+ scriptlessVueLayoutDecisionCache.delete(layoutFile);
12156
+ throw error;
12157
+ }
12158
+ };
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;
11809
12166
  const libEntry = libConfig?.enabled && normalizedId ? ctx.runtimeState.lib.entries.get(normalizedId) : void 0;
11810
12167
  addNormalizedWatchFile(this, id);
11811
12168
  const baseName = removeExtensionDeep(id);
@@ -11971,6 +12328,7 @@ function createEntryLoader(options) {
11971
12328
  debug,
11972
12329
  relativeCwdId,
11973
12330
  getTime,
12331
+ emittedWxmlCodeCache: ctx.runtimeState?.wxml?.emittedCode,
11974
12332
  skipEntries: shouldSkipAppEntries
11975
12333
  });
11976
12334
  if (type === "app" && !shouldSkipAppEntries && appResult) appEntryOutputCache.current = {
@@ -11984,498 +12342,170 @@ function createEntryLoader(options) {
11984
12342
  }, { invalidateResolveCache() {
11985
12343
  entryResolver.invalidate();
11986
12344
  scriptlessVueLayoutDecisionCache.clear();
11987
- resolveCacheVersion += 1;
11988
- appEntryOutputCache.current = void 0;
11989
- } });
11990
- }
11991
- //#endregion
11992
- //#region src/plugins/hooks/useLoadEntry/normalizer.ts
11993
- const PLUGIN_PROTOCOL_RE = /plugin:\/\//;
11994
- const WINDOWS_PATH_SEPARATOR_RE = /\\/g;
11995
- function resolveImportee(importee, jsonPath, configService) {
11996
- let updated = importee;
11997
- if (jsonPath && Array.isArray(configService.aliasEntries)) {
11998
- const matchedEntry = configService.aliasEntries.find((entry) => matches(entry.find, importee));
11999
- if (matchedEntry) updated = importee.replace(matchedEntry.find, matchedEntry.replacement);
12000
- }
12001
- const baseDir = jsonPath ? path.dirname(jsonPath) : configService.absoluteSrcRoot;
12002
- return path.resolve(baseDir, updated);
12003
- }
12004
- function createEntryNormalizer(configService) {
12005
- return function normalizeEntry(entry, jsonPath) {
12006
- if (PLUGIN_PROTOCOL_RE.test(entry)) return entry;
12007
- const normalizedEntry = normalizeNpmImportLookupPath(entry);
12008
- if (normalizedEntry && isObject(configService.packageJson.dependencies) && hasNpmDependencyPrefix(configService.packageJson.dependencies, normalizedEntry)) return `npm:${normalizedEntry}`;
12009
- if (entry.replace(WINDOWS_PATH_SEPARATOR_RE, "/").startsWith("/")) return normalizedEntry;
12010
- const normalized = resolveImportee(normalizedEntry, jsonPath, configService);
12011
- return configService.relativeAbsoluteSrcRoot(normalized);
12012
- };
12013
- }
12014
- //#endregion
12015
- //#region src/plugins/hooks/useLoadEntry/template.ts
12016
- function createTemplateScanner(wxmlService, debug) {
12017
- return async function scanTemplateEntry(templateEntry) {
12018
- const start = performance$1.now();
12019
- const wxmlToken = await wxmlService.scan(templateEntry);
12020
- if (wxmlToken) {
12021
- const { components } = wxmlToken;
12022
- wxmlService.setWxmlComponentsMap(templateEntry, components);
12023
- }
12024
- debug?.(`scanTemplateEntry ${templateEntry} 耗时 ${(performance$1.now() - start).toFixed(2)}ms`);
12025
- };
12026
- }
12027
- //#endregion
12028
- //#region src/plugins/hooks/useLoadEntry/index.ts
12029
- function useLoadEntry(ctx, options) {
12030
- const debug = createDebugger("weapp-vite:load-entry");
12031
- const buildTarget = options?.buildTarget ?? "app";
12032
- const entriesMap = /* @__PURE__ */ new Map();
12033
- const loadedEntrySet = /* @__PURE__ */ new Set();
12034
- const dirtyEntrySet = /* @__PURE__ */ new Set();
12035
- const dirtyEntryReasons = /* @__PURE__ */ new Map();
12036
- const resolvedEntryMap = /* @__PURE__ */ new Map();
12037
- const layoutEntryDependents = /* @__PURE__ */ new Map();
12038
- const entryLayoutDependencies = /* @__PURE__ */ new Map();
12039
- const jsonEmitManager = createJsonEmitManager(ctx.configService);
12040
- const registerJsonAsset = jsonEmitManager.register.bind(jsonEmitManager);
12041
- const normalizeEntry = createEntryNormalizer(ctx.configService);
12042
- const scanTemplateEntry = createTemplateScanner(ctx.wxmlService, debug);
12043
- const emitEntriesChunks = createChunkEmitter(ctx.configService, loadedEntrySet, debug);
12044
- const loadEntry = createEntryLoader({
12045
- ctx,
12046
- entriesMap,
12047
- loadedEntrySet,
12048
- dirtyEntrySet,
12049
- resolvedEntryMap,
12050
- replaceLayoutDependencies(entryId, dependencies) {
12051
- const previousDependencies = entryLayoutDependencies.get(entryId);
12052
- if (previousDependencies) for (const dependency of previousDependencies) {
12053
- const dependents = layoutEntryDependents.get(dependency);
12054
- if (!dependents) continue;
12055
- dependents.delete(entryId);
12056
- if (dependents.size === 0) layoutEntryDependents.delete(dependency);
12057
- }
12058
- const normalizedDependencies = new Set(dependencies);
12059
- if (normalizedDependencies.size === 0) {
12060
- entryLayoutDependencies.delete(entryId);
12061
- return;
12062
- }
12063
- entryLayoutDependencies.set(entryId, normalizedDependencies);
12064
- for (const dependency of normalizedDependencies) {
12065
- let dependents = layoutEntryDependents.get(dependency);
12066
- if (!dependents) {
12067
- dependents = /* @__PURE__ */ new Set();
12068
- layoutEntryDependents.set(dependency, dependents);
12069
- }
12070
- dependents.add(entryId);
12071
- }
12072
- },
12073
- normalizeEntry,
12074
- registerJsonAsset,
12075
- scanTemplateEntry,
12076
- emitEntriesChunks,
12077
- applyAutoImports: createAutoImportAugmenter(ctx.autoImportService, ctx.wxmlService),
12078
- extendedLibManager: createExtendedLibManager(),
12079
- buildTarget,
12080
- debug
12081
- });
12082
- const hmrSharedChunksMode = options?.hmr?.sharedChunks ?? "auto";
12083
- const hmrSharedChunkImporters = options?.hmr?.sharedChunkImporters;
12084
- return {
12085
- loadEntry,
12086
- entriesMap,
12087
- loadedEntrySet,
12088
- dirtyEntrySet,
12089
- resolvedEntryMap,
12090
- layoutEntryDependents,
12091
- jsonEmitFilesMap: jsonEmitManager.map,
12092
- normalizeEntry,
12093
- markEntryDirty(entryId, reason = "direct") {
12094
- dirtyEntrySet.add(entryId);
12095
- dirtyEntryReasons.set(entryId, reason);
12096
- loadedEntrySet.delete(entryId);
12097
- },
12098
- async emitDirtyEntries() {
12099
- if (!dirtyEntrySet.size) {
12100
- options?.hmr?.setDidEmitAllEntries?.(false);
12101
- options?.hmr?.setLastEmittedEntries?.(/* @__PURE__ */ new Set());
12102
- return;
12103
- }
12104
- const dirtyCount = dirtyEntrySet.size;
12105
- const pendingEntryIds = resolvePendingEntryIds({
12106
- isDev: Boolean(ctx.configService?.isDev),
12107
- mode: hmrSharedChunksMode,
12108
- resolvedEntryMap,
12109
- dirtyEntrySet,
12110
- dirtyEntryReasons,
12111
- sharedChunkImporters: hmrSharedChunkImporters,
12112
- subPackageRoots: new Set(ctx.scanService?.subPackageMap?.keys?.() ?? []),
12113
- relativeAbsoluteSrcRoot: ctx.configService.relativeAbsoluteSrcRoot.bind(ctx.configService)
12114
- });
12115
- const pending = [];
12116
- const shouldEmitAllEntries = pendingEntryIds.size > 0 && pendingEntryIds.size === resolvedEntryMap.size;
12117
- options?.hmr?.setDidEmitAllEntries?.(shouldEmitAllEntries);
12118
- options?.hmr?.setLastEmittedEntries?.(new Set(pendingEntryIds));
12119
- for (const entryId of pendingEntryIds) {
12120
- const resolvedId = resolvedEntryMap.get(entryId);
12121
- if (!resolvedId) continue;
12122
- pending.push(resolvedId);
12123
- dirtyEntrySet.delete(entryId);
12124
- dirtyEntryReasons.delete(entryId);
12125
- }
12126
- if (debug) debug(`hmr emit dirty=${dirtyCount} resolved=${resolvedEntryMap.size} emitAll=${shouldEmitAllEntries} pending=${pending.length}`);
12127
- if (pending.length) await Promise.all(emitEntriesChunks.call(this, pending));
12128
- }
12129
- };
12130
- }
12131
- function resolvePendingEntryIds(options) {
12132
- const pending = new Set(options.dirtyEntrySet);
12133
- if (options.mode === "full") return new Set(options.resolvedEntryMap.keys());
12134
- if (!options.isDev || options.mode === "off") return pending;
12135
- if (!options.sharedChunkImporters?.size) return pending;
12136
- for (const importers of options.sharedChunkImporters.values()) {
12137
- if (importers.size <= 1) continue;
12138
- let hasDependencyDrivenImporter = false;
12139
- let hasDirectDirtyImporter = false;
12140
- for (const importer of importers) {
12141
- if (options.dirtyEntrySet.has(importer) && options.dirtyEntryReasons.get(importer) === "dependency") {
12142
- hasDependencyDrivenImporter = true;
12143
- break;
12144
- }
12145
- if (options.dirtyEntrySet.has(importer) && options.dirtyEntryReasons.get(importer) === "direct") hasDirectDirtyImporter = true;
12146
- }
12147
- if (!hasDependencyDrivenImporter && !hasDirectDirtyImporter) continue;
12148
- for (const importer of importers) pending.add(importer);
12149
- }
12150
- return pending;
12151
- }
12152
- //#endregion
12153
- //#region src/utils/wxmlScriptModule.ts
12154
- const IMPORT_SJS_TAG_RE = /<import-sjs([\s\S]*?)>/g;
12155
- const IMPORT_SJS_SRC_RE = /\bsrc\s*=\s*/g;
12156
- const IMPORT_SJS_MODULE_RE = /\bmodule\s*=\s*/g;
12157
- const DEFAULT_SCRIPT_MODULE_TAG_NAMES = ["wxs", "sjs"];
12158
- const DEFAULT_SCRIPT_MODULE_TAG_BY_EXTENSION = Object.freeze({
12159
- wxs: "wxs",
12160
- sjs: "sjs"
12161
- });
12162
- const SCRIPT_MODULE_IMPORT_ATTRS = Object.freeze({
12163
- "wxs": ["src"],
12164
- "sjs": ["src"],
12165
- "import-sjs": ["from"]
12166
- });
12167
- function resolveScriptModuleTagByPlatform(platform, scriptModuleExtension) {
12168
- return getPlatformScriptModuleTag(platform, scriptModuleExtension);
12169
- }
12170
- function normalizeScriptModuleExtension(scriptModuleExtension) {
12171
- if (!scriptModuleExtension) return;
12172
- return scriptModuleExtension.startsWith(".") ? scriptModuleExtension.slice(1) : scriptModuleExtension;
12173
- }
12174
- function getDefaultScriptModuleTagByExtension(scriptModuleExtension) {
12175
- if (!scriptModuleExtension) return "wxs";
12176
- return DEFAULT_SCRIPT_MODULE_TAG_BY_EXTENSION[normalizeScriptModuleExtension(scriptModuleExtension)] ?? "wxs";
12177
- }
12178
- function resolveScriptModuleTagName(options) {
12179
- if (options?.scriptModuleTag) return options.scriptModuleTag;
12180
- return resolveScriptModuleTagByPlatform(options?.platform, options?.scriptModuleExtension) ?? getDefaultScriptModuleTagByExtension(options?.scriptModuleExtension);
12181
- }
12182
- function getDerivedScriptModuleTagNames() {
12183
- return MINI_PROGRAM_PLATFORM_ADAPTERS.flatMap((adapter) => Object.values(adapter.scriptModuleTagByExtension ?? {})).filter((value) => typeof value === "string" && value.length > 0);
12184
- }
12185
- function getScriptModuleTagNames() {
12186
- return [...new Set([...DEFAULT_SCRIPT_MODULE_TAG_NAMES, ...getDerivedScriptModuleTagNames()])];
12187
- }
12188
- function isScriptModuleTagName(tagName) {
12189
- return typeof tagName === "string" && getScriptModuleTagNames().includes(tagName);
12190
- }
12191
- function getScriptModuleImportAttrs(tagName) {
12192
- if (!tagName) return;
12193
- return SCRIPT_MODULE_IMPORT_ATTRS[tagName];
12194
- }
12195
- function isScriptModuleImportAttr(tagName, attrName) {
12196
- if (!tagName) return false;
12197
- return getScriptModuleImportAttrs(tagName)?.includes(attrName) === true;
12198
- }
12199
- function shouldNormalizeScriptModuleAttributes(tagName) {
12200
- return tagName === "import-sjs";
12201
- }
12202
- function normalizeImportSjsAttributes(source) {
12203
- return source.replace(IMPORT_SJS_TAG_RE, (tag) => {
12204
- return tag.replace(IMPORT_SJS_SRC_RE, "from=").replace(IMPORT_SJS_MODULE_RE, "name=");
12205
- });
12206
- }
12207
- //#endregion
12208
- //#region src/wxs/utils.ts
12209
- function normalizeWxsFilename(value, extension = "wxs") {
12210
- const normalized = extension.startsWith(".") ? extension.slice(1) : extension;
12211
- let filename = value;
12212
- filename = filename.replace(/\.[jt]s$/i, "");
12213
- filename = filename.replace(/\.(wxs|sjs)$/i, "");
12214
- return addExtension(filename, `.${normalized}`);
12215
- }
12216
- //#endregion
12217
- //#region src/wxs/index.ts
12218
- function transformWxsCode(code, options) {
12219
- const filename = options?.filename ?? "script.ts";
12220
- const extension = options?.extension ?? "wxs";
12221
- const importees = [];
12222
- const maybePushImportee = (value) => {
12223
- if (typeof value !== "string" || !value) return;
12224
- importees.push({ source: value });
12225
- };
12226
- const tryCollectArgument = (path) => {
12227
- const node = path.node;
12228
- if (t.isStringLiteral(node)) {
12229
- maybePushImportee(node.value);
12230
- return;
12231
- }
12232
- if (t.isTemplateLiteral(node) && node.expressions.length === 0) {
12233
- maybePushImportee(node.quasis.map((q) => q.value.cooked ?? q.value.raw ?? "").join(""));
12234
- return;
12235
- }
12236
- try {
12237
- const evaluated = path.evaluate();
12238
- if (evaluated.confident) maybePushImportee(evaluated.value);
12239
- } catch {}
12240
- };
12241
- return {
12242
- result: babel.transformSync(code, {
12243
- babelrc: false,
12244
- configFile: false,
12245
- presets: [["@babel/preset-env"], ["@babel/preset-typescript"]],
12246
- filename,
12247
- plugins: [{ visitor: {
12248
- Directive: { enter(p) {
12249
- p.remove();
12250
- } },
12251
- CallExpression: { enter(p) {
12252
- const node = p.node;
12253
- if (!t.isIdentifier(node.callee, { name: "require" })) return;
12254
- if (node.arguments.length !== 1) return;
12255
- tryCollectArgument(p.get("arguments.0"));
12256
- const arg = node.arguments[0];
12257
- if (t.isStringLiteral(arg)) arg.value = normalizeWxsFilename(arg.value, extension);
12258
- } },
12259
- ExpressionStatement(p) {
12260
- const expression = p.node.expression;
12261
- 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();
12262
- },
12263
- NewExpression: { enter(p) {
12264
- const node = p.node;
12265
- if (t.isIdentifier(node.callee, { name: "RegExp" })) p.replaceWith(t.callExpression(t.identifier("getRegExp"), node.arguments));
12266
- else if (t.isIdentifier(node.callee, { name: "Date" })) p.replaceWith(t.callExpression(t.identifier("getDate"), node.arguments));
12267
- } },
12268
- RegExpLiteral: { enter(p) {
12269
- const args = [t.stringLiteral(p.node.pattern)];
12270
- if (p.node.flags) args.push(t.stringLiteral(p.node.flags));
12271
- p.replaceWith(t.callExpression(t.identifier("getRegExp"), args));
12272
- } },
12273
- MemberExpression: { enter(p) {
12274
- const node = p.node;
12275
- if (!t.isIdentifier(node.object, { name: "exports" })) return;
12276
- const moduleExports = t.memberExpression(t.identifier("module"), t.identifier("exports"));
12277
- p.replaceWith(t.memberExpression(moduleExports, node.property, node.computed, node.optional));
12278
- } },
12279
- ImportDeclaration: { enter(p) {
12280
- maybePushImportee(p.node.source.value);
12281
- } }
12282
- } }]
12283
- }),
12284
- importees
12285
- };
12286
- }
12287
- //#endregion
12288
- //#region src/wxml/handle.ts
12289
- const handleCache = /* @__PURE__ */ new WeakMap();
12290
- const inlineWxsTransformCache = /* @__PURE__ */ new Map();
12291
- const INLINE_WXS_CACHE_LIMIT = 256;
12292
- function createCacheKey$1(options) {
12293
- const extension = options.scriptModuleExtension ?? "";
12294
- const tag = options.scriptModuleTag ?? "";
12295
- const templateExt = options.templateExtension ?? "";
12296
- return `${options.removeComment ? 1 : 0}|${options.transformEvent ? 1 : 0}|${extension}|${tag}|${templateExt}`;
12297
- }
12298
- function getCachedResult(data, cacheKey) {
12299
- return handleCache.get(data)?.get(cacheKey);
12300
- }
12301
- function setCachedResult(data, cacheKey, result) {
12302
- let cacheForToken = handleCache.get(data);
12303
- if (!cacheForToken) {
12304
- cacheForToken = /* @__PURE__ */ new Map();
12305
- handleCache.set(data, cacheForToken);
12306
- }
12307
- cacheForToken.set(cacheKey, result);
12308
- return result;
12309
- }
12310
- function getCachedInlineWxsTransform(code, extension) {
12311
- const key = `${extension}::${code}`;
12312
- const cached = inlineWxsTransformCache.get(key);
12313
- if (cached) {
12314
- inlineWxsTransformCache.delete(key);
12315
- inlineWxsTransformCache.set(key, cached);
12316
- return cached;
12317
- }
12318
- const transformed = transformWxsCode(code, { extension });
12319
- inlineWxsTransformCache.set(key, transformed);
12320
- if (inlineWxsTransformCache.size > INLINE_WXS_CACHE_LIMIT) {
12321
- const firstKey = inlineWxsTransformCache.keys().next().value;
12322
- if (firstKey) inlineWxsTransformCache.delete(firstKey);
12323
- }
12324
- return transformed;
12325
- }
12326
- function handleWxml(data, options) {
12327
- const opts = defu(options, {
12328
- removeComment: true,
12329
- transformEvent: true,
12330
- scriptModuleExtension: void 0,
12331
- scriptModuleTag: void 0,
12332
- templateExtension: void 0
12333
- });
12334
- const cacheKey = createCacheKey$1(opts);
12335
- const cached = getCachedResult(data, cacheKey);
12336
- if (cached) return cached;
12337
- const { code, removalRanges = [], commentTokens = [], eventTokens = [], directiveTokens = [], tagNameTokens = [], inlineWxsTokens = [], removeWxsLangAttrTokens = [], scriptModuleTagTokens = [], wxsImportNormalizeTokens = [], templateImportNormalizeTokens = [], components, deps } = data;
12338
- const normalizedScriptExtension = opts.scriptModuleExtension?.startsWith(".") ? opts.scriptModuleExtension.slice(1) : opts.scriptModuleExtension;
12339
- const normalizedTemplateExtension = opts.templateExtension?.startsWith(".") ? opts.templateExtension.slice(1) : opts.templateExtension;
12340
- const resolvedScriptTag = resolveScriptModuleTagName({
12341
- scriptModuleExtension: normalizedScriptExtension,
12342
- scriptModuleTag: opts.scriptModuleTag
12343
- });
12344
- const shouldNormalizeImports = wxsImportNormalizeTokens.length > 0;
12345
- const shouldNormalizeTemplateImports = templateImportNormalizeTokens.length > 0 && normalizedTemplateExtension;
12346
- const shouldRemoveLang = removeWxsLangAttrTokens.length > 0;
12347
- const shouldTransformInlineWxs = inlineWxsTokens.length > 0;
12348
- const shouldTransformEvents = opts.transformEvent && eventTokens.length > 0;
12349
- const shouldTransformDirectives = directiveTokens.length > 0;
12350
- const shouldTransformTagNames = tagNameTokens.length > 0;
12351
- const shouldTransformScriptModuleTags = resolvedScriptTag !== "wxs" && scriptModuleTagTokens.length > 0;
12352
- const shouldRemoveConditionals = removalRanges.length > 0;
12353
- const shouldRemoveComments = opts.removeComment && commentTokens.length > 0;
12354
- if (!shouldNormalizeImports && !shouldNormalizeTemplateImports && !shouldRemoveLang && !shouldTransformInlineWxs && !shouldTransformEvents && !shouldTransformDirectives && !shouldTransformTagNames && !shouldTransformScriptModuleTags && !shouldRemoveConditionals && !shouldRemoveComments) return setCachedResult(data, cacheKey, {
12355
- code,
12356
- components,
12357
- deps
12358
- });
12359
- const ms = new MagicString(code);
12360
- if (shouldNormalizeImports) for (const { start, end, value } of wxsImportNormalizeTokens) ms.update(start, end, normalizeWxsFilename(value, normalizedScriptExtension ?? "wxs"));
12361
- if (shouldNormalizeTemplateImports) for (const { start, end, value } of templateImportNormalizeTokens) {
12362
- let nextValue = changeFileExtension(value, normalizedTemplateExtension);
12363
- if (value.startsWith("./") && !nextValue.startsWith("./") && !nextValue.startsWith("../") && !nextValue.startsWith("/")) nextValue = `./${nextValue}`;
12364
- ms.update(start, end, nextValue);
12365
- }
12366
- if (shouldRemoveLang) for (const { start, end } of removeWxsLangAttrTokens) ms.update(start, end, "");
12367
- if (shouldTransformInlineWxs) for (const { end, start, value } of inlineWxsTokens) {
12368
- const { result } = getCachedInlineWxsTransform(value, normalizedScriptExtension ?? "wxs");
12369
- if (result?.code) ms.update(start, end, `\n${result.code}`);
12370
- }
12371
- if (shouldTransformScriptModuleTags) {
12372
- const visited = /* @__PURE__ */ new Set();
12373
- for (const { start, end } of scriptModuleTagTokens) {
12374
- const key = `${start}:${end}`;
12375
- if (visited.has(key)) continue;
12376
- visited.add(key);
12377
- ms.update(start, end, resolvedScriptTag);
12378
- }
12379
- }
12380
- if (shouldTransformEvents) for (const { end, start, value } of eventTokens) ms.update(start, end, value);
12381
- if (shouldTransformDirectives) for (const { end, start, value } of directiveTokens) ms.update(start, end, value);
12382
- if (shouldTransformTagNames) for (const { end, start, value } of tagNameTokens) ms.update(start, end, value);
12383
- if (shouldRemoveConditionals) {
12384
- for (const { start, end } of removalRanges) if (end > start) ms.remove(start, end);
12385
- }
12386
- if (shouldRemoveComments) for (const { end, start } of commentTokens) ms.remove(start, end);
12387
- return setCachedResult(data, cacheKey, {
12388
- code: shouldNormalizeScriptModuleAttributes(resolvedScriptTag) ? normalizeImportSjsAttributes(ms.toString()) : ms.toString(),
12389
- components,
12390
- deps
12391
- });
12345
+ resolveCacheVersion += 1;
12346
+ appEntryOutputCache.current = void 0;
12347
+ } });
12392
12348
  }
12393
12349
  //#endregion
12394
- //#region src/plugins/utils/wxmlEmit.ts
12395
- function resolveWxmlEmitContext(compiler) {
12396
- const { wxmlService, configService, scanService } = compiler;
12397
- if (!wxmlService || !configService || !scanService) throw new Error("emitWxmlAssets 需要先初始化 wxmlService、configService 和 scanService。");
12398
- const { templateExtension, scriptModuleExtension } = resolveCompilerOutputExtensions(configService.outputExtensions);
12399
- return {
12400
- wxmlService,
12401
- configService,
12402
- scanService,
12403
- templateExtension,
12404
- scriptModuleExtension,
12405
- scriptModuleTag: resolveScriptModuleTagName({
12406
- platform: configService.platform,
12407
- scriptModuleExtension
12408
- })
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);
12409
12370
  };
12410
12371
  }
12411
- function resolveWxmlEmitTargets(options) {
12412
- const { compiler, subPackageMeta, buildTarget = "app" } = options;
12413
- const { wxmlService, configService, scanService, templateExtension } = resolveWxmlEmitContext(compiler);
12414
- return Array.from(wxmlService.tokenMap.entries()).map(([id, token]) => {
12415
- return {
12416
- id,
12417
- token,
12418
- fileName: resolveRelativeOutputFileNameWithExtension(configService, id, templateExtension)
12419
- };
12420
- }).filter(({ id, fileName }) => {
12421
- if (subPackageMeta) return fileName.startsWith(subPackageMeta.subPackage.root);
12422
- if (buildTarget === "plugin") {
12423
- const pluginRoot = configService.absolutePluginRoot;
12424
- if (!pluginRoot) return false;
12425
- 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);
12426
12381
  }
12427
- return scanService.isMainPackageFileName(fileName);
12428
- });
12382
+ debug?.(`scanTemplateEntry ${templateEntry} 耗时 ${(performance$1.now() - start).toFixed(2)}ms`);
12383
+ };
12429
12384
  }
12430
- function emitWxmlAssetFile(options) {
12431
- const { runtime, id, fileName, token, deps, emittedCodeCache, scriptModuleExtension, scriptModuleTag, templateExtension } = options;
12432
- runtime.addWatchFile?.(normalizeWatchPath(id));
12433
- if (deps) for (const dep of deps) runtime.addWatchFile?.(normalizeWatchPath(dep));
12434
- const result = handleWxml(token, {
12435
- scriptModuleExtension,
12436
- scriptModuleTag,
12437
- templateExtension
12438
- });
12439
- if (emittedCodeCache.get(fileName) === result.code) return false;
12440
- emittedCodeCache.set(fileName, result.code);
12441
- runtime.emitFile({
12442
- type: "asset",
12443
- fileName,
12444
- 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
12445
12439
  });
12446
- 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
+ };
12447
12488
  }
12448
- function emitWxmlAssetsWithCache(options) {
12449
- const { runtime, compiler, subPackageMeta, emittedCodeCache, buildTarget = "app" } = options;
12450
- const { wxmlService, templateExtension, scriptModuleExtension, scriptModuleTag } = resolveWxmlEmitContext(compiler);
12451
- const currentPackageWxmls = resolveWxmlEmitTargets({
12452
- compiler,
12453
- subPackageMeta,
12454
- buildTarget
12455
- });
12456
- const emittedFiles = [];
12457
- for (const { id, fileName, token } of currentPackageWxmls) {
12458
- emittedFiles.push(fileName);
12459
- emitWxmlAssetFile({
12460
- runtime,
12461
- id,
12462
- fileName,
12463
- token,
12464
- deps: wxmlService.depsMap.get(id),
12465
- emittedCodeCache,
12466
- scriptModuleExtension,
12467
- scriptModuleTag,
12468
- templateExtension
12469
- });
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);
12470
12507
  }
12471
- return emittedFiles;
12472
- }
12473
- function emitJsonAsset(runtime, fileName, source, extension = "json") {
12474
- runtime.emitFile({
12475
- type: "asset",
12476
- fileName: changeFileExtension(fileName, extension),
12477
- source
12478
- });
12508
+ return pending;
12479
12509
  }
12480
12510
  //#endregion
12481
12511
  //#region src/plugins/core/helpers/bundle.ts
@@ -14032,11 +14062,20 @@ function invalidateSharedStyleCache() {
14032
14062
  //#region src/plugins/utils/invalidateEntry/shared.ts
14033
14063
  const watchedCssExts = new Set(supportedCssLangs.map((ext) => `.${ext}`));
14034
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
+ ]);
14035
14073
  const configSuffixes$1 = configExtensions.map((ext) => `.${ext}`);
14036
14074
  const sidecarSuffixes = [
14037
14075
  ...configSuffixes$1,
14038
14076
  ...watchedCssExts,
14039
- ...watchedTemplateExts
14077
+ ...watchedTemplateExts,
14078
+ ...watchedScriptModuleExts
14040
14079
  ];
14041
14080
  const defaultIgnoredDirNames = new Set([
14042
14081
  "node_modules",
@@ -14210,15 +14249,26 @@ async function invalidateEntryForSidecar(ctx, filePath, event = "update") {
14210
14249
  if (configSuffix) scriptBasePath = filePath.slice(0, -configSuffix.length);
14211
14250
  else if (ext && watchedCssExts.has(ext)) scriptBasePath = filePath.slice(0, -ext.length);
14212
14251
  else if (ext && watchedTemplateExts.has(ext)) scriptBasePath = filePath.slice(0, -ext.length);
14213
- if (!scriptBasePath) return;
14252
+ const isScriptModuleSidecar = Array.from(watchedScriptModuleExts).some((suffix) => normalizedPath.endsWith(suffix));
14253
+ if (!scriptBasePath && !isScriptModuleSidecar) return;
14214
14254
  const touchedTargets = /* @__PURE__ */ new Set();
14215
14255
  const touchedScripts = /* @__PURE__ */ new Set();
14216
- const primaryScript = await findJsEntry(scriptBasePath);
14217
- if (primaryScript.path) touchedScripts.add(primaryScript.path);
14218
- if (!primaryScript.path && ext && watchedCssExts.has(ext)) {
14219
- const { importers, scripts } = await collectAffectedScriptsAndImporters(ctx, normalizedPath);
14256
+ if (isScriptModuleSidecar || ext && watchedTemplateExts.has(ext)) {
14257
+ const importers = ctx.wxmlService?.getImporters(normalizedPath) ?? /* @__PURE__ */ new Set();
14220
14258
  for (const importer of importers) touchedTargets.add(importer);
14221
- 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
+ }
14222
14272
  }
14223
14273
  const isCssSidecar = Boolean(ext && watchedCssExts.has(ext));
14224
14274
  const isTemplateSidecar = Boolean(ext && watchedTemplateExts.has(ext));
@@ -14231,7 +14281,7 @@ async function invalidateEntryForSidecar(ctx, filePath, event = "update") {
14231
14281
  await touch(script);
14232
14282
  } catch {}
14233
14283
  if (!touchedTargets.size && !touchedScripts.size) {
14234
- if (event === "create" && (isCssSidecar || isTemplateSidecar)) logger_default.info(`[sidecar:${event}] ${relativeSource} 新增,但未找到引用方,等待后续关联`);
14284
+ if (event === "create" && (isCssSidecar || isTemplateSidecar || isScriptModuleSidecar)) logger_default.info(`[sidecar:${event}] ${relativeSource} 新增,但未找到引用方,等待后续关联`);
14235
14285
  return;
14236
14286
  }
14237
14287
  const touchedList = [];
@@ -14256,9 +14306,12 @@ function ensureSidecarWatcher(ctx, rootDir) {
14256
14306
  if (!isSidecarFile(filePath)) return;
14257
14307
  const ext = path.extname(filePath);
14258
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;
14259
14312
  if (isCssFile && (event === "create" || event === "update")) extractCssImportDependencies(ctx, filePath);
14260
14313
  const isDeleteEvent = event === "delete";
14261
- if (event === "create" && ready || isDeleteEvent) {
14314
+ if (event === "create" && ready || isDeleteEvent || event === "update" && hasReverseImporters) {
14262
14315
  (async () => {
14263
14316
  await invalidateEntryForSidecar(ctx, filePath, event);
14264
14317
  if (isCssFile && isDeleteEvent) cleanupCssImporterGraph(ctx, filePath);
@@ -14270,7 +14323,8 @@ function ensureSidecarWatcher(ctx, rootDir) {
14270
14323
  const patterns = [
14271
14324
  ...configExtensions.map((ext) => path.join(absRoot, `**/*.${ext}`)),
14272
14325
  ...supportedCssLangs.map((ext) => path.join(absRoot, `**/*.${ext}`)),
14273
- ...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}`))
14274
14328
  ];
14275
14329
  const ignoredMatcher = createSidecarIgnoredMatcher(ctx, absRoot);
14276
14330
  const watcher = chokidar.watch(patterns, createSidecarWatchOptions(ctx.configService, {
@@ -14693,8 +14747,9 @@ function injectSharedStyleImports(css, modulePath, fileName, sharedStyles, confi
14693
14747
  }
14694
14748
  //#endregion
14695
14749
  //#region src/plugins/css.ts
14750
+ const LEADING_BLANK_LINES_RE = /^(?:[ \t]*\r?\n)+/;
14696
14751
  function stripLeadingBlankLines(code) {
14697
- return code.replace(/^(?:[ \t]*\r?\n)+/, "");
14752
+ return code.replace(LEADING_BLANK_LINES_RE, "");
14698
14753
  }
14699
14754
  async function handleBundleEntry(bundle, bundleKey, asset, configService, sharedStyles, emitted) {
14700
14755
  if (asset.type !== "asset") return;
@@ -14893,6 +14948,7 @@ function registerVueTemplateToken(ctx, filename, template) {
14893
14948
  try {
14894
14949
  const token = wxmlService.analyze(template);
14895
14950
  wxmlService.tokenMap.set(filename, token);
14951
+ wxmlService.setDeps(filename, wxmlService.collectDepsFromToken(filename, token.deps));
14896
14952
  wxmlService.setWxmlComponentsMap(filename, token.components);
14897
14953
  } catch {}
14898
14954
  }
@@ -18852,10 +18908,10 @@ function createDependenciesCache(ctx) {
18852
18908
  }
18853
18909
  //#endregion
18854
18910
  //#region src/runtime/npmPlugin/relations.ts
18855
- const TRAILING_SLASHES_RE = /\/+$/;
18911
+ const TRAILING_SLASHES_RE$1 = /\/+$/;
18856
18912
  const EMPTY_VALUE_RE = /^$/;
18857
18913
  function normalizeRelativeDir(value) {
18858
- const normalized = toPosixPath(value).replace(TRAILING_SLASHES_RE, "");
18914
+ const normalized = toPosixPath(value).replace(TRAILING_SLASHES_RE$1, "");
18859
18915
  return (normalized.startsWith("./") ? normalized.slice(2) : normalized).replace(EMPTY_VALUE_RE, ".");
18860
18916
  }
18861
18917
  function resolvePlatformProjectRoot(configService) {
@@ -18905,6 +18961,8 @@ function getPackNpmRelationList(ctx) {
18905
18961
  //#endregion
18906
18962
  //#region src/runtime/npmPlugin/service.ts
18907
18963
  const LEADING_SLASHES_RE = /^\/+/;
18964
+ const WINDOWS_PATH_RE = /\\|^[A-Z]:[\\/]/i;
18965
+ const TRAILING_SLASHES_RE = /\/+$/;
18908
18966
  function matchDependencyName(patterns, dep) {
18909
18967
  return patterns.some((pattern) => {
18910
18968
  if (typeof pattern === "string") return pattern === dep;
@@ -18922,6 +18980,13 @@ function matchDependencyPath(patterns, value) {
18922
18980
  return pattern.test(value);
18923
18981
  });
18924
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
+ }
18925
18990
  function resolveTargetDependencies(allDependencies, patterns) {
18926
18991
  if (patterns === false) return [];
18927
18992
  if (!Array.isArray(patterns)) return allDependencies;
@@ -19020,7 +19085,7 @@ function createNpmService(ctx) {
19020
19085
  overwrite: true,
19021
19086
  filter: (src) => {
19022
19087
  if (Array.isArray(meta.subPackage.dependencies)) {
19023
- const relPath = toPosixPath(path.relative(sourceOutDir, src));
19088
+ const relPath = resolveCopyFilterRelativePath(sourceOutDir, String(src));
19024
19089
  if (relPath === "") return true;
19025
19090
  return matchDependencyPath(meta.subPackage.dependencies, relPath);
19026
19091
  }
@@ -19233,6 +19298,7 @@ function createRuntimeState() {
19233
19298
  },
19234
19299
  wxml: {
19235
19300
  depsMap: /* @__PURE__ */ new Map(),
19301
+ importerMap: /* @__PURE__ */ new Map(),
19236
19302
  tokenMap: /* @__PURE__ */ new Map(),
19237
19303
  componentsMap: /* @__PURE__ */ new Map(),
19238
19304
  cache: new FileCache(),
@@ -19241,6 +19307,7 @@ function createRuntimeState() {
19241
19307
  scan: {
19242
19308
  subPackageMap: /* @__PURE__ */ new Map(),
19243
19309
  independentSubPackageMap: /* @__PURE__ */ new Map(),
19310
+ warnedMessages: /* @__PURE__ */ new Set(),
19244
19311
  isDirty: true,
19245
19312
  independentDirtyRoots: /* @__PURE__ */ new Set(),
19246
19313
  pluginJsonPath: void 0
@@ -19545,7 +19612,12 @@ function resolveScanJsonEntryBasename(appDirname, location, fallbackName) {
19545
19612
  }
19546
19613
  function createScanService(ctx) {
19547
19614
  const scanState = ctx.runtimeState.scan;
19548
- 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
+ }
19549
19621
  function mergeAutoRoutePages(pages, routePages) {
19550
19622
  if (routePages.length === 0) return pages;
19551
19623
  const existingPages = Array.isArray(pages) ? pages.filter((page) => typeof page === "string" && page.length > 0) : [];
@@ -19618,12 +19690,12 @@ function createScanService(ctx) {
19618
19690
  const vueAppPath = await findVueEntry(appBasename);
19619
19691
  let configFromVue;
19620
19692
  if (!appConfigFile && vueAppPath) {
19621
- const { extractConfigFromVue } = await import("./file-BAUXs16l.mjs").then((n) => n.r);
19693
+ const { extractConfigFromVue } = await import("./file-Cf3pf5w7.mjs").then((n) => n.r);
19622
19694
  configFromVue = await extractConfigFromVue(vueAppPath);
19623
19695
  if (configFromVue) appConfigFile = vueAppPath;
19624
19696
  }
19625
- if (appEntryPath && vueAppPath) logger_default.warn(`[app] 检测到 ${path.basename(appEntryPath)} 与 ${path.basename(vueAppPath)} 同时存在,当前将优先使用 ${path.basename(appEntryPath)} 作为应用入口,${path.basename(vueAppPath)} 将被忽略。`);
19626
- 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 配置不会生效。`);
19627
19699
  if (ctx.configService.absolutePluginRoot) {
19628
19700
  const { path: pluginConfigFile } = await findJsonEntry(resolveScanPluginBasename(ctx.configService.absolutePluginRoot));
19629
19701
  if (pluginConfigFile) {
@@ -19681,10 +19753,12 @@ function createScanService(ctx) {
19681
19753
  const metas = [];
19682
19754
  const independentSubPackages = [...json.subPackages ?? [], ...json.subpackages ?? []];
19683
19755
  for (const subPackage of independentSubPackages) {
19684
- const subPackageConfig = configService.weappViteConfig?.subPackages?.[subPackage.root];
19685
- 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;
19686
19759
  const resolvedSubPackage = {
19687
19760
  ...subPackage,
19761
+ ...normalizedRoot ? { root: normalizedRoot } : {},
19688
19762
  dependencies: npmSubPackageConfig?.dependencies,
19689
19763
  inlineConfig: subPackageConfig?.inlineConfig
19690
19764
  };
@@ -19696,11 +19770,11 @@ function createScanService(ctx) {
19696
19770
  meta.styleEntries = normalizeSubPackageStyleEntries(subPackageConfig?.styles, resolvedSubPackage, configService);
19697
19771
  meta.watchSharedStyles = subPackageConfig?.watchSharedStyles ?? true;
19698
19772
  metas.push(meta);
19699
- if (subPackage.root) {
19700
- subPackageMap.set(subPackage.root, meta);
19773
+ if (normalizedRoot) {
19774
+ subPackageMap.set(normalizedRoot, meta);
19701
19775
  if (subPackage.independent) {
19702
- independentSubPackageMap.set(subPackage.root, meta);
19703
- if (scanState.isDirty) independentDirtyRoots.add(subPackage.root);
19776
+ independentSubPackageMap.set(normalizedRoot, meta);
19777
+ if (scanState.isDirty) independentDirtyRoots.add(normalizedRoot);
19704
19778
  }
19705
19779
  }
19706
19780
  }
@@ -19711,8 +19785,9 @@ function createScanService(ctx) {
19711
19785
  throw new Error(`在 ${configService.absoluteSrcRoot} 目录下没有找到 \`app.json\`, 请确保你初始化了小程序项目,或者在 \`vite.config.ts\` 中设置的正确的 \`weapp.srcRoot\` 配置路径 `);
19712
19786
  }
19713
19787
  function isMainPackageFileName(fileName) {
19788
+ const normalizedFileName = toPosixPath(fileName);
19714
19789
  return [...independentSubPackageMap.keys()].every((root) => {
19715
- return !fileName.startsWith(root);
19790
+ return !normalizedFileName.startsWith(root);
19716
19791
  });
19717
19792
  }
19718
19793
  return {
@@ -19756,7 +19831,8 @@ function createScanService(ctx) {
19756
19831
  },
19757
19832
  markIndependentDirty(root) {
19758
19833
  if (!root) return;
19759
- if (independentSubPackageMap.has(root)) independentDirtyRoots.add(root);
19834
+ const normalizedRoot = normalizeRoot(root);
19835
+ if (independentSubPackageMap.has(normalizedRoot)) independentDirtyRoots.add(normalizedRoot);
19760
19836
  },
19761
19837
  drainIndependentDirtyRoots() {
19762
19838
  const roots = [...independentDirtyRoots];
@@ -19885,17 +19961,49 @@ function createWebServicePlugin(ctx) {
19885
19961
  //#endregion
19886
19962
  //#region src/runtime/wxmlPlugin.ts
19887
19963
  function createWxmlService(ctx) {
19888
- 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
+ }
19889
19989
  async function addDeps(filepath, deps = []) {
19890
- if (!depsMap.has(filepath)) {
19891
- const set = /* @__PURE__ */ new Set();
19892
- for (const dep of deps) set.add(dep);
19893
- depsMap.set(filepath, set);
19894
- await Promise.all(deps.map((dep) => scan(dep)));
19895
- } else {
19896
- const setRef = depsMap.get(filepath);
19897
- if (setRef) for (const dep of deps) setRef.add(dep);
19898
- }
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) ?? []);
19899
20007
  }
19900
20008
  function getAllDeps() {
19901
20009
  const set = /* @__PURE__ */ new Set();
@@ -19909,6 +20017,7 @@ function createWxmlService(ctx) {
19909
20017
  const currentRoot = ctx.configService?.currentSubPackageRoot;
19910
20018
  if (!currentRoot) {
19911
20019
  depsMap.clear();
20020
+ importerMap.clear();
19912
20021
  tokenMap.clear();
19913
20022
  componentsMap.clear();
19914
20023
  cache.cache.clear();
@@ -19922,14 +20031,20 @@ function createWxmlService(ctx) {
19922
20031
  };
19923
20032
  for (const key of Array.from(depsMap.keys())) {
19924
20033
  if (shouldClear(key)) {
20034
+ const depSet = depsMap.get(key);
20035
+ if (depSet) for (const dep of depSet) unlinkImporter(dep, key);
19925
20036
  depsMap.delete(key);
19926
20037
  continue;
19927
20038
  }
19928
20039
  const depSet = depsMap.get(key);
19929
20040
  if (depSet) {
19930
- 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
+ }
19931
20045
  }
19932
20046
  }
20047
+ for (const key of Array.from(importerMap.keys())) if (shouldClear(key)) importerMap.delete(key);
19933
20048
  for (const key of Array.from(tokenMap.keys())) if (shouldClear(key)) tokenMap.delete(key);
19934
20049
  for (const key of Array.from(componentsMap.keys())) if (shouldClear(key)) componentsMap.delete(key);
19935
20050
  for (const key of Array.from(cache.cache.keys())) if (shouldClear(key)) cache.delete(key);
@@ -19970,14 +20085,10 @@ function createWxmlService(ctx) {
19970
20085
  return cached;
19971
20086
  }
19972
20087
  }
19973
- const dirname = path.dirname(filepath);
19974
20088
  const res = analyze(await fs.readFile(filepath, "utf8"));
19975
20089
  tokenMap.set(filepath, res);
19976
20090
  cache.set(filepath, res);
19977
- await addDeps(filepath, res.deps.filter((x) => isTemplateImportTag(x.tagName) && isTemplate(x.value)).map((x) => {
19978
- if (x.value.startsWith("/")) return path.resolve(configService.absoluteSrcRoot, x.value.slice(1));
19979
- else return path.resolve(dirname, x.value);
19980
- }));
20091
+ await setDeps(filepath, collectDepsFromToken(filepath, res.deps));
19981
20092
  return res;
19982
20093
  }
19983
20094
  function setWxmlComponentsMap(absPath, components) {
@@ -19985,9 +20096,13 @@ function createWxmlService(ctx) {
19985
20096
  }
19986
20097
  return {
19987
20098
  depsMap,
20099
+ importerMap,
19988
20100
  tokenMap,
19989
20101
  wxmlComponentsMap: componentsMap,
19990
20102
  addDeps,
20103
+ setDeps,
20104
+ collectDepsFromToken,
20105
+ getImporters,
19991
20106
  getAllDeps,
19992
20107
  clearAll,
19993
20108
  analyze,