weapp-tailwindcss 5.0.0-next.11 → 5.0.0-next.13

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.
Files changed (81) hide show
  1. package/dist/{bundle-state-BRkhpjio.js → bundle-state-Bz8vLnCf.js} +3 -2
  2. package/dist/{bundle-state-BrtFgX-A.mjs → bundle-state-CP2XS3Uj.mjs} +3 -2
  3. package/dist/bundlers/shared/css-cleanup.d.ts +6 -1
  4. package/dist/bundlers/shared/generator-css/source-files.d.ts +9 -6
  5. package/dist/bundlers/shared/generator-css/source-resolver.d.ts +16 -2
  6. package/dist/bundlers/shared/generator-css.d.ts +4 -0
  7. package/dist/bundlers/shared/hmr-timing.d.ts +18 -1
  8. package/dist/bundlers/vite/bundle-state.d.ts +1 -0
  9. package/dist/bundlers/vite/css-finalizer.d.ts +2 -0
  10. package/dist/bundlers/vite/generate-bundle/css-handler-options.d.ts +5 -1
  11. package/dist/bundlers/vite/generate-bundle/css-share-scope.d.ts +1 -0
  12. package/dist/bundlers/vite/generate-bundle.d.ts +8 -1
  13. package/dist/bundlers/vite/incremental-runtime-class-set.d.ts +1 -0
  14. package/dist/bundlers/vite/runtime-class-set.d.ts +4 -1
  15. package/dist/bundlers/vite/source-candidates.d.ts +11 -0
  16. package/dist/bundlers/vite/source-scan.d.ts +18 -1
  17. package/dist/bundlers/vite/static-config-content.d.ts +5 -0
  18. package/dist/bundlers/webpack/BaseUnifiedPlugin/shared.d.ts +5 -0
  19. package/dist/cli.js +453 -9
  20. package/dist/cli.mjs +451 -8
  21. package/dist/core.js +1 -1
  22. package/dist/core.mjs +1 -1
  23. package/dist/css-macro/postcss.js +1 -1
  24. package/dist/css-macro/postcss.mjs +1 -1
  25. package/dist/css-macro.js +2 -2
  26. package/dist/css-macro.mjs +2 -2
  27. package/dist/defaults.js +1 -1
  28. package/dist/defaults.mjs +1 -1
  29. package/dist/generator-C9H44wEF.mjs +32 -0
  30. package/dist/generator-CRORPkpW.js +55 -0
  31. package/dist/generator.js +12 -11
  32. package/dist/generator.mjs +2 -1
  33. package/dist/gulp.js +49 -13
  34. package/dist/gulp.mjs +46 -10
  35. package/dist/{incremental-runtime-class-set-CBMefNHQ.js → incremental-runtime-class-set-DN9KKjSi.js} +512 -103
  36. package/dist/{incremental-runtime-class-set-DaS2yw5c.mjs → incremental-runtime-class-set-Dbn4yPfZ.mjs} +491 -88
  37. package/dist/index.js +4 -4
  38. package/dist/index.mjs +4 -4
  39. package/dist/{postcss-BdcRlSpp.js → postcss-Ab7YzAbs.js} +30 -19
  40. package/dist/{postcss-Bs-RbNzK.js → postcss-CZE8k8oP.js} +59 -53
  41. package/dist/{postcss-xZDiTRII.mjs → postcss-CtlrNknb.mjs} +19 -8
  42. package/dist/postcss.js +1 -1
  43. package/dist/postcss.mjs +1 -1
  44. package/dist/{precheck-D5eEdqeH.js → precheck-CRX-pMKJ.js} +37 -17
  45. package/dist/{precheck-DtBGFS-n.mjs → precheck-SG48aLG2.mjs} +29 -9
  46. package/dist/presets.js +6 -6
  47. package/dist/presets.mjs +4 -4
  48. package/dist/source-candidates-C4YgmZ8A.js +274 -0
  49. package/dist/source-candidates-CyupdLKi.mjs +259 -0
  50. package/dist/tailwindcss/runtime/cache.d.ts +1 -0
  51. package/dist/tailwindcss/v3-engine/types.d.ts +3 -0
  52. package/dist/tailwindcss/v4-engine/types.d.ts +8 -0
  53. package/dist/{tailwindcss-DGM8lHUj.mjs → tailwindcss-BbTVeQkG.mjs} +9 -4
  54. package/dist/{tailwindcss-B78nj6n7.js → tailwindcss-DZ6jVYb4.js} +21 -16
  55. package/dist/v3-engine-D61eilBl.mjs +3208 -0
  56. package/dist/v3-engine-DwV1E6rX.js +3461 -0
  57. package/dist/{vite-C8S1wfyQ.mjs → vite-Ti_qSctn.mjs} +380 -542
  58. package/dist/{vite-BEj9JOOA.js → vite-xKS6RvLR.js} +385 -550
  59. package/dist/vite.js +1 -1
  60. package/dist/vite.mjs +1 -1
  61. package/dist/weapp-tw-css-import-rewrite-loader.js +29 -9
  62. package/dist/weapp-tw-runtime-classset-loader.js +1 -1
  63. package/dist/{webpack-ZGIKKpFf.mjs → webpack-DvptFz7B.mjs} +36 -19
  64. package/dist/{webpack-Dm1IXTIh.js → webpack-wfNutjMm.js} +40 -23
  65. package/dist/webpack.js +1 -1
  66. package/dist/webpack.mjs +1 -1
  67. package/package.json +3 -3
  68. package/dist/cache-B_9E7FxF.js +0 -517
  69. package/dist/cache-DEDxBMIw.mjs +0 -443
  70. package/dist/generator-CahkD2vq.mjs +0 -1469
  71. package/dist/generator-Ck1Dd1V0.js +0 -1568
  72. package/dist/runtime-patch-CqB-A4zA.js +0 -85
  73. package/dist/runtime-patch-DGKsVkiG.mjs +0 -71
  74. package/dist/source-scan-CIVTa3Cj.js +0 -297
  75. package/dist/source-scan-CJ0y0XBj.mjs +0 -258
  76. /package/dist/{constants-BeeyfJ9k.js → constants-BoB_6lFw.js} +0 -0
  77. /package/dist/{constants-BG12WAKw.mjs → constants-E_loJC49.mjs} +0 -0
  78. /package/dist/{logger-EVNB9z7i.js → logger-BRy6XPQ2.js} +0 -0
  79. /package/dist/{logger-CZUxvJJD.mjs → logger-Bub1jggA.mjs} +0 -0
  80. /package/dist/{utils-CGBVVNm6.mjs → utils-CycMvPn_.mjs} +0 -0
  81. /package/dist/{utils-4ODFyoqD.js → utils-D0MZP_tr.js} +0 -0
@@ -1,26 +1,20 @@
1
- import { c as resolveTailwindcssOptions, l as omitUndefined, n as getRuntimeClassSetSignature, s as findTailwindConfig, u as findNearestPackageRoot } from "./cache-DEDxBMIw.mjs";
2
- import { n as createDebug } from "./runtime-patch-DGKsVkiG.mjs";
3
- import { c as resolveTailwindV4SourceOptionsFromPatcher, d as filterUnsupportedMiniProgramTailwindV4Candidates, i as normalizeWeappTailwindcssGeneratorOptions, m as resolveTailwindV3SourceFromPatcher, s as resolveTailwindV4SourceFromPatcher } from "./generator-CahkD2vq.mjs";
4
- import { a as processCachedTask, c as normalizeTailwindSourceForGenerator, i as validateCandidatesByGenerator, l as hasTailwindGeneratedCssMarkers, n as emitHmrTiming, o as hasTailwindRootDirectives, r as generateCssByGenerator, s as hasTailwindSourceDirectives, t as createBundleRuntimeClassSetManager } from "./incremental-runtime-class-set-DaS2yw5c.mjs";
5
- import { a as analyzeSource, c as isClassContextLiteralPath, g as createTailwindRuntimeReadyPromise, h as collectRuntimeClassSet, i as createAttributeMatcher, l as replaceWxml, m as toCustomAttributesEntities, n as getCompilerContext, o as JsTokenUpdater, p as vitePluginName, r as generateCode, s as _defineProperty, t as shouldSkipJsTransform, u as babelParse, v as refreshTailwindRuntimeState } from "./precheck-DtBGFS-n.mjs";
6
- import { o as resolveUniUtsPlatform } from "./utils-CGBVVNm6.mjs";
7
- import { c as upsertTailwindV4CssSource, i as resolveUniAppXOptions, r as isUniAppXEnabled, s as hasConfiguredTailwindV4CssRoots } from "./tailwindcss-DGM8lHUj.mjs";
8
- import { a as parseConfigParam, i as normalizeLegacyContentEntries, n as createSourceScanPattern, o as resolveCssSourceEntries, r as expandTailwindSourceEntries, t as collectCssInlineSourceCandidates } from "./source-scan-CJ0y0XBj.mjs";
9
- import { a as createBundleModuleGraphOptions, c as resolvePluginDisabledState, d as normalizeOutputPathKey, i as applyLinkedResults, l as isSourceStyleRequest, n as createBundleBuildState, o as pushConcurrentTaskFactories, p as toAbsoluteOutputPath, r as updateBundleBuildState, s as resolvePackageDir, t as buildBundleSnapshot } from "./bundle-state-BrtFgX-A.mjs";
10
- import { t as logger$1 } from "./logger-CZUxvJJD.mjs";
11
- import postcss from "postcss";
1
+ import { B as omitUndefined, D as filterUnsupportedMiniProgramTailwindV4Candidates, F as createDebug, R as findTailwindConfig, V as findNearestPackageRoot, _ as resolveViteSourceScanEntries, g as resolveTailwindV4EntriesFromCssCached, l as getRuntimeClassSetSignature, m as discoverTailwindV4CssEntries, p as createViteSourceScanMatcher, v as resolveViteTailwindV4CssDependencies, z as resolveTailwindcssOptions } from "./v3-engine-D61eilBl.mjs";
2
+ import { i as normalizeWeappTailwindcssGeneratorOptions } from "./generator-C9H44wEF.mjs";
3
+ import { a as validateCandidatesByGenerator, c as hasTailwindSourceDirectives, i as generateCssByGenerator, l as normalizeTailwindSourceForGenerator, n as createHmrTimingRecorder, o as processCachedTask, s as hasTailwindRootDirectives, t as createBundleRuntimeClassSetManager, u as hasTailwindGeneratedCssMarkers } from "./incremental-runtime-class-set-Dbn4yPfZ.mjs";
4
+ import { a as analyzeSource, c as isClassContextLiteralPath, g as createTailwindRuntimeReadyPromise, h as collectRuntimeClassSet, i as createAttributeMatcher, l as replaceWxml, m as toCustomAttributesEntities, n as getCompilerContext, o as JsTokenUpdater, p as vitePluginName, r as generateCode, s as _defineProperty, t as shouldSkipJsTransform, u as babelParse, v as refreshTailwindRuntimeState } from "./precheck-SG48aLG2.mjs";
5
+ import { o as resolveUniUtsPlatform } from "./utils-CycMvPn_.mjs";
6
+ import { c as upsertTailwindV4CssSource, i as resolveUniAppXOptions, r as isUniAppXEnabled, s as hasConfiguredTailwindV4CssRoots } from "./tailwindcss-BbTVeQkG.mjs";
7
+ import { n as isSourceCandidateRequest, t as createSourceCandidateCollector } from "./source-candidates-CyupdLKi.mjs";
8
+ import { a as createBundleModuleGraphOptions, c as resolvePluginDisabledState, d as normalizeOutputPathKey, i as applyLinkedResults, l as isSourceStyleRequest, n as createBundleBuildState, o as pushConcurrentTaskFactories, p as toAbsoluteOutputPath, r as updateBundleBuildState, s as resolvePackageDir, t as buildBundleSnapshot } from "./bundle-state-CP2XS3Uj.mjs";
9
+ import { t as logger$1 } from "./logger-Bub1jggA.mjs";
10
+ import fs, { existsSync, readFileSync } from "node:fs";
12
11
  import path from "node:path";
13
12
  import process from "node:process";
14
13
  import { logger } from "@weapp-tailwindcss/logger";
15
- import { cleanUrl as cleanUrl$1, ensurePosix } from "@weapp-tailwindcss/shared";
16
- import { extractRawCandidatesWithPositions } from "tailwindcss-patch";
17
- import fs, { existsSync, readFileSync } from "node:fs";
18
- import { loadConfig } from "tailwindcss-config";
14
+ import { cleanUrl, ensurePosix } from "@weapp-tailwindcss/shared";
19
15
  import { readFile } from "node:fs/promises";
20
16
  import MagicString from "magic-string";
21
17
  import { splitCode } from "@weapp-tailwindcss/shared/extractors";
22
- import fg from "fast-glob";
23
- import micromatch from "micromatch";
24
18
  import postcssHtmlTransform from "@weapp-tailwindcss/postcss/html-transform";
25
19
  import { NodeTypes } from "@vue/compiler-dom";
26
20
  import { parse } from "@vue/compiler-sfc";
@@ -312,7 +306,7 @@ function normalizePath(id) {
312
306
  async function formatPostcssSourceMap(rawMap, file) {
313
307
  const inputFileDir = path.dirname(file);
314
308
  const sources = rawMap.sources.map((source) => {
315
- const cleanSource = cleanUrl$1(decodeURIComponent(source));
309
+ const cleanSource = cleanUrl(decodeURIComponent(source));
316
310
  if (cleanSource[0] === "<" && cleanSource.endsWith(">")) return `\0${cleanSource}`;
317
311
  return normalizePath(path.resolve(inputFileDir, cleanSource));
318
312
  });
@@ -364,7 +358,7 @@ function isPreprocessorRequest(id, lang) {
364
358
  return PREPROCESSOR_EXT_RE.test(id);
365
359
  }
366
360
  function resolveUniAppXCssTarget(id) {
367
- return UVUE_NVUE_RE.test(cleanUrl$1(id)) ? "uvue" : void 0;
361
+ return UVUE_NVUE_RE.test(cleanUrl(id)) ? "uvue" : void 0;
368
362
  }
369
363
  function resolveUniAppXJsTransformEnabled$1(uniAppX) {
370
364
  return uniAppX === void 0 ? true : isUniAppXEnabled(uniAppX);
@@ -413,7 +407,7 @@ function createUniAppXPlugins(options) {
413
407
  const postcssResult = await styleHandler(code, styleHandlerOptions);
414
408
  const warnings = typeof postcssResult.warnings === "function" ? postcssResult.warnings() : [];
415
409
  for (const warning of warnings) logger$1.warn(warning.toString());
416
- const postcssMap = await formatPostcssSourceMap(postcssResult.map.toJSON(), cleanUrl$1(id));
410
+ const postcssMap = await formatPostcssSourceMap(postcssResult.map.toJSON(), cleanUrl(id));
417
411
  return {
418
412
  code: postcssResult.css,
419
413
  map: postcssMap
@@ -534,6 +528,7 @@ function createCssHandlerOptions(opts, majorVersion, file) {
534
528
  function shouldGenerateCssByGenerator(opts, file, rawSource, processed) {
535
529
  const generatorOptions = normalizeWeappTailwindcssGeneratorOptions(opts.generator);
536
530
  if (hasTailwindGeneratedCssMarkers(rawSource) || hasTailwindSourceDirectives(rawSource, { importFallback: generatorOptions.importFallback })) return true;
531
+ if (opts.twPatcher.majorVersion === 3) return false;
537
532
  return processed && shouldFinalizeProcessedCssAsset(opts, file);
538
533
  }
539
534
  function shouldFinalizeProcessedCssAsset(opts, file) {
@@ -545,7 +540,7 @@ function createViteCssFinalizerOutputPlugin(context) {
545
540
  generateBundle: {
546
541
  order: "post",
547
542
  async handler(_options, bundle) {
548
- const { opts, runtimeState, ensureRuntimeClassSet, isCssAssetProcessed, markCssAssetProcessed, debug, getResolvedConfig, recordCssAssetResult, getRecordedGeneratorCandidates, getSourceCandidates, waitForSourceCandidateSyncs, rememberMainCssSource } = context;
543
+ const { opts, runtimeState, ensureRuntimeClassSet, isCssAssetProcessed, markCssAssetProcessed, debug, getResolvedConfig, recordCssAssetResult, getRecordedGeneratorCandidates, getSourceCandidates, getSourceCandidatesForEntries, waitForSourceCandidateSyncs, rememberMainCssSource } = context;
549
544
  if (getResolvedConfig()?.command !== "build") return;
550
545
  const isCssOutputAssetEntry = (entry) => {
551
546
  const [, output] = entry;
@@ -575,6 +570,7 @@ function createViteCssFinalizerOutputPlugin(context) {
575
570
  file,
576
571
  cssHandlerOptions,
577
572
  cssUserHandlerOptions,
573
+ getSourceCandidatesForEntries,
578
574
  styleHandler: opts.styleHandler,
579
575
  debug
580
576
  }) : void 0;
@@ -630,20 +626,25 @@ function createCssHandlerOptionsCache(options) {
630
626
  const cssUserHandlerOptionsCache = /* @__PURE__ */ new Map();
631
627
  const getCssHandlerOptions = (file) => {
632
628
  const majorVersion = options.getMajorVersion();
633
- const isMainChunk = options.mainCssChunkMatcher(file, options.appType);
634
- const cacheKey = `${majorVersion ?? "unknown"}:${isMainChunk ? "1" : "0"}:${file}`;
629
+ const appType = options.getAppType();
630
+ const isMainChunk = options.mainCssChunkMatcher(file, appType);
631
+ const outputRoot = options.getOutputRoot?.();
632
+ const cacheKey = `${majorVersion ?? "unknown"}:${appType ?? "unknown"}:${isMainChunk ? "1" : "0"}:${outputRoot ?? ""}:${file}`;
635
633
  const cached = cssHandlerOptionsCache.get(cacheKey);
636
634
  if (cached) return cached;
637
635
  const created = {
638
636
  isMainChunk,
639
637
  postcssOptions: { options: { from: file } },
640
- majorVersion
638
+ majorVersion,
639
+ sourceOptions: { outputRoot }
641
640
  };
642
641
  cssHandlerOptionsCache.set(cacheKey, created);
643
642
  return created;
644
643
  };
645
644
  const getCssUserHandlerOptions = (file) => {
646
- const cacheKey = `${options.getMajorVersion() ?? "unknown"}:${file}`;
645
+ const majorVersion = options.getMajorVersion();
646
+ const outputRoot = options.getOutputRoot?.();
647
+ const cacheKey = `${majorVersion ?? "unknown"}:${outputRoot ?? ""}:${file}`;
647
648
  const cached = cssUserHandlerOptionsCache.get(cacheKey);
648
649
  if (cached) return cached;
649
650
  const created = {
@@ -682,6 +683,8 @@ function createCssTransformShareScope(file, rawSource) {
682
683
  }
683
684
  function createCssTransformShareScopeKey(opts, file, rawSource) {
684
685
  if (opts.mainCssChunkMatcher(file, opts.appType)) return `main:${normalizeOutputPathKey(file)}`;
686
+ const generatorOptions = normalizeWeappTailwindcssGeneratorOptions(opts.generator);
687
+ if (hasTailwindGeneratedCssMarkers(rawSource) || hasTailwindSourceDirectives(rawSource, { importFallback: generatorOptions.importFallback })) return `source:${normalizeOutputPathKey(file)}`;
685
688
  return createCssTransformShareScope(file, rawSource);
686
689
  }
687
690
  function createCssRuntimeSignature(runtimeSignature, generatorCandidateSignature) {
@@ -873,16 +876,29 @@ function hasRuntimeAffectingSourceChanges(changedByType) {
873
876
  }
874
877
  //#endregion
875
878
  //#region src/bundlers/vite/generate-bundle.ts
879
+ function addSiblingCssFile(files, file) {
880
+ if (file.endsWith(".wxml")) files.add(file.replace(/\.wxml$/, ".wxss"));
881
+ else if (file.endsWith(".js")) files.add(file.replace(/\.js$/, ".wxss"));
882
+ }
883
+ function collectRuntimeLinkedCssFiles(snapshot) {
884
+ const files = /* @__PURE__ */ new Set();
885
+ for (const file of snapshot.runtimeAffectingChangedByType.html) addSiblingCssFile(files, file);
886
+ for (const file of snapshot.runtimeAffectingChangedByType.js) addSiblingCssFile(files, file);
887
+ return files;
888
+ }
876
889
  function createGenerateBundleHook(context) {
877
890
  const state = createBundleBuildState();
891
+ const lastCssResultByFile = /* @__PURE__ */ new Map();
892
+ let currentOutDir;
878
893
  const cssHandlerOptions = createCssHandlerOptionsCache({
879
- appType: context.opts.appType,
894
+ getAppType: () => context.opts.appType,
880
895
  mainCssChunkMatcher: context.opts.mainCssChunkMatcher,
881
- getMajorVersion: () => context.runtimeState.twPatcher.majorVersion
896
+ getMajorVersion: () => context.runtimeState.twPatcher.majorVersion,
897
+ getOutputRoot: () => currentOutDir
882
898
  });
883
899
  return async function generateBundle(_opt, bundle) {
884
900
  const addWatchFile = (id) => this.addWatchFile?.(id);
885
- const { opts, runtimeState, ensureBundleRuntimeClassSet, debug, getResolvedConfig, markCssAssetProcessed, recordCssAssetResult, getSourceCandidates, waitForSourceCandidateSyncs, rememberMainCssSource, getRememberedMainCssSources, getRememberedMainCssSignature, setRememberedMainCssSignature, recordGeneratorCandidates } = context;
901
+ const { opts, runtimeState, ensureBundleRuntimeClassSet, debug, getResolvedConfig, markCssAssetProcessed, recordCssAssetResult, getSourceCandidates, getSourceCandidatesForEntries, waitForSourceCandidateSyncs, rememberMainCssSource, getRememberedMainCssSources, getRememberedMainCssSignature, setRememberedMainCssSignature, recordGeneratorCandidates, hmrTimingRecorder } = context;
886
902
  const { cache, onEnd, onStart, onUpdate, styleHandler, templateHandler, jsHandler, uniAppX } = opts;
887
903
  const generatorOptions = normalizeWeappTailwindcssGeneratorOptions(opts.generator);
888
904
  const { getCssHandlerOptions, getCssUserHandlerOptions } = cssHandlerOptions;
@@ -890,17 +906,35 @@ function createGenerateBundleHook(context) {
890
906
  debug("start");
891
907
  onStart();
892
908
  const hmrTimingStartedAt = performance.now();
909
+ const timingDetails = {};
910
+ const recordTimingDetail = (name, startedAt) => {
911
+ timingDetails[name] = (timingDetails[name] ?? 0) + Math.max(0, performance.now() - startedAt);
912
+ };
913
+ const timeTask = async (name, task) => {
914
+ const start = performance.now();
915
+ try {
916
+ await task();
917
+ } finally {
918
+ recordTimingDetail(`tasks.${name}`, start);
919
+ }
920
+ };
893
921
  const metrics = createEmptyMetrics();
894
922
  const forceRuntimeRefreshByEnv = process.env["WEAPP_TW_VITE_FORCE_RUNTIME_REFRESH"] === "1";
895
923
  const disableDirtyOptimization = process.env["WEAPP_TW_VITE_DISABLE_DIRTY"] === "1";
896
924
  const disableJsPrecheck = process.env["WEAPP_TW_VITE_DISABLE_JS_PRECHECK"] === "1";
897
925
  const debugCssDiff = process.env["WEAPP_TW_VITE_DEBUG_CSS_DIFF"] === "1";
926
+ const disableV3OxideSourceRuntime = process.env["WEAPP_TW_VITE_DISABLE_V3_OXIDE_RUNTIME"] === "1";
898
927
  const resolvedConfig = getResolvedConfig();
899
928
  const bundleFiles = Object.keys(bundle);
900
- const useIncrementalMode = !(resolvedConfig?.command === "build") || hasOmittedKnownBundleFiles(bundleFiles, state.sourceHashByFile.keys());
929
+ const buildCommand = resolvedConfig?.command === "build";
930
+ const hasPreviousBundleState = state.iteration > 0 || state.sourceHashByFile.size > 0;
931
+ const useIncrementalMode = !buildCommand || hasPreviousBundleState || hasOmittedKnownBundleFiles(bundleFiles, state.sourceHashByFile.keys());
901
932
  const rootDir = resolvedConfig?.root ? path.resolve(resolvedConfig.root) : process.cwd();
902
933
  const outDir = resolvedConfig?.build?.outDir ? path.resolve(rootDir, resolvedConfig.build.outDir) : rootDir;
934
+ currentOutDir = outDir;
935
+ const snapshotStart = performance.now();
903
936
  const snapshot = buildBundleSnapshot(bundle, opts, outDir, state, disableDirtyOptimization || !useIncrementalMode);
937
+ recordTimingDetail("snapshot", snapshotStart);
904
938
  const useBundleRuntimeClassSet = useIncrementalMode || runtimeState.twPatcher.majorVersion === 4;
905
939
  const forceRuntimeRefreshBySource = useIncrementalMode && hasRuntimeAffectingSourceChanges(snapshot.runtimeAffectingChangedByType);
906
940
  const processFiles = snapshot.processFiles;
@@ -910,18 +944,27 @@ function createGenerateBundleHook(context) {
910
944
  useIncrementalMode,
911
945
  iteration: state.iteration + 1
912
946
  });
947
+ const sourceCandidateWaitStart = performance.now();
948
+ await waitForSourceCandidateSyncs?.();
949
+ recordTimingDetail("sourceCandidates.wait", sourceCandidateWaitStart);
950
+ const sourceCandidates = getSourceCandidates?.() ?? /* @__PURE__ */ new Set();
913
951
  const jsEntries = snapshot.jsEntries;
914
952
  const getJsEntry = createJsEntryResolver(jsEntries);
915
953
  const moduleGraphOptions = createBundleModuleGraphOptions(outDir, jsEntries);
954
+ const hasCssAssetEntry = snapshot.entries.some((entry) => entry.type === "css" && entry.output.type === "asset");
955
+ const hasRuntimeAffectingChanges = hasRuntimeAffectingSourceChanges(snapshot.runtimeAffectingChangedByType);
956
+ const useV3OxideSourceRuntime = runtimeState.twPatcher.majorVersion === 3 && sourceCandidates.size > 0 && hasCssAssetEntry && !forceRuntimeRefreshByEnv && !disableV3OxideSourceRuntime;
916
957
  const runtimeStart = performance.now();
917
- const runtime = useBundleRuntimeClassSet ? await ensureBundleRuntimeClassSet(snapshot, forceRuntimeRefreshByEnv) : await context.ensureRuntimeClassSet(forceRuntimeRefreshByEnv);
958
+ const runtime = useV3OxideSourceRuntime ? await ensureBundleRuntimeClassSet(snapshot, forceRuntimeRefreshByEnv, {
959
+ allowBaselineOnlyInitialSync: true,
960
+ baseClassSet: sourceCandidates
961
+ }) : useBundleRuntimeClassSet ? await ensureBundleRuntimeClassSet(snapshot, forceRuntimeRefreshByEnv, { allowBaselineOnlyInitialSync: buildCommand }) : await context.ensureRuntimeClassSet(forceRuntimeRefreshByEnv);
962
+ if (useV3OxideSourceRuntime) debug("[tailwindcss:v3] use oxide source candidates as runtime input, candidates=%d", sourceCandidates.size);
918
963
  const shouldFilterTailwindV4MiniProgramCandidates = runtimeState.twPatcher.majorVersion === 4 && generatorOptions.target === "weapp";
919
- await waitForSourceCandidateSyncs?.();
920
- const sourceCandidates = getSourceCandidates?.() ?? /* @__PURE__ */ new Set();
921
964
  const collectedGeneratorCandidates = new Set([...runtime, ...sourceCandidates]);
922
965
  let generatorRuntime = collectLegacyContainerCompatCandidates(sourceCandidates, shouldFilterTailwindV4MiniProgramCandidates ? filterUnsupportedMiniProgramTailwindV4Candidates(collectedGeneratorCandidates) : collectedGeneratorCandidates);
923
966
  let transformRuntime = runtime;
924
- if (runtimeState.twPatcher.majorVersion === 3 && generatorRuntime.size > 0) {
967
+ if (runtimeState.twPatcher.majorVersion === 3 && generatorRuntime.size > 0 && !useV3OxideSourceRuntime) {
925
968
  const cssEntries = snapshot.entries.filter((entry) => entry.type === "css" && entry.output.type === "asset");
926
969
  const mainCssEntry = cssEntries.find((entry) => getCssHandlerOptions(entry.file).isMainChunk) ?? cssEntries[0];
927
970
  if (mainCssEntry) {
@@ -946,12 +989,16 @@ function createGenerateBundleHook(context) {
946
989
  }
947
990
  }
948
991
  const generatorCandidateSignature = createCandidateSignature(generatorRuntime);
992
+ const generatorCandidatesChanged = state.generatorCandidateSignature !== generatorCandidateSignature;
993
+ const runtimeLinkedCssFiles = collectRuntimeLinkedCssFiles(snapshot);
949
994
  recordGeneratorCandidates?.(generatorRuntime);
950
995
  const defaultTemplateHandlerOptions = { runtimeSet: transformRuntime };
951
996
  metrics.runtimeSet = measureElapsed(runtimeStart);
997
+ timingDetails.runtime = metrics.runtimeSet;
952
998
  if (forceRuntimeRefreshBySource) debug("runtimeSet forced refresh due to source changes: html=%d js=%d", snapshot.runtimeAffectingChangedByType.html.size, snapshot.runtimeAffectingChangedByType.js.size);
953
999
  debug("get runtimeSet, class count: %d, transform class count: %d", runtime.size, transformRuntime.size);
954
1000
  const runtimeSignature = getRuntimeClassSetSignature(runtimeState.twPatcher) ?? "runtime:missing";
1001
+ const shouldProcessTailwindGeneration = !useIncrementalMode || hasRuntimeAffectingChanges || generatorCandidatesChanged || snapshot.processFiles.css.size > 0;
955
1002
  const { applyLinkedUpdates, pendingLinkedUpdates } = createLinkedUpdateHelpers({
956
1003
  jsEntries,
957
1004
  onUpdate,
@@ -971,7 +1018,7 @@ function createGenerateBundleHook(context) {
971
1018
  metrics.html.total++;
972
1019
  if (!processFiles.html.has(file)) continue;
973
1020
  const rawSource = originalEntrySource;
974
- tasks.push(processCachedTask({
1021
+ tasks.push(timeTask("html", () => processCachedTask({
975
1022
  cache,
976
1023
  cacheKey: file,
977
1024
  hashKey: `${file}:html:${runtimeSignature}`,
@@ -999,7 +1046,7 @@ function createGenerateBundleHook(context) {
999
1046
  debug("html handle: %s", file);
1000
1047
  return { result: transformed };
1001
1048
  }
1002
- }));
1049
+ })));
1003
1050
  continue;
1004
1051
  }
1005
1052
  if (type === "css" && originalSource.type === "asset") {
@@ -1008,15 +1055,28 @@ function createGenerateBundleHook(context) {
1008
1055
  const cssRuntimeAffectingSignature = snapshot.runtimeAffectingSignatureByFile.get(file) ?? rawSource;
1009
1056
  const cssShareScope = createCssTransformShareScopeKey(opts, file, rawSource);
1010
1057
  const cssHandlerOptions = getCssHandlerOptions(file);
1011
- const cssRuntimeSignature = createCssRuntimeSignature(runtimeSignature, generatorCandidateSignature);
1058
+ const shouldTrackGeneratorRuntime = shouldProcessTailwindGeneration && (!useIncrementalMode || cssHandlerOptions.isMainChunk || processFiles.css.has(file) || runtimeLinkedCssFiles.has(file));
1059
+ const scopedGeneratorCandidateSignature = shouldTrackGeneratorRuntime ? generatorCandidateSignature : "generator:stable";
1060
+ const cssRuntimeSignature = createCssRuntimeSignature(runtimeSignature, scopedGeneratorCandidateSignature);
1012
1061
  const cssSharedCacheKey = `${cssShareScope}:${cssRuntimeSignature}:${runtimeState.twPatcher.majorVersion ?? "unknown"}:${cssHandlerOptions.isMainChunk ? "1" : "0"}:${cssRuntimeAffectingSignature}`;
1013
- tasks.push(processCachedTask({
1062
+ if (!shouldTrackGeneratorRuntime) {
1063
+ const lastCss = lastCssResultByFile.get(file);
1064
+ if (lastCss != null) {
1065
+ originalSource.source = lastCss;
1066
+ markCssAssetProcessed?.(originalSource, file);
1067
+ metrics.css.cacheHits++;
1068
+ debug("css replay last result: %s", file);
1069
+ continue;
1070
+ }
1071
+ }
1072
+ tasks.push(timeTask("css", () => processCachedTask({
1014
1073
  cache,
1015
1074
  cacheKey: file,
1016
1075
  hashKey: `${file}:css:${cssRuntimeSignature}:${runtimeState.twPatcher.majorVersion ?? "unknown"}`,
1017
- hash: `${getSnapshotHash(snapshot.runtimeAffectingHashByFile, file, cssRuntimeAffectingSignature)}:${generatorCandidateSignature}`,
1076
+ hash: `${getSnapshotHash(snapshot.runtimeAffectingHashByFile, file, cssRuntimeAffectingSignature)}:${scopedGeneratorCandidateSignature}`,
1018
1077
  applyResult(source) {
1019
1078
  originalSource.source = source;
1079
+ lastCssResultByFile.set(file, source);
1020
1080
  markCssAssetProcessed?.(originalSource, file);
1021
1081
  if (cssHandlerOptions.isMainChunk) rememberMainCssSource?.(file, rawSource, cssRuntimeSignature);
1022
1082
  },
@@ -1038,6 +1098,7 @@ function createGenerateBundleHook(context) {
1038
1098
  const runTransform = async () => {
1039
1099
  const start = performance.now();
1040
1100
  await runtimeState.readyPromise;
1101
+ const previousCss = useIncrementalMode && !snapshot.changedByType.css.has(file) ? lastCssResultByFile.get(file) : void 0;
1041
1102
  const generated = await generateCssByGenerator({
1042
1103
  opts,
1043
1104
  runtimeState,
@@ -1046,8 +1107,10 @@ function createGenerateBundleHook(context) {
1046
1107
  file,
1047
1108
  cssHandlerOptions,
1048
1109
  cssUserHandlerOptions: getCssUserHandlerOptions(file),
1110
+ getSourceCandidatesForEntries,
1049
1111
  styleHandler,
1050
- debug
1112
+ debug,
1113
+ previousCss
1051
1114
  });
1052
1115
  if (generated) {
1053
1116
  registerGeneratorDependencies({ addWatchFile }, generated.dependencies);
@@ -1072,7 +1135,7 @@ function createGenerateBundleHook(context) {
1072
1135
  debug("css handle: %s", file);
1073
1136
  return { result: css };
1074
1137
  }
1075
- }));
1138
+ })));
1076
1139
  continue;
1077
1140
  }
1078
1141
  if (type !== "js") continue;
@@ -1085,38 +1148,40 @@ function createGenerateBundleHook(context) {
1085
1148
  const linkedSet = useIncrementalMode ? /* @__PURE__ */ new Set() : void 0;
1086
1149
  if (linkedByEntry && linkedSet) linkedByEntry.set(file, linkedSet);
1087
1150
  jsTaskFactories.push(async () => {
1088
- const hashSalt = createJsHashSalt(runtimeSignature, useIncrementalMode ? createLinkedImpactSignature(file, snapshot.linkedImpactsByEntry, snapshot.sourceHashByFile) : void 0);
1089
- await processCachedTask({
1090
- cache,
1091
- cacheKey: file,
1092
- hashKey: `${file}:js`,
1093
- hash: `${getSnapshotHash(snapshot.sourceHashByFile, file, initialRawSource)}:${hashSalt}`,
1094
- applyResult(source) {
1095
- originalSource.code = source;
1096
- },
1097
- onCacheHit() {
1098
- metrics.js.cacheHits++;
1099
- debug("js cache hit: %s", file);
1100
- },
1101
- async transform() {
1102
- const start = performance.now();
1103
- const rawSource = originalSource.code;
1104
- if (!shouldTransformJs) debug("js cache replay miss, fallback transform: %s", file);
1105
- const handlerOptions = createHandlerOptions(absoluteFile);
1106
- if (!disableJsPrecheck && shouldSkipJsTransform(rawSource, handlerOptions)) {
1151
+ await timeTask("js", async () => {
1152
+ const hashSalt = createJsHashSalt(runtimeSignature, useIncrementalMode ? createLinkedImpactSignature(file, snapshot.linkedImpactsByEntry, snapshot.sourceHashByFile) : void 0);
1153
+ await processCachedTask({
1154
+ cache,
1155
+ cacheKey: file,
1156
+ hashKey: `${file}:js`,
1157
+ hash: `${getSnapshotHash(snapshot.sourceHashByFile, file, initialRawSource)}:${hashSalt}`,
1158
+ applyResult(source) {
1159
+ originalSource.code = source;
1160
+ },
1161
+ onCacheHit() {
1162
+ metrics.js.cacheHits++;
1163
+ debug("js cache hit: %s", file);
1164
+ },
1165
+ async transform() {
1166
+ const start = performance.now();
1167
+ const rawSource = originalSource.code;
1168
+ if (!shouldTransformJs) debug("js cache replay miss, fallback transform: %s", file);
1169
+ const handlerOptions = createHandlerOptions(absoluteFile);
1170
+ if (!disableJsPrecheck && shouldSkipJsTransform(rawSource, handlerOptions)) {
1171
+ metrics.js.elapsed += measureElapsed(start);
1172
+ metrics.js.transformed++;
1173
+ return { result: rawSource };
1174
+ }
1175
+ const { code, linked } = await jsHandler(rawSource, transformRuntime, handlerOptions);
1107
1176
  metrics.js.elapsed += measureElapsed(start);
1108
1177
  metrics.js.transformed++;
1109
- return { result: rawSource };
1178
+ onUpdate(file, rawSource, code);
1179
+ debug("js handle: %s", file);
1180
+ collectLinkedFileNames(linked, getJsEntry, linkedSet);
1181
+ applyLinkedUpdates(linked);
1182
+ return { result: code };
1110
1183
  }
1111
- const { code, linked } = await jsHandler(rawSource, transformRuntime, handlerOptions);
1112
- metrics.js.elapsed += measureElapsed(start);
1113
- metrics.js.transformed++;
1114
- onUpdate(file, rawSource, code);
1115
- debug("js handle: %s", file);
1116
- collectLinkedFileNames(linked, getJsEntry, linkedSet);
1117
- applyLinkedUpdates(linked);
1118
- return { result: code };
1119
- }
1184
+ });
1120
1185
  });
1121
1186
  });
1122
1187
  } else if (uniAppX && originalSource.type === "asset") {
@@ -1140,37 +1205,39 @@ function createGenerateBundleHook(context) {
1140
1205
  uniAppX
1141
1206
  });
1142
1207
  jsTaskFactories.push(async () => {
1143
- const start = performance.now();
1144
- if (!shouldTransformJs) {
1145
- debug("js skip transform (clean, uni-app-x), replay cache: %s", file);
1208
+ await timeTask("js", async () => {
1209
+ const start = performance.now();
1210
+ if (!shouldTransformJs) {
1211
+ debug("js skip transform (clean, uni-app-x), replay cache: %s", file);
1212
+ await factory();
1213
+ metrics.js.elapsed += measureElapsed(start);
1214
+ metrics.js.transformed++;
1215
+ return;
1216
+ }
1217
+ const currentSource = originalEntrySource;
1218
+ const precheckOptions = createHandlerOptions(path.resolve(outDir, file), {
1219
+ uniAppX: resolveUniAppXJsTransformEnabled(uniAppX),
1220
+ babelParserOptions: {
1221
+ plugins: ["typescript"],
1222
+ sourceType: "unambiguous"
1223
+ }
1224
+ });
1225
+ if (!disableJsPrecheck && shouldSkipJsTransform(currentSource, precheckOptions)) {
1226
+ metrics.js.elapsed += measureElapsed(start);
1227
+ metrics.js.transformed++;
1228
+ return;
1229
+ }
1146
1230
  await factory();
1147
1231
  metrics.js.elapsed += measureElapsed(start);
1148
1232
  metrics.js.transformed++;
1149
- return;
1150
- }
1151
- const currentSource = originalEntrySource;
1152
- const precheckOptions = createHandlerOptions(path.resolve(outDir, file), {
1153
- uniAppX: resolveUniAppXJsTransformEnabled(uniAppX),
1154
- babelParserOptions: {
1155
- plugins: ["typescript"],
1156
- sourceType: "unambiguous"
1157
- }
1158
1233
  });
1159
- if (!disableJsPrecheck && shouldSkipJsTransform(currentSource, precheckOptions)) {
1160
- metrics.js.elapsed += measureElapsed(start);
1161
- metrics.js.transformed++;
1162
- return;
1163
- }
1164
- await factory();
1165
- metrics.js.elapsed += measureElapsed(start);
1166
- metrics.js.transformed++;
1167
1234
  });
1168
1235
  }
1169
1236
  }
1170
1237
  const cssRuntimeSignature = createCssRuntimeSignature(runtimeSignature, generatorCandidateSignature);
1171
1238
  if (useIncrementalMode) for (const [file, rawSource] of getRememberedMainCssSources?.() ?? []) {
1172
1239
  if (bundleFiles.includes(file) || getRememberedMainCssSignature?.(file) === cssRuntimeSignature) continue;
1173
- tasks.push((async () => {
1240
+ tasks.push(timeTask("css.replay", async () => {
1174
1241
  const start = performance.now();
1175
1242
  const cssHandlerOptions = getCssHandlerOptions(file);
1176
1243
  const generated = await generateCssByGenerator({
@@ -1181,6 +1248,7 @@ function createGenerateBundleHook(context) {
1181
1248
  file,
1182
1249
  cssHandlerOptions,
1183
1250
  cssUserHandlerOptions: getCssUserHandlerOptions(file),
1251
+ getSourceCandidatesForEntries,
1184
1252
  styleHandler,
1185
1253
  debug
1186
1254
  });
@@ -1203,14 +1271,22 @@ function createGenerateBundleHook(context) {
1203
1271
  metrics.css.transformed++;
1204
1272
  onUpdate(file, rawSource, css);
1205
1273
  debug("css replay handle: %s", file);
1206
- })());
1274
+ }));
1207
1275
  }
1208
1276
  pushConcurrentTaskFactories(tasks, jsTaskFactories);
1277
+ const tasksStart = performance.now();
1209
1278
  await Promise.all(tasks);
1279
+ recordTimingDetail("tasks", tasksStart);
1210
1280
  for (const apply of pendingLinkedUpdates) apply();
1281
+ const stateUpdateStart = performance.now();
1211
1282
  updateBundleBuildState(state, snapshot, useIncrementalMode ? linkedByEntry ?? /* @__PURE__ */ new Map() : /* @__PURE__ */ new Map(), { incremental: useIncrementalMode });
1283
+ state.generatorCandidateSignature = generatorCandidateSignature;
1284
+ recordTimingDetail("state.update", stateUpdateStart);
1212
1285
  debug("metrics iteration=%d runtime=%sms html(total=%d transform=%d hit=%d rate=%s elapsed=%sms) js(total=%d transform=%d hit=%d rate=%s elapsed=%sms) css(total=%d transform=%d hit=%d rate=%s elapsed=%sms)", useIncrementalMode ? state.iteration : 0, formatMs(metrics.runtimeSet), metrics.html.total, metrics.html.transformed, metrics.html.cacheHits, formatCacheHitRate(metrics.html), formatMs(metrics.html.elapsed), metrics.js.total, metrics.js.transformed, metrics.js.cacheHits, formatCacheHitRate(metrics.js), formatMs(metrics.js.elapsed), metrics.css.total, metrics.css.transformed, metrics.css.cacheHits, formatCacheHitRate(metrics.css), formatMs(metrics.css.elapsed));
1213
- emitHmrTiming("vite", "generateBundle", performance.now() - hmrTimingStartedAt);
1286
+ if (hmrTimingRecorder) {
1287
+ hmrTimingRecorder.record("generateBundle", performance.now() - hmrTimingStartedAt, timingDetails);
1288
+ hmrTimingRecorder.emitTotal();
1289
+ }
1214
1290
  onEnd();
1215
1291
  debug("end");
1216
1292
  };
@@ -1397,7 +1473,7 @@ function joinPosixPath(base, subpath) {
1397
1473
  }
1398
1474
  function isCssLikeImporter(importer) {
1399
1475
  if (!importer) return false;
1400
- const normalized = cleanUrl$1(importer);
1476
+ const normalized = cleanUrl(importer);
1401
1477
  return isSourceStyleRequest(importer) || isCSSRequest(normalized) || normalized.endsWith("/*");
1402
1478
  }
1403
1479
  function stripTailwindConfigDirectives(code) {
@@ -1509,7 +1585,7 @@ function createViteRuntimeClassSet(options) {
1509
1585
  if (runtimeSetPromise === task) runtimeSetPromise = void 0;
1510
1586
  }
1511
1587
  }
1512
- async function ensureBundleRuntimeClassSet(snapshot, forceRefresh = false) {
1588
+ async function ensureBundleRuntimeClassSet(snapshot, forceRefresh = false, options = {}) {
1513
1589
  const forceRuntimeRefresh = forceRefresh || process.env["WEAPP_TW_VITE_FORCE_RUNTIME_REFRESH"] === "1";
1514
1590
  const invalidation = resolveRuntimeRefreshOptions();
1515
1591
  const shouldRefreshPatcher = forceRuntimeRefresh || invalidation.changed;
@@ -1530,13 +1606,16 @@ function createViteRuntimeClassSet(options) {
1530
1606
  await bundleRuntimeClassSetManager.reset();
1531
1607
  }
1532
1608
  if (runtimeState.twPatcher.majorVersion === 3 && !forceRuntimeRefresh) try {
1533
- let baseClassSet;
1534
- if (!runtimeSet || shouldRefreshPatcher) baseClassSet = await collectRuntimeClassSet(runtimeState.twPatcher, {
1609
+ let baseClassSet = options.baseClassSet;
1610
+ if (!baseClassSet && (!runtimeSet || shouldRefreshPatcher)) baseClassSet = await collectRuntimeClassSet(runtimeState.twPatcher, {
1535
1611
  force: true,
1536
1612
  skipRefresh: shouldRefreshPatcher,
1537
1613
  clearCache: shouldRefreshPatcher
1538
1614
  });
1539
- const nextRuntimeSet = await bundleRuntimeClassSetManager.sync(runtimeState.twPatcher, snapshot, { baseClassSet });
1615
+ const nextRuntimeSet = await bundleRuntimeClassSetManager.sync(runtimeState.twPatcher, snapshot, {
1616
+ baseClassSet: baseClassSet ?? (options.allowBaselineOnlyInitialSync === true ? runtimeSet : void 0),
1617
+ skipInitialFullScanWithBase: options.allowBaselineOnlyInitialSync === true && Boolean(runtimeSet)
1618
+ });
1540
1619
  runtimeSet = nextRuntimeSet;
1541
1620
  return nextRuntimeSet;
1542
1621
  } catch (error) {
@@ -1565,374 +1644,6 @@ function createViteRuntimeClassSet(options) {
1565
1644
  };
1566
1645
  }
1567
1646
  //#endregion
1568
- //#region src/bundlers/vite/source-candidates.ts
1569
- const CLEAN_URL_RE = /[?#].*$/;
1570
- const SOURCE_CANDIDATE_EXTENSIONS = [
1571
- "js",
1572
- "jsx",
1573
- "mjs",
1574
- "cjs",
1575
- "ts",
1576
- "tsx",
1577
- "mts",
1578
- "cts",
1579
- "vue",
1580
- "uvue",
1581
- "nvue",
1582
- "svelte",
1583
- "mpx",
1584
- "html",
1585
- "wxml",
1586
- "axml",
1587
- "jxml",
1588
- "ksml",
1589
- "ttml",
1590
- "qml",
1591
- "tyml",
1592
- "xhsml",
1593
- "swan",
1594
- "css",
1595
- "wxss",
1596
- "acss",
1597
- "jxss",
1598
- "ttss",
1599
- "qss",
1600
- "tyss",
1601
- "scss",
1602
- "sass",
1603
- "less",
1604
- "styl",
1605
- "stylus"
1606
- ];
1607
- const SOURCE_CANDIDATE_EXTENSION_RE = /\.(?:[cm]?[jt]sx?|vue|uvue|nvue|svelte|mpx|html|wxml|axml|jxml|ksml|ttml|qml|tyml|xhsml|swan|css|wxss|acss|jxss|ttss|qss|tyss|scss|sass|less|stylus?)$/;
1608
- const CSS_SOURCE_CANDIDATE_EXTENSION_RE = /^(?:css|wxss|acss|jxss|ttss|qss|tyss|scss|sass|less|styl|stylus)$/;
1609
- const SOURCE_CANDIDATE_GLOB = `**/*.{${SOURCE_CANDIDATE_EXTENSIONS.join(",")}}`;
1610
- const DEFAULT_SCAN_IGNORE = ["**/node_modules/**", "**/.git/**"];
1611
- function cleanUrl(id) {
1612
- return id.replace(CLEAN_URL_RE, "");
1613
- }
1614
- function toPosixPath$1(value) {
1615
- return value.split(path.sep).join("/");
1616
- }
1617
- function resolveOutDirIgnorePattern(root, outDir) {
1618
- if (!outDir) return;
1619
- const relative = path.relative(root, path.resolve(root, outDir));
1620
- if (!relative || relative.startsWith("..") || path.isAbsolute(relative)) return;
1621
- return `${toPosixPath$1(relative)}/**`;
1622
- }
1623
- function resolveSourceCandidateExtension(id) {
1624
- const normalized = cleanUrl(id);
1625
- return /\.([^.\\/]+)$/.exec(normalized)?.[1] ?? "html";
1626
- }
1627
- function isSourceCandidateRequest(id) {
1628
- return SOURCE_CANDIDATE_EXTENSION_RE.test(cleanUrl(id));
1629
- }
1630
- function removeCandidateSet(candidateCount, candidates) {
1631
- for (const candidate of candidates) {
1632
- const count = candidateCount.get(candidate);
1633
- if (count == null) continue;
1634
- if (count <= 1) {
1635
- candidateCount.delete(candidate);
1636
- continue;
1637
- }
1638
- candidateCount.set(candidate, count - 1);
1639
- }
1640
- }
1641
- function addCandidateSet(candidateCount, candidates) {
1642
- for (const candidate of candidates) candidateCount.set(candidate, (candidateCount.get(candidate) ?? 0) + 1);
1643
- }
1644
- const CSS_APPLY_RE = /@apply\s+([^;{}]+)/g;
1645
- const CSS_APPLY_IMPORTANT = "!important";
1646
- function extractCssApplyCandidates(source) {
1647
- const candidates = /* @__PURE__ */ new Set();
1648
- CSS_APPLY_RE.lastIndex = 0;
1649
- let match = CSS_APPLY_RE.exec(source);
1650
- while (match !== null) {
1651
- const params = match[1] ?? "";
1652
- for (const candidate of splitCode(params, true)) {
1653
- const normalized = candidate.trim();
1654
- if (normalized && normalized !== CSS_APPLY_IMPORTANT) candidates.add(normalized);
1655
- }
1656
- match = CSS_APPLY_RE.exec(source);
1657
- }
1658
- return candidates;
1659
- }
1660
- function createSourceCandidateCollector() {
1661
- const candidatesById = /* @__PURE__ */ new Map();
1662
- const candidateCount = /* @__PURE__ */ new Map();
1663
- let inlineIncludedCandidates = /* @__PURE__ */ new Set();
1664
- let inlineExcludedCandidates = /* @__PURE__ */ new Set();
1665
- async function sync(id, source) {
1666
- const normalizedId = cleanUrl(id);
1667
- const extension = resolveSourceCandidateExtension(normalizedId);
1668
- const nextCandidates = /* @__PURE__ */ new Set();
1669
- if (CSS_SOURCE_CANDIDATE_EXTENSION_RE.test(extension)) for (const candidate of extractCssApplyCandidates(source)) nextCandidates.add(candidate);
1670
- else {
1671
- const matches = await extractRawCandidatesWithPositions(source, extension);
1672
- for (const match of matches) {
1673
- const candidate = match.rawCandidate;
1674
- if (typeof candidate === "string" && candidate.length > 0) nextCandidates.add(candidate);
1675
- }
1676
- }
1677
- remove(normalizedId);
1678
- if (nextCandidates.size === 0) return;
1679
- candidatesById.set(normalizedId, nextCandidates);
1680
- addCandidateSet(candidateCount, nextCandidates);
1681
- }
1682
- async function syncFile(id) {
1683
- const normalizedId = cleanUrl(id);
1684
- await sync(normalizedId, await readFile(normalizedId, "utf8"));
1685
- }
1686
- async function scanRoot({ entries, root, outDir }) {
1687
- const resolvedRoot = path.resolve(root);
1688
- const outDirIgnore = resolveOutDirIgnorePattern(resolvedRoot, outDir);
1689
- const ignore = outDirIgnore ? [...DEFAULT_SCAN_IGNORE, outDirIgnore] : DEFAULT_SCAN_IGNORE;
1690
- const files = entries ? await expandTailwindSourceEntries(entries, { ignore }) : await fg(SOURCE_CANDIDATE_GLOB, {
1691
- absolute: true,
1692
- cwd: resolvedRoot,
1693
- ignore,
1694
- onlyFiles: true,
1695
- unique: true
1696
- });
1697
- await Promise.all(files.map((file) => syncFile(file)));
1698
- }
1699
- function syncInline(inlineCandidates) {
1700
- inlineIncludedCandidates = new Set(inlineCandidates?.included ?? []);
1701
- inlineExcludedCandidates = new Set(inlineCandidates?.excluded ?? []);
1702
- }
1703
- function remove(id) {
1704
- const normalizedId = cleanUrl(id);
1705
- const previousCandidates = candidatesById.get(normalizedId);
1706
- if (!previousCandidates) return;
1707
- removeCandidateSet(candidateCount, previousCandidates);
1708
- candidatesById.delete(normalizedId);
1709
- }
1710
- function values() {
1711
- const values = new Set([...candidateCount.keys(), ...inlineIncludedCandidates]);
1712
- for (const candidate of inlineExcludedCandidates) values.delete(candidate);
1713
- return values;
1714
- }
1715
- function clear() {
1716
- candidatesById.clear();
1717
- candidateCount.clear();
1718
- inlineIncludedCandidates.clear();
1719
- inlineExcludedCandidates.clear();
1720
- }
1721
- return {
1722
- sync,
1723
- syncFile,
1724
- scanRoot,
1725
- syncInline,
1726
- remove,
1727
- values,
1728
- clear
1729
- };
1730
- }
1731
- //#endregion
1732
- //#region src/bundlers/vite/source-scan.ts
1733
- const VITE_SOURCE_CANDIDATE_PATTERN = createSourceScanPattern([
1734
- "js",
1735
- "jsx",
1736
- "mjs",
1737
- "cjs",
1738
- "ts",
1739
- "tsx",
1740
- "mts",
1741
- "cts",
1742
- "vue",
1743
- "uvue",
1744
- "nvue",
1745
- "svelte",
1746
- "mpx",
1747
- "html",
1748
- "wxml",
1749
- "axml",
1750
- "jxml",
1751
- "ksml",
1752
- "ttml",
1753
- "qml",
1754
- "tyml",
1755
- "xhsml",
1756
- "swan",
1757
- "css",
1758
- "wxss",
1759
- "acss",
1760
- "jxss",
1761
- "ttss",
1762
- "qss",
1763
- "tyss",
1764
- "scss",
1765
- "sass",
1766
- "less",
1767
- "styl",
1768
- "stylus"
1769
- ]);
1770
- function parseImportSourceParam(params) {
1771
- const match = /\bsource\(\s*(none|(['"])(.*?)\2)\s*\)/.exec(params);
1772
- if (!match) return;
1773
- return {
1774
- none: match[1] === "none",
1775
- sourcePath: match[3]
1776
- };
1777
- }
1778
- function isTailwindCssImport(params) {
1779
- return /^\s*(['"])tailwindcss(?:\/[^'"]*)?\1/.test(params);
1780
- }
1781
- function resolveSourceBase(base, sourcePath) {
1782
- return path.isAbsolute(sourcePath) ? sourcePath : path.resolve(base, sourcePath);
1783
- }
1784
- function resolveConfigPath(base, configPath) {
1785
- return path.isAbsolute(configPath) ? path.resolve(configPath) : path.resolve(base, configPath);
1786
- }
1787
- async function resolveConfigContentEntries(root, base) {
1788
- const configPaths = /* @__PURE__ */ new Set();
1789
- root.walkAtRules("config", (rule) => {
1790
- const configPath = parseConfigParam(rule.params);
1791
- if (configPath) configPaths.add(resolveConfigPath(base, configPath));
1792
- });
1793
- const entries = [];
1794
- for (const configPath of configPaths) try {
1795
- const loaded = await loadConfig({
1796
- config: configPath,
1797
- cwd: path.dirname(configPath)
1798
- });
1799
- entries.push(...normalizeLegacyContentEntries(loaded?.config.content, path.dirname(configPath)));
1800
- } catch {}
1801
- return {
1802
- dependencies: [...configPaths],
1803
- entries
1804
- };
1805
- }
1806
- async function resolveTailwindV4EntriesFromCss(css, base) {
1807
- let root;
1808
- try {
1809
- root = postcss.parse(css);
1810
- } catch {
1811
- return;
1812
- }
1813
- let importSourceBase;
1814
- let hasSourceNone = false;
1815
- const [sourceEntries, configEntries] = await Promise.all([resolveCssSourceEntries(root, base, VITE_SOURCE_CANDIDATE_PATTERN), resolveConfigContentEntries(root, base)]);
1816
- const entries = [...configEntries.entries, ...sourceEntries];
1817
- const inlineCandidates = collectCssInlineSourceCandidates(root);
1818
- root.walkAtRules("import", (rule) => {
1819
- if (!isTailwindCssImport(rule.params)) return;
1820
- const sourceParam = parseImportSourceParam(rule.params);
1821
- if (sourceParam?.none) hasSourceNone = true;
1822
- if (sourceParam?.sourcePath) importSourceBase = resolveSourceBase(base, sourceParam.sourcePath);
1823
- });
1824
- if (importSourceBase) return {
1825
- entries: [{
1826
- base: importSourceBase,
1827
- negated: false,
1828
- pattern: VITE_SOURCE_CANDIDATE_PATTERN
1829
- }, ...entries],
1830
- explicit: true,
1831
- inlineCandidates,
1832
- dependencies: configEntries.dependencies
1833
- };
1834
- if (hasSourceNone) return {
1835
- entries,
1836
- explicit: true,
1837
- inlineCandidates,
1838
- dependencies: configEntries.dependencies
1839
- };
1840
- return entries.length > 0 ? {
1841
- entries,
1842
- explicit: true,
1843
- inlineCandidates,
1844
- dependencies: configEntries.dependencies
1845
- } : inlineCandidates.included.size > 0 || inlineCandidates.excluded.size > 0 ? {
1846
- entries: [],
1847
- explicit: true,
1848
- inlineCandidates,
1849
- dependencies: configEntries.dependencies
1850
- } : void 0;
1851
- }
1852
- async function resolveViteTailwindV4CssDependencies(css, base) {
1853
- return (await resolveTailwindV4EntriesFromCss(css, base))?.dependencies ?? [];
1854
- }
1855
- function collectExistingCssEntries(options) {
1856
- return [
1857
- ...options.cssEntries ?? [],
1858
- ...options.tailwindcss?.v4?.cssEntries ?? [],
1859
- ...options.tailwindcssPatcherOptions?.tailwindcss?.v4?.cssEntries ?? []
1860
- ].filter((item) => typeof item === "string" && item.length > 0).map((item) => path.resolve(item)).filter((item) => existsSync(item));
1861
- }
1862
- function mergeInlineCandidates(allInlineCandidates) {
1863
- const merged = {
1864
- included: /* @__PURE__ */ new Set(),
1865
- excluded: /* @__PURE__ */ new Set()
1866
- };
1867
- for (const inlineCandidates of allInlineCandidates) {
1868
- if (!inlineCandidates) continue;
1869
- for (const candidate of inlineCandidates.included) if (!merged.excluded.has(candidate)) merged.included.add(candidate);
1870
- for (const candidate of inlineCandidates.excluded) {
1871
- merged.excluded.add(candidate);
1872
- merged.included.delete(candidate);
1873
- }
1874
- }
1875
- return merged.included.size > 0 || merged.excluded.size > 0 ? merged : void 0;
1876
- }
1877
- async function resolveViteSourceScanEntries(options, patcher) {
1878
- if (patcher.majorVersion === 3) {
1879
- const source = await resolveTailwindV3SourceFromPatcher(patcher);
1880
- const contentEntries = normalizeLegacyContentEntries(source.configObject?.content, source.config ? path.dirname(source.config) : source.cwd);
1881
- return contentEntries.length > 0 ? { entries: contentEntries } : void 0;
1882
- }
1883
- if (patcher.majorVersion === 4) {
1884
- const sourceOptions = resolveTailwindV4SourceOptionsFromPatcher(patcher);
1885
- const cssEntries = collectExistingCssEntries(options);
1886
- const entries = [];
1887
- const cssInlineCandidates = [];
1888
- for (const cssEntry of cssEntries) {
1889
- const resolved = await resolveTailwindV4EntriesFromCss(readFileSync(cssEntry, "utf8"), path.dirname(cssEntry));
1890
- if (resolved) {
1891
- entries.push(...resolved.entries);
1892
- cssInlineCandidates.push(resolved.inlineCandidates);
1893
- }
1894
- }
1895
- const inlineCandidates = mergeInlineCandidates(cssInlineCandidates);
1896
- if (entries.length > 0 || inlineCandidates) return {
1897
- entries,
1898
- inlineCandidates
1899
- };
1900
- if (typeof sourceOptions.css === "string" && sourceOptions.css.length > 0) {
1901
- const resolved = await resolveTailwindV4EntriesFromCss(sourceOptions.css, sourceOptions.base ?? sourceOptions.projectRoot ?? process.cwd());
1902
- return resolved ? {
1903
- entries: resolved.entries,
1904
- inlineCandidates: resolved.inlineCandidates
1905
- } : void 0;
1906
- }
1907
- const source = await resolveTailwindV4SourceFromPatcher(patcher);
1908
- const resolved = await resolveTailwindV4EntriesFromCss(source.css, source.base);
1909
- return resolved ? {
1910
- entries: resolved.entries,
1911
- inlineCandidates: resolved.inlineCandidates
1912
- } : void 0;
1913
- }
1914
- }
1915
- function toPosixPath(value) {
1916
- return value.split(path.sep).join("/");
1917
- }
1918
- function createViteSourceScanMatcher(entries) {
1919
- if (!entries?.length) return;
1920
- const positiveEntries = entries.filter((entry) => !entry.negated);
1921
- const negativeEntries = entries.filter((entry) => entry.negated);
1922
- if (positiveEntries.length === 0) return () => false;
1923
- return (file) => {
1924
- const resolvedFile = path.resolve(file);
1925
- if (!positiveEntries.some((entry) => {
1926
- const relative = toPosixPath(path.relative(path.resolve(entry.base), resolvedFile));
1927
- return relative && !relative.startsWith("../") && !path.isAbsolute(relative) && micromatch.isMatch(relative, entry.pattern);
1928
- })) return false;
1929
- return !negativeEntries.some((entry) => {
1930
- const relative = toPosixPath(path.relative(path.resolve(entry.base), resolvedFile));
1931
- return relative && !relative.startsWith("../") && !path.isAbsolute(relative) && micromatch.isMatch(relative, entry.pattern);
1932
- });
1933
- };
1934
- }
1935
- //#endregion
1936
1647
  //#region src/bundlers/vite/tailwind-basedir.ts
1937
1648
  const PACKAGE_JSON_FILE = "package.json";
1938
1649
  function resolveImplicitTailwindcssBasedirFromViteRoot(root) {
@@ -1957,6 +1668,7 @@ function resolveImplicitTailwindcssBasedirFromViteRoot(root) {
1957
1668
  const debug = createDebug();
1958
1669
  const weappTailwindcssPackageDir = resolvePackageDir("weapp-tailwindcss");
1959
1670
  const weappTailwindcssDirPosix = slash(weappTailwindcssPackageDir);
1671
+ const sourceCandidateScanSnapshotCache = /* @__PURE__ */ new Map();
1960
1672
  function normalizeSignaturePath(value) {
1961
1673
  return slash(path.resolve(value));
1962
1674
  }
@@ -1980,7 +1692,8 @@ function createSourceCandidateScanSignature(input) {
1980
1692
  roots: input.roots.map((root) => ({
1981
1693
  entries: serializeSourceEntries(root.entries),
1982
1694
  root: normalizeSignaturePath(root.root)
1983
- }))
1695
+ })),
1696
+ scanAllSources: input.scanAllSources ?? false
1984
1697
  });
1985
1698
  }
1986
1699
  /**
@@ -2008,25 +1721,53 @@ function WeappTailwindcss(options = {}) {
2008
1721
  const autoCssSourceContent = /* @__PURE__ */ new Map();
2009
1722
  let refreshRuntimeStateForAutoCssSources;
2010
1723
  let autoCssSourcesRefresh;
2011
- const registerAutoCssSource = async (id, css) => {
1724
+ let autoCssSourcesDiscovered = false;
1725
+ const registerAutoCssSource = async (id, css, options = {}) => {
2012
1726
  if (tailwindcssMajorVersion < 4 || !shouldOwnTailwindGeneration || hasInitialTailwindCssRoots) return;
2013
- const file = cleanUrl$1(id);
1727
+ const file = cleanUrl(id);
2014
1728
  if (!path.isAbsolute(file)) return;
2015
1729
  const sourceFile = path.normalize(file);
2016
1730
  const sourceCss = normalizeTailwindSourceForGenerator(css, { importFallback: true });
2017
1731
  if (autoCssSourceContent.get(sourceFile) === sourceCss) return;
2018
1732
  autoCssSourceContent.set(sourceFile, sourceCss);
2019
- upsertTailwindV4CssSource(opts, {
1733
+ const dependencies = await resolveViteTailwindV4CssDependencies(sourceCss, path.dirname(sourceFile));
1734
+ if (!upsertTailwindV4CssSource(opts, {
2020
1735
  file: sourceFile,
1736
+ base: path.dirname(sourceFile),
2021
1737
  css: sourceCss,
2022
- dependencies: await resolveViteTailwindV4CssDependencies(sourceCss, path.dirname(sourceFile))
2023
- });
1738
+ dependencies
1739
+ })) return;
1740
+ invalidateSourceCandidateScan();
2024
1741
  debug("detected tailwindcss v4 css source from vite css module: %s", sourceFile);
1742
+ if (options.refresh === false) return;
2025
1743
  autoCssSourcesRefresh = (autoCssSourcesRefresh ?? Promise.resolve()).then(async () => {
2026
1744
  await refreshRuntimeStateForAutoCssSources?.(true);
1745
+ await syncSourceCandidateScan({ force: true });
2027
1746
  });
2028
1747
  await autoCssSourcesRefresh;
2029
1748
  };
1749
+ const discoverAndRegisterAutoCssSources = async () => {
1750
+ if (tailwindcssMajorVersion < 4 || !shouldOwnTailwindGeneration || hasInitialTailwindCssRoots || !resolvedConfig?.root) return;
1751
+ const cssEntries = await discoverTailwindV4CssEntries(resolvedConfig.root, resolvedConfig.build?.outDir);
1752
+ autoCssSourcesDiscovered = true;
1753
+ let changed = false;
1754
+ for (const cssEntry of cssEntries) {
1755
+ const sourceFile = path.resolve(cssEntry);
1756
+ const sourceCss = normalizeTailwindSourceForGenerator(await readFile(sourceFile, "utf8"), { importFallback: true });
1757
+ if (autoCssSourceContent.get(sourceFile) === sourceCss) continue;
1758
+ autoCssSourceContent.set(sourceFile, sourceCss);
1759
+ const resolved = await resolveTailwindV4EntriesFromCssCached(sourceCss, path.dirname(sourceFile));
1760
+ changed = upsertTailwindV4CssSource(opts, {
1761
+ file: sourceFile,
1762
+ base: path.dirname(sourceFile),
1763
+ css: sourceCss,
1764
+ dependencies: resolved?.dependencies ?? []
1765
+ }) || changed;
1766
+ }
1767
+ if (!changed) return;
1768
+ invalidateSourceCandidateScan();
1769
+ await refreshRuntimeStateForAutoCssSources?.(true);
1770
+ };
2030
1771
  const rewritePlugins = createRewriteCssImportsPlugins({
2031
1772
  getAppType: () => opts.appType,
2032
1773
  rootImport: shouldOwnTailwindGeneration ? `${weappTailwindcssDirPosix}/generator-placeholder.css` : void 0,
@@ -2040,10 +1781,15 @@ function WeappTailwindcss(options = {}) {
2040
1781
  let resolvedConfig;
2041
1782
  let recordedGeneratorCandidates;
2042
1783
  const sourceCandidateCollector = createSourceCandidateCollector();
1784
+ const sourceCandidateScanCache = /* @__PURE__ */ new Map();
2043
1785
  let sourceScanEntries;
2044
1786
  let sourceScanMatcher;
1787
+ let sourceScanDependencies = /* @__PURE__ */ new Set();
1788
+ let sourceScanExplicit = false;
2045
1789
  let sourceCandidateScanSignature;
1790
+ let sourceCandidateScanInvalidated = true;
2046
1791
  const pendingSourceCandidateSyncs = /* @__PURE__ */ new Set();
1792
+ const pendingSourceCandidateSyncByFile = /* @__PURE__ */ new Map();
2047
1793
  const processedCssAssets = /* @__PURE__ */ new WeakSet();
2048
1794
  const processedCssAssetFiles = /* @__PURE__ */ new Set();
2049
1795
  const rememberedMainCssSources = /* @__PURE__ */ new Map();
@@ -2057,6 +1803,7 @@ function WeappTailwindcss(options = {}) {
2057
1803
  disabledDefaultTemplateHandler,
2058
1804
  debug
2059
1805
  });
1806
+ const hmrTimingRecorder = createHmrTimingRecorder("vite");
2060
1807
  refreshRuntimeStateForAutoCssSources = refreshRuntimeState;
2061
1808
  onLoad();
2062
1809
  const getResolvedConfig = () => resolvedConfig;
@@ -2072,8 +1819,21 @@ function WeappTailwindcss(options = {}) {
2072
1819
  };
2073
1820
  const getRecordedGeneratorCandidates = () => recordedGeneratorCandidates;
2074
1821
  const getSourceCandidates = () => sourceCandidateCollector.values();
1822
+ const getSourceCandidatesForEntries = (entries) => sourceCandidateCollector.valuesForEntries(entries);
2075
1823
  const isWatchBuild = () => resolvedConfig?.command === "build" && resolvedConfig.build.watch != null;
1824
+ const isWatchLikeBuild = () => isWatchBuild() || resolvedConfig?.command === "serve" || process.env["WEAPP_TW_WATCH_REGRESSION"] === "1" || process.env["WEAPP_TW_HMR_TIMING"] === "1";
1825
+ const hasSourceCandidateScanState = () => sourceCandidateScanSignature !== void 0;
1826
+ const normalizeSourceScanDependency = (file) => path.normalize(path.resolve(cleanUrl(file)));
1827
+ const isSourceScanDependency = (file) => sourceScanDependencies.has(normalizeSourceScanDependency(file));
1828
+ const invalidateSourceCandidateScan = () => {
1829
+ sourceCandidateScanInvalidated = true;
1830
+ };
2076
1831
  const collectSourceCandidateScanRoots = (root, entries) => {
1832
+ if (entries?.length) return [{
1833
+ entries,
1834
+ root
1835
+ }];
1836
+ if (sourceScanExplicit) return [];
2077
1837
  const roots = [{
2078
1838
  entries,
2079
1839
  root
@@ -2100,24 +1860,100 @@ function WeappTailwindcss(options = {}) {
2100
1860
  outDir
2101
1861
  })));
2102
1862
  };
1863
+ const cacheCurrentSourceCandidateScan = () => {
1864
+ if (sourceCandidateScanSignature) {
1865
+ sourceCandidateScanCache.set(sourceCandidateScanSignature, sourceCandidateCollector.snapshot());
1866
+ sourceCandidateScanSnapshotCache.set(sourceCandidateScanSignature, sourceCandidateCollector.snapshot());
1867
+ }
1868
+ };
1869
+ const shouldDiscoverAutoCssSources = () => {
1870
+ if (!autoCssSourcesDiscovered) return true;
1871
+ if (!isWatchLikeBuild()) return true;
1872
+ return sourceCandidateScanInvalidated;
1873
+ };
1874
+ async function syncSourceCandidateScan(options = {}) {
1875
+ if (!shouldOwnTailwindGeneration) return;
1876
+ if (!options.force && isWatchLikeBuild() && hasSourceCandidateScanState() && !sourceCandidateScanInvalidated) {
1877
+ debug("reuse vite source candidate scan definition for watch rebuild");
1878
+ return;
1879
+ }
1880
+ const root = resolvedConfig?.root ?? process.cwd();
1881
+ const outDir = resolvedConfig?.build?.outDir;
1882
+ const sourceScan = await resolveViteSourceScanEntries(opts, runtimeState.twPatcher, {
1883
+ outDir,
1884
+ root
1885
+ });
1886
+ sourceScanEntries = sourceScan?.entries;
1887
+ sourceScanExplicit = sourceScan?.explicit ?? false;
1888
+ sourceScanMatcher = createViteSourceScanMatcher(sourceScanEntries);
1889
+ sourceScanDependencies = new Set((sourceScan?.dependencies ?? []).map(normalizeSourceScanDependency));
1890
+ const roots = collectSourceCandidateScanRoots(root, sourceScanEntries);
1891
+ const nextScanSignature = createSourceCandidateScanSignature({
1892
+ inlineCandidates: sourceScan?.inlineCandidates,
1893
+ outDir,
1894
+ roots,
1895
+ scanAllSources: !sourceScanExplicit
1896
+ });
1897
+ if (hasSourceCandidateScanState() && sourceCandidateScanSignature === nextScanSignature) {
1898
+ sourceCandidateCollector.syncInline(sourceScan?.inlineCandidates);
1899
+ sourceCandidateScanCache.set(nextScanSignature, sourceCandidateCollector.snapshot());
1900
+ debug("reuse vite source candidate scan for watch rebuild");
1901
+ sourceCandidateScanInvalidated = false;
1902
+ return;
1903
+ }
1904
+ const cachedScan = isWatchLikeBuild() ? sourceCandidateScanCache.get(nextScanSignature) ?? sourceCandidateScanSnapshotCache.get(nextScanSignature) : void 0;
1905
+ if (cachedScan) {
1906
+ sourceCandidateCollector.restore(cachedScan);
1907
+ sourceCandidateScanSignature = nextScanSignature;
1908
+ debug("reuse cached vite source candidate scan for watch rebuild");
1909
+ sourceCandidateScanInvalidated = false;
1910
+ return;
1911
+ }
1912
+ sourceCandidateCollector.clear();
1913
+ sourceCandidateCollector.syncInline(sourceScan?.inlineCandidates);
1914
+ await scanSourceCandidateRoots(roots, outDir);
1915
+ sourceCandidateScanSignature = nextScanSignature;
1916
+ sourceCandidateScanInvalidated = false;
1917
+ if (isWatchLikeBuild()) {
1918
+ sourceCandidateScanCache.set(nextScanSignature, sourceCandidateCollector.snapshot());
1919
+ sourceCandidateScanSnapshotCache.set(nextScanSignature, sourceCandidateCollector.snapshot());
1920
+ }
1921
+ }
2103
1922
  const waitForSourceCandidateSyncs = async () => {
2104
1923
  while (pendingSourceCandidateSyncs.size > 0) await Promise.all(pendingSourceCandidateSyncs);
2105
1924
  };
2106
1925
  const syncChangedSourceCandidateFile = (id) => {
2107
1926
  if (!shouldOwnTailwindGeneration || !isSourceCandidateRequest(id)) return Promise.resolve();
2108
- const file = cleanUrl$1(id);
1927
+ const file = cleanUrl(id);
1928
+ if (isSourceScanDependency(file)) invalidateSourceCandidateScan();
2109
1929
  if (sourceScanMatcher && !sourceScanMatcher(file)) {
2110
1930
  sourceCandidateCollector.remove(file);
1931
+ cacheCurrentSourceCandidateScan();
2111
1932
  return Promise.resolve();
2112
1933
  }
1934
+ if (sourceScanExplicit && sourceScanEntries?.length === 0) {
1935
+ cacheCurrentSourceCandidateScan();
1936
+ return Promise.resolve();
1937
+ }
1938
+ const existingTask = pendingSourceCandidateSyncByFile.get(file);
1939
+ if (existingTask) return existingTask;
2113
1940
  const task = sourceCandidateCollector.syncFile(id).catch((error) => {
2114
1941
  debug("source candidate watch sync failed: %s %O", id, error);
1942
+ }).then(() => {
1943
+ cacheCurrentSourceCandidateScan();
2115
1944
  }).finally(() => {
2116
1945
  pendingSourceCandidateSyncs.delete(task);
1946
+ pendingSourceCandidateSyncByFile.delete(file);
2117
1947
  });
2118
1948
  pendingSourceCandidateSyncs.add(task);
1949
+ pendingSourceCandidateSyncByFile.set(file, task);
2119
1950
  return task;
2120
1951
  };
1952
+ const shouldCollectTransformedSourceCandidates = (id) => {
1953
+ if (id.search(/[?#]/) < 0) return true;
1954
+ const file = cleanUrl(id);
1955
+ return !/\.(?:vue|uvue|nvue|svelte|mpx)$/i.test(file);
1956
+ };
2121
1957
  const rememberMainCssSource = (file, rawSource, cssRuntimeSignature) => {
2122
1958
  rememberedMainCssSources.set(file, rawSource);
2123
1959
  if (cssRuntimeSignature) rememberedMainCssSignatureByFile.set(file, cssRuntimeSignature);
@@ -2136,12 +1972,14 @@ function WeappTailwindcss(options = {}) {
2136
1972
  getResolvedConfig,
2137
1973
  markCssAssetProcessed,
2138
1974
  getSourceCandidates,
1975
+ getSourceCandidatesForEntries,
2139
1976
  waitForSourceCandidateSyncs,
2140
1977
  rememberMainCssSource,
2141
1978
  getRememberedMainCssSources,
2142
1979
  getRememberedMainCssSignature,
2143
1980
  setRememberedMainCssSignature,
2144
- recordGeneratorCandidates
1981
+ recordGeneratorCandidates,
1982
+ hmrTimingRecorder
2145
1983
  });
2146
1984
  const cssFinalizerOutputPlugin = createViteCssFinalizerOutputPlugin({
2147
1985
  opts,
@@ -2153,6 +1991,7 @@ function WeappTailwindcss(options = {}) {
2153
1991
  isCssAssetProcessed,
2154
1992
  getRecordedGeneratorCandidates,
2155
1993
  getSourceCandidates,
1994
+ getSourceCandidatesForEntries,
2156
1995
  waitForSourceCandidateSyncs,
2157
1996
  rememberMainCssSource
2158
1997
  });
@@ -2176,46 +2015,43 @@ function WeappTailwindcss(options = {}) {
2176
2015
  name: `${vitePluginName}:source-candidates`,
2177
2016
  enforce: "pre",
2178
2017
  async transform(code, id) {
2179
- if (!shouldOwnTailwindGeneration || !isSourceCandidateRequest(id)) return;
2180
- const file = cleanUrl$1(id);
2181
- if (sourceScanMatcher && !sourceScanMatcher(file)) {
2182
- sourceCandidateCollector.remove(file);
2183
- return;
2184
- }
2185
- await sourceCandidateCollector.sync(id, code);
2018
+ if (!shouldOwnTailwindGeneration || !isSourceCandidateRequest(id) || !shouldCollectTransformedSourceCandidates(id)) return;
2019
+ return hmrTimingRecorder.measure("sourceCandidates.transform", async () => {
2020
+ const file = cleanUrl(id);
2021
+ if (sourceScanMatcher && !sourceScanMatcher(file)) {
2022
+ sourceCandidateCollector.remove(file);
2023
+ cacheCurrentSourceCandidateScan();
2024
+ return;
2025
+ }
2026
+ if (sourceScanExplicit && sourceScanEntries?.length === 0) {
2027
+ cacheCurrentSourceCandidateScan();
2028
+ return;
2029
+ }
2030
+ await sourceCandidateCollector.merge(id, code);
2031
+ cacheCurrentSourceCandidateScan();
2032
+ }, { emit: false });
2186
2033
  },
2187
2034
  async watchChange(id, change) {
2188
- if (change.event === "delete") {
2189
- sourceCandidateCollector.remove(id);
2190
- return;
2191
- }
2192
- await syncChangedSourceCandidateFile(id);
2035
+ await hmrTimingRecorder.measure("sourceCandidates.watchChange", async () => {
2036
+ if (isSourceScanDependency(id)) invalidateSourceCandidateScan();
2037
+ if (change.event === "delete") {
2038
+ sourceCandidateCollector.remove(id);
2039
+ cacheCurrentSourceCandidateScan();
2040
+ return;
2041
+ }
2042
+ await syncChangedSourceCandidateFile(id);
2043
+ }, { emit: false });
2193
2044
  },
2194
2045
  async handleHotUpdate(ctx) {
2195
- await syncChangedSourceCandidateFile(ctx.file);
2046
+ await hmrTimingRecorder.measure("sourceCandidates.handleHotUpdate", async () => {
2047
+ await syncChangedSourceCandidateFile(ctx.file);
2048
+ }, { emit: false });
2196
2049
  },
2197
2050
  async buildStart() {
2198
- if (!shouldOwnTailwindGeneration) return;
2199
- const root = resolvedConfig?.root ?? process.cwd();
2200
- const outDir = resolvedConfig?.build?.outDir;
2201
- const sourceScan = await resolveViteSourceScanEntries(opts, runtimeState.twPatcher);
2202
- sourceScanEntries = sourceScan?.entries;
2203
- sourceScanMatcher = createViteSourceScanMatcher(sourceScanEntries);
2204
- const roots = collectSourceCandidateScanRoots(root, sourceScanEntries);
2205
- const nextScanSignature = createSourceCandidateScanSignature({
2206
- inlineCandidates: sourceScan?.inlineCandidates,
2207
- outDir,
2208
- roots
2209
- });
2210
- if (isWatchBuild() && sourceCandidateScanSignature === nextScanSignature) {
2211
- sourceCandidateCollector.syncInline(sourceScan?.inlineCandidates);
2212
- debug("reuse vite source candidate scan for watch rebuild");
2213
- return;
2214
- }
2215
- sourceCandidateCollector.clear();
2216
- sourceCandidateCollector.syncInline(sourceScan?.inlineCandidates);
2217
- await scanSourceCandidateRoots(roots, outDir);
2218
- sourceCandidateScanSignature = nextScanSignature;
2051
+ await hmrTimingRecorder.measure("sourceCandidates.buildStart", async () => {
2052
+ if (shouldDiscoverAutoCssSources()) await discoverAndRegisterAutoCssSources();
2053
+ await syncSourceCandidateScan();
2054
+ }, { emit: false });
2219
2055
  }
2220
2056
  },
2221
2057
  {
@@ -2246,45 +2082,47 @@ function WeappTailwindcss(options = {}) {
2246
2082
  });
2247
2083
  },
2248
2084
  async configResolved(config) {
2249
- resolvedConfig = config;
2250
- if (shouldOwnTailwindGeneration) {
2251
- const removed = Array.isArray(config.plugins) ? removeTailwindVitePlugins(config.plugins) : 0;
2252
- if (removed > 0) debug("remove official tailwind vite plugins in generator mode: %d", removed);
2253
- }
2254
- const resolvedRoot = config.root ? path.resolve(config.root) : void 0;
2255
- let shouldRefreshRuntime = false;
2256
- if (!hasExplicitTailwindcssBasedir && resolvedRoot) {
2257
- const nextTailwindcssBasedir = resolveImplicitTailwindcssBasedirFromViteRoot(resolvedRoot);
2258
- if (opts.tailwindcssBasedir !== nextTailwindcssBasedir) {
2259
- const previousBasedir = opts.tailwindcssBasedir;
2260
- opts.tailwindcssBasedir = nextTailwindcssBasedir;
2261
- debug("align tailwindcss basedir with vite root: %s -> %s", previousBasedir ?? "undefined", nextTailwindcssBasedir);
2262
- shouldRefreshRuntime = true;
2085
+ await hmrTimingRecorder.measure("configResolved", async () => {
2086
+ resolvedConfig = config;
2087
+ if (shouldOwnTailwindGeneration) {
2088
+ const removed = Array.isArray(config.plugins) ? removeTailwindVitePlugins(config.plugins) : 0;
2089
+ if (removed > 0) debug("remove official tailwind vite plugins in generator mode: %d", removed);
2263
2090
  }
2264
- }
2265
- if (!hasExplicitAppType && resolvedRoot) {
2266
- const nextAppType = resolveImplicitAppTypeFromViteRoot(resolvedRoot);
2267
- if (nextAppType && opts.appType !== nextAppType) {
2268
- const previousAppType = opts.appType;
2269
- opts.appType = nextAppType;
2270
- logger.info("根据 Vite 项目根目录自动推断 appType -> %s", nextAppType);
2271
- debug("align appType with vite root: %s -> %s", previousAppType ?? "undefined", nextAppType);
2272
- shouldRefreshRuntime = true;
2091
+ const resolvedRoot = config.root ? path.resolve(config.root) : void 0;
2092
+ let shouldRefreshRuntime = false;
2093
+ if (!hasExplicitTailwindcssBasedir && resolvedRoot) {
2094
+ const nextTailwindcssBasedir = resolveImplicitTailwindcssBasedirFromViteRoot(resolvedRoot);
2095
+ if (opts.tailwindcssBasedir !== nextTailwindcssBasedir) {
2096
+ const previousBasedir = opts.tailwindcssBasedir;
2097
+ opts.tailwindcssBasedir = nextTailwindcssBasedir;
2098
+ debug("align tailwindcss basedir with vite root: %s -> %s", previousBasedir ?? "undefined", nextTailwindcssBasedir);
2099
+ shouldRefreshRuntime = true;
2100
+ }
2273
2101
  }
2274
- }
2275
- if (shouldRefreshRuntime) await refreshRuntimeState(true);
2276
- if (typeof config.css.postcss === "object" && Array.isArray(config.css.postcss.plugins)) {
2277
- const postcssPlugins = config.css.postcss.plugins;
2278
- if (shouldOwnTailwindGeneration) {
2279
- const removed = removeTailwindPostcssPlugins(postcssPlugins);
2280
- if (removed > 0) debug("remove official tailwind postcss plugins in generator mode: %d", removed);
2102
+ if (!hasExplicitAppType && resolvedRoot) {
2103
+ const nextAppType = resolveImplicitAppTypeFromViteRoot(resolvedRoot);
2104
+ if (nextAppType && opts.appType !== nextAppType) {
2105
+ const previousAppType = opts.appType;
2106
+ opts.appType = nextAppType;
2107
+ logger.info("根据 Vite 项目根目录自动推断 appType -> %s", nextAppType);
2108
+ debug("align appType with vite root: %s -> %s", previousAppType ?? "undefined", nextAppType);
2109
+ shouldRefreshRuntime = true;
2110
+ }
2281
2111
  }
2282
- const idx = postcssPlugins.findIndex((x) => getPostcssPluginName(x) === "postcss-html-transform");
2283
- if (idx > -1) {
2284
- postcssPlugins.splice(idx, 1, postcssHtmlTransform());
2285
- debug("remove postcss-html-transform plugin from vite config");
2112
+ if (shouldRefreshRuntime) await refreshRuntimeState(true);
2113
+ if (typeof config.css.postcss === "object" && Array.isArray(config.css.postcss.plugins)) {
2114
+ const postcssPlugins = config.css.postcss.plugins;
2115
+ if (shouldOwnTailwindGeneration) {
2116
+ const removed = removeTailwindPostcssPlugins(postcssPlugins);
2117
+ if (removed > 0) debug("remove official tailwind postcss plugins in generator mode: %d", removed);
2118
+ }
2119
+ const idx = postcssPlugins.findIndex((x) => getPostcssPluginName(x) === "postcss-html-transform");
2120
+ if (idx > -1) {
2121
+ postcssPlugins.splice(idx, 1, postcssHtmlTransform());
2122
+ debug("remove postcss-html-transform plugin from vite config");
2123
+ }
2286
2124
  }
2287
- }
2125
+ }, { emit: false });
2288
2126
  },
2289
2127
  generateBundle: {
2290
2128
  order: "post",