weapp-tailwindcss 4.9.8 → 4.10.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/dist/{chunk-N75TUIFJ.mjs → chunk-3B2AYJZI.mjs} +450 -66
  2. package/dist/{chunk-M27GDCY2.mjs → chunk-3PHGTNEG.mjs} +37 -1
  3. package/dist/{chunk-PO3CCFU7.js → chunk-3RGU475C.js} +4 -4
  4. package/dist/{chunk-Z545JGD6.js → chunk-BGS7BPOO.js} +65 -38
  5. package/dist/{chunk-HAM3JEU2.js → chunk-DBAAU4LK.js} +1 -1
  6. package/dist/{chunk-BJWGT5OD.js → chunk-G6EL4MDW.js} +5 -5
  7. package/dist/{chunk-47TVJCQM.mjs → chunk-HT76VHOV.mjs} +1 -1
  8. package/dist/{chunk-DOX3RXJ2.js → chunk-IIDSY4XZ.js} +2 -2
  9. package/dist/{chunk-YJDEI6WM.js → chunk-ISBBDWDL.js} +470 -86
  10. package/dist/{chunk-RGMNU44M.mjs → chunk-J3SZZ2LI.mjs} +44 -17
  11. package/dist/{chunk-OW5UKXZU.js → chunk-JGS26JXK.js} +42 -6
  12. package/dist/{chunk-WJVKUHYW.js → chunk-LMFYBTHK.js} +16 -13
  13. package/dist/{chunk-CKEQFURT.mjs → chunk-MFIMWE7C.mjs} +13 -10
  14. package/dist/{chunk-W3JRVMJD.mjs → chunk-P5UFIGA6.mjs} +1 -1
  15. package/dist/{chunk-EAD4D7DF.js → chunk-QR6PZEH5.js} +211 -84
  16. package/dist/{chunk-77PO4QLM.mjs → chunk-RQPZ5Q2B.mjs} +151 -24
  17. package/dist/cli.js +39 -39
  18. package/dist/cli.mjs +2 -2
  19. package/dist/core.js +29 -22
  20. package/dist/core.mjs +28 -21
  21. package/dist/css-macro/postcss.js +1 -1
  22. package/dist/css-macro/postcss.mjs +1 -1
  23. package/dist/css-macro.js +1 -1
  24. package/dist/css-macro.mjs +1 -1
  25. package/dist/defaults.js +1 -1
  26. package/dist/defaults.mjs +1 -1
  27. package/dist/gulp.js +6 -6
  28. package/dist/gulp.mjs +4 -4
  29. package/dist/index.js +10 -10
  30. package/dist/index.mjs +7 -7
  31. package/dist/postcss-html-transform.js +1 -1
  32. package/dist/postcss-html-transform.mjs +1 -1
  33. package/dist/presets.js +5 -5
  34. package/dist/presets.mjs +1 -1
  35. package/dist/reset.js +1 -1
  36. package/dist/reset.mjs +1 -1
  37. package/dist/types.d.mts +5 -0
  38. package/dist/types.d.ts +5 -0
  39. package/dist/types.js +1 -1
  40. package/dist/types.mjs +1 -1
  41. package/dist/vite.js +7 -7
  42. package/dist/vite.mjs +4 -4
  43. package/dist/webpack.js +8 -8
  44. package/dist/webpack.mjs +5 -5
  45. package/dist/webpack4.js +63 -41
  46. package/dist/webpack4.mjs +40 -18
  47. package/package.json +10 -6
@@ -12,20 +12,20 @@ import {
12
12
  } from "./chunk-RRHPTTCP.mjs";
13
13
  import {
14
14
  setupPatchRecorder
15
- } from "./chunk-W3JRVMJD.mjs";
15
+ } from "./chunk-P5UFIGA6.mjs";
16
16
  import {
17
17
  collectRuntimeClassSet,
18
18
  createAttributeMatcher,
19
19
  createDebug,
20
20
  generateCode,
21
21
  getCompilerContext,
22
+ getRuntimeClassSetSignature,
22
23
  refreshTailwindRuntimeState,
23
24
  replaceWxml,
24
25
  toCustomAttributesEntities,
25
26
  vitePluginName
26
- } from "./chunk-77PO4QLM.mjs";
27
+ } from "./chunk-RQPZ5Q2B.mjs";
27
28
  import {
28
- getGroupedEntries,
29
29
  resolveUniUtsPlatform
30
30
  } from "./chunk-OOHJLO5M.mjs";
31
31
 
@@ -352,6 +352,7 @@ function createUniAppXAssetTask(file, originalSource, outDir, options) {
352
352
  return async () => {
353
353
  const {
354
354
  cache,
355
+ hashKey,
355
356
  createHandlerOptions,
356
357
  debug: debug2,
357
358
  jsHandler,
@@ -361,10 +362,13 @@ function createUniAppXAssetTask(file, originalSource, outDir, options) {
361
362
  } = options;
362
363
  const absoluteFile = toAbsoluteOutputPath(file, outDir);
363
364
  const rawSource = originalSource.source.toString();
365
+ const rawHashSource = options.hashSalt ? `${rawSource}
366
+ /*${options.hashSalt}*/` : rawSource;
364
367
  await processCachedTask({
365
368
  cache,
366
369
  cacheKey: file,
367
- rawSource,
370
+ hashKey,
371
+ rawSource: rawHashSource,
368
372
  applyResult(source) {
369
373
  originalSource.source = source;
370
374
  },
@@ -465,8 +469,210 @@ function applyLinkedResults(linked, entries, onLinkedUpdate, onApplied) {
465
469
  }
466
470
  }
467
471
 
472
+ // src/bundlers/vite/js-precheck.ts
473
+ var FAST_JS_TRANSFORM_HINT_RE = /className\b|class\s*=|classList\.|\b(?:twMerge|clsx|classnames|cn|cva)\b|\[["'`]class["'`]\]|text-\[|bg-\[|\b(?:[whpm]|px|py|mx|my|rounded|flex|grid|gap)-/;
474
+ var DEPENDENCY_HINT_RE = /\bimport\s*[("'`{*]|\brequire\s*\(|\bexport\s+\*\s+from\s+["'`]|\bexport\s*\{[^}]*\}\s*from\s+["'`]/;
475
+ function shouldSkipViteJsTransform(rawSource, options) {
476
+ if (!rawSource) {
477
+ return true;
478
+ }
479
+ if (options?.alwaysEscape) {
480
+ return false;
481
+ }
482
+ if (options?.moduleSpecifierReplacements && Object.keys(options.moduleSpecifierReplacements).length > 0) {
483
+ return false;
484
+ }
485
+ if (options?.wrapExpression) {
486
+ return false;
487
+ }
488
+ if (DEPENDENCY_HINT_RE.test(rawSource)) {
489
+ return false;
490
+ }
491
+ return !FAST_JS_TRANSFORM_HINT_RE.test(rawSource);
492
+ }
493
+
468
494
  // src/bundlers/vite/generate-bundle.ts
495
+ function createEmptyMetric() {
496
+ return {
497
+ total: 0,
498
+ transformed: 0,
499
+ cacheHits: 0,
500
+ elapsed: 0
501
+ };
502
+ }
503
+ function createEmptyMetrics() {
504
+ return {
505
+ runtimeSet: 0,
506
+ html: createEmptyMetric(),
507
+ js: createEmptyMetric(),
508
+ css: createEmptyMetric()
509
+ };
510
+ }
511
+ function classifyEntry(file, opts) {
512
+ if (opts.cssMatcher(file)) {
513
+ return "css";
514
+ }
515
+ if (opts.htmlMatcher(file)) {
516
+ return "html";
517
+ }
518
+ if (opts.jsMatcher(file) || opts.wxsMatcher(file)) {
519
+ return "js";
520
+ }
521
+ return "other";
522
+ }
523
+ function readEntrySource(output) {
524
+ if (output.type === "chunk") {
525
+ return output.code;
526
+ }
527
+ return output.source.toString();
528
+ }
529
+ function toJsAbsoluteFilename(file, outDir) {
530
+ return toAbsoluteOutputPath(file, outDir);
531
+ }
532
+ function computeDirtyEntries(entries, opts, state) {
533
+ const nextSourceHashByFile = /* @__PURE__ */ new Map();
534
+ const changedByType = {
535
+ html: /* @__PURE__ */ new Set(),
536
+ js: /* @__PURE__ */ new Set(),
537
+ css: /* @__PURE__ */ new Set(),
538
+ other: /* @__PURE__ */ new Set()
539
+ };
540
+ for (const [file, output] of entries) {
541
+ const type = classifyEntry(file, opts);
542
+ const source = readEntrySource(output);
543
+ const hash = opts.cache.computeHash(source);
544
+ nextSourceHashByFile.set(file, hash);
545
+ const previousHash = state.previousSourceHashByFile.get(file);
546
+ if (previousHash == null || previousHash !== hash) {
547
+ changedByType[type].add(file);
548
+ }
549
+ }
550
+ return {
551
+ sourceHashByFile: nextSourceHashByFile,
552
+ changedByType
553
+ };
554
+ }
555
+ function buildProcessSets(entries, opts, changedByType, previousLinkedByEntry, forceAll = false) {
556
+ const processFiles = {
557
+ html: /* @__PURE__ */ new Set(),
558
+ js: /* @__PURE__ */ new Set(),
559
+ css: /* @__PURE__ */ new Set()
560
+ };
561
+ const linkedImpactsByEntry = /* @__PURE__ */ new Map();
562
+ if (forceAll) {
563
+ for (const [file] of entries) {
564
+ const type = classifyEntry(file, opts);
565
+ if (type === "html" || type === "js" || type === "css") {
566
+ processFiles[type].add(file);
567
+ }
568
+ }
569
+ return {
570
+ files: processFiles,
571
+ linkedImpactsByEntry
572
+ };
573
+ }
574
+ const firstRun = previousLinkedByEntry.size === 0;
575
+ if (firstRun) {
576
+ for (const [file] of entries) {
577
+ const type = classifyEntry(file, opts);
578
+ if (type === "html" || type === "js" || type === "css") {
579
+ processFiles[type].add(file);
580
+ }
581
+ }
582
+ return {
583
+ files: processFiles,
584
+ linkedImpactsByEntry
585
+ };
586
+ }
587
+ for (const file of changedByType.html) {
588
+ processFiles.html.add(file);
589
+ }
590
+ for (const file of changedByType.css) {
591
+ processFiles.css.add(file);
592
+ }
593
+ for (const file of changedByType.js) {
594
+ processFiles.js.add(file);
595
+ }
596
+ for (const changedFile of changedByType.js) {
597
+ for (const [entryFile, linkedFiles] of previousLinkedByEntry.entries()) {
598
+ if (linkedFiles.has(changedFile)) {
599
+ processFiles.js.add(entryFile);
600
+ let impacts = linkedImpactsByEntry.get(entryFile);
601
+ if (!impacts) {
602
+ impacts = /* @__PURE__ */ new Set();
603
+ linkedImpactsByEntry.set(entryFile, impacts);
604
+ }
605
+ impacts.add(changedFile);
606
+ }
607
+ }
608
+ }
609
+ return {
610
+ files: processFiles,
611
+ linkedImpactsByEntry
612
+ };
613
+ }
614
+ function measureElapsed(start) {
615
+ return performance.now() - start;
616
+ }
617
+ function formatCacheHitRate(metric) {
618
+ if (metric.total === 0) {
619
+ return "0.00%";
620
+ }
621
+ return `${(metric.cacheHits / metric.total * 100).toFixed(2)}%`;
622
+ }
623
+ function formatMs(value) {
624
+ return value.toFixed(2);
625
+ }
626
+ function summarizeStringDiff(previous, next) {
627
+ if (previous === next) {
628
+ return "same";
629
+ }
630
+ const previousLength = previous.length;
631
+ const nextLength = next.length;
632
+ const minLength = Math.min(previousLength, nextLength);
633
+ let prefixLength = 0;
634
+ while (prefixLength < minLength && previous.charCodeAt(prefixLength) === next.charCodeAt(prefixLength)) {
635
+ prefixLength += 1;
636
+ }
637
+ let previousSuffixCursor = previousLength - 1;
638
+ let nextSuffixCursor = nextLength - 1;
639
+ while (previousSuffixCursor >= prefixLength && nextSuffixCursor >= prefixLength && previous.charCodeAt(previousSuffixCursor) === next.charCodeAt(nextSuffixCursor)) {
640
+ previousSuffixCursor -= 1;
641
+ nextSuffixCursor -= 1;
642
+ }
643
+ const previousChangedLength = previousSuffixCursor >= prefixLength ? previousSuffixCursor - prefixLength + 1 : 0;
644
+ const nextChangedLength = nextSuffixCursor >= prefixLength ? nextSuffixCursor - prefixLength + 1 : 0;
645
+ return `changed@${prefixLength} old=${previousChangedLength} new=${nextChangedLength} len=${previousLength}->${nextLength}`;
646
+ }
647
+ function createLinkedImpactSignature(entry, linkedImpactsByEntry, sourceHashByFile) {
648
+ const changedLinkedFiles = linkedImpactsByEntry.get(entry);
649
+ if (!changedLinkedFiles || changedLinkedFiles.size === 0) {
650
+ return void 0;
651
+ }
652
+ const parts = [...changedLinkedFiles].sort().map((file) => {
653
+ const hash = sourceHashByFile.get(file) ?? "missing";
654
+ return `${file}:${hash}`;
655
+ });
656
+ return parts.join(",");
657
+ }
658
+ function createJsHashSalt(runtimeSignature, linkedImpactSignature) {
659
+ if (!linkedImpactSignature) {
660
+ return runtimeSignature;
661
+ }
662
+ return `${runtimeSignature}:linked:${linkedImpactSignature}`;
663
+ }
469
664
  function createGenerateBundleHook(context) {
665
+ const state = {
666
+ iteration: 0,
667
+ previousSourceHashByFile: /* @__PURE__ */ new Map(),
668
+ previousLinkedByEntry: /* @__PURE__ */ new Map(),
669
+ changedByType: {
670
+ html: /* @__PURE__ */ new Set(),
671
+ js: /* @__PURE__ */ new Set(),
672
+ css: /* @__PURE__ */ new Set(),
673
+ other: /* @__PURE__ */ new Set()
674
+ }
675
+ };
470
676
  return async function generateBundle(_opt, bundle) {
471
677
  const {
472
678
  opts,
@@ -490,7 +696,15 @@ function createGenerateBundleHook(context) {
490
696
  await runtimeState.patchPromise;
491
697
  debug2("start");
492
698
  onStart();
699
+ const metrics = createEmptyMetrics();
700
+ const forceRuntimeRefresh = process2.env.WEAPP_TW_VITE_FORCE_RUNTIME_REFRESH === "1";
701
+ const disableDirtyOptimization = process2.env.WEAPP_TW_VITE_DISABLE_DIRTY === "1";
702
+ const disableJsPrecheck = process2.env.WEAPP_TW_VITE_DISABLE_JS_PRECHECK === "1";
703
+ const debugCssDiff = process2.env.WEAPP_TW_VITE_DEBUG_CSS_DIFF === "1";
493
704
  const entries = Object.entries(bundle);
705
+ const dirtyEntries = computeDirtyEntries(entries, opts, state);
706
+ const processSets = buildProcessSets(entries, opts, dirtyEntries.changedByType, state.previousLinkedByEntry, disableDirtyOptimization);
707
+ const processFiles = processSets.files;
494
708
  const resolvedConfig = getResolvedConfig();
495
709
  const rootDir = resolvedConfig?.root ? path2.resolve(resolvedConfig.root) : process2.cwd();
496
710
  const outDir = resolvedConfig?.build?.outDir ? path2.resolve(rootDir, resolvedConfig.build.outDir) : rootDir;
@@ -498,14 +712,16 @@ function createGenerateBundleHook(context) {
498
712
  for (const [fileName, output] of entries) {
499
713
  const entry = { fileName, output };
500
714
  if (isJavaScriptEntry(entry)) {
501
- const absolute = toAbsoluteOutputPath(fileName, outDir);
715
+ const absolute = toJsAbsoluteFilename(fileName, outDir);
502
716
  jsEntries.set(absolute, entry);
503
717
  }
504
718
  }
505
719
  const moduleGraphOptions = createBundleModuleGraphOptions(outDir, jsEntries);
506
- const groupedEntries = getGroupedEntries(entries, opts);
507
- const runtime = await ensureRuntimeClassSet(true);
720
+ const runtimeStart = performance.now();
721
+ const runtime = await ensureRuntimeClassSet(forceRuntimeRefresh);
722
+ metrics.runtimeSet = measureElapsed(runtimeStart);
508
723
  debug2("get runtimeSet, class count: %d", runtime.size);
724
+ const runtimeSignature = getRuntimeClassSetSignature(runtimeState.twPatcher) ?? "runtime:missing";
509
725
  const handleLinkedUpdate = (fileName, previous, next) => {
510
726
  onUpdate(fileName, previous, next);
511
727
  debug2("js linked handle: %s", fileName);
@@ -532,25 +748,37 @@ function createGenerateBundleHook(context) {
532
748
  sourceFilename: absoluteFilename
533
749
  }
534
750
  });
751
+ const linkedByEntry = /* @__PURE__ */ new Map();
535
752
  const tasks = [];
536
- if (Array.isArray(groupedEntries.html)) {
537
- for (const [file, originalSource] of groupedEntries.html) {
753
+ const jsTaskFactories = [];
754
+ for (const [file, originalSource] of entries) {
755
+ const type = classifyEntry(file, opts);
756
+ if (type === "html" && originalSource.type === "asset") {
757
+ metrics.html.total++;
758
+ if (!processFiles.html.has(file)) {
759
+ continue;
760
+ }
538
761
  const rawSource = originalSource.source.toString();
539
762
  tasks.push(
540
763
  processCachedTask({
541
764
  cache,
542
765
  cacheKey: file,
543
766
  rawSource,
767
+ hashKey: `${file}:html:${runtimeSignature}`,
544
768
  applyResult(source) {
545
769
  originalSource.source = source;
546
770
  },
547
771
  onCacheHit() {
772
+ metrics.html.cacheHits++;
548
773
  debug2("html cache hit: %s", file);
549
774
  },
550
775
  async transform() {
776
+ const start = performance.now();
551
777
  const transformed = await templateHandler(rawSource, {
552
778
  runtimeSet: runtime
553
779
  });
780
+ metrics.html.elapsed += measureElapsed(start);
781
+ metrics.html.transformed++;
554
782
  onUpdate(file, rawSource, transformed);
555
783
  debug2("html handle: %s", file);
556
784
  return {
@@ -559,73 +787,29 @@ function createGenerateBundleHook(context) {
559
787
  }
560
788
  })
561
789
  );
790
+ continue;
562
791
  }
563
- }
564
- const jsTaskFactories = [];
565
- if (Array.isArray(groupedEntries.js)) {
566
- for (const [file, originalSource] of groupedEntries.js) {
567
- if (originalSource.type === "chunk") {
568
- const absoluteFile = toAbsoluteOutputPath(file, outDir);
569
- const initialRawSource = originalSource.code;
570
- jsTaskFactories.push(async () => {
571
- await processCachedTask({
572
- cache,
573
- cacheKey: file,
574
- rawSource: initialRawSource,
575
- applyResult(source) {
576
- originalSource.code = source;
577
- },
578
- onCacheHit() {
579
- debug2("js cache hit: %s", file);
580
- },
581
- async transform() {
582
- const rawSource = originalSource.code;
583
- const { code, linked } = await jsHandler(rawSource, runtime, createHandlerOptions(absoluteFile));
584
- onUpdate(file, rawSource, code);
585
- debug2("js handle: %s", file);
586
- applyLinkedUpdates(linked);
587
- return {
588
- result: code
589
- };
590
- }
591
- });
592
- });
593
- } else if (uniAppX && originalSource.type === "asset") {
594
- jsTaskFactories.push(
595
- createUniAppXAssetTask(
596
- file,
597
- originalSource,
598
- outDir,
599
- {
600
- cache,
601
- createHandlerOptions,
602
- debug: debug2,
603
- jsHandler,
604
- onUpdate,
605
- runtimeSet: runtime,
606
- applyLinkedResults: applyLinkedUpdates,
607
- uniAppX
608
- }
609
- )
610
- );
792
+ if (type === "css" && originalSource.type === "asset") {
793
+ metrics.css.total++;
794
+ if (!processFiles.css.has(file)) {
795
+ continue;
611
796
  }
612
- }
613
- }
614
- if (Array.isArray(groupedEntries.css)) {
615
- for (const [file, originalSource] of groupedEntries.css) {
616
797
  const rawSource = originalSource.source.toString();
617
798
  tasks.push(
618
799
  processCachedTask({
619
800
  cache,
620
801
  cacheKey: file,
621
802
  rawSource,
803
+ hashKey: `${file}:css:${runtimeSignature}:${runtimeState.twPatcher.majorVersion ?? "unknown"}`,
622
804
  applyResult(source) {
623
805
  originalSource.source = source;
624
806
  },
625
807
  onCacheHit() {
808
+ metrics.css.cacheHits++;
626
809
  debug2("css cache hit: %s", file);
627
810
  },
628
811
  async transform() {
812
+ const start = performance.now();
629
813
  await runtimeState.patchPromise;
630
814
  const { css } = await styleHandler(rawSource, {
631
815
  isMainChunk: mainCssChunkMatcher(originalSource.fileName, appType),
@@ -636,6 +820,11 @@ function createGenerateBundleHook(context) {
636
820
  },
637
821
  majorVersion: runtimeState.twPatcher.majorVersion
638
822
  });
823
+ if (debugCssDiff) {
824
+ debug2("css diff %s: %s", file, summarizeStringDiff(rawSource, css));
825
+ }
826
+ metrics.css.elapsed += measureElapsed(start);
827
+ metrics.css.transformed++;
639
828
  onUpdate(file, rawSource, css);
640
829
  debug2("css handle: %s", file);
641
830
  return {
@@ -644,6 +833,130 @@ function createGenerateBundleHook(context) {
644
833
  }
645
834
  })
646
835
  );
836
+ continue;
837
+ }
838
+ if (type !== "js") {
839
+ continue;
840
+ }
841
+ metrics.js.total++;
842
+ if (!processFiles.js.has(file)) {
843
+ continue;
844
+ }
845
+ if (originalSource.type === "chunk") {
846
+ const absoluteFile = toJsAbsoluteFilename(file, outDir);
847
+ const initialRawSource = originalSource.code;
848
+ const linkedSet = /* @__PURE__ */ new Set();
849
+ linkedByEntry.set(file, linkedSet);
850
+ jsTaskFactories.push(async () => {
851
+ const linkedImpactSignature = createLinkedImpactSignature(
852
+ file,
853
+ processSets.linkedImpactsByEntry,
854
+ dirtyEntries.sourceHashByFile
855
+ );
856
+ const hashSalt = createJsHashSalt(runtimeSignature, linkedImpactSignature);
857
+ await processCachedTask({
858
+ cache,
859
+ cacheKey: file,
860
+ hashKey: `${file}:js`,
861
+ rawSource: `${initialRawSource}
862
+ /*${hashSalt}*/`,
863
+ applyResult(source) {
864
+ originalSource.code = source;
865
+ },
866
+ onCacheHit() {
867
+ metrics.js.cacheHits++;
868
+ debug2("js cache hit: %s", file);
869
+ },
870
+ async transform() {
871
+ const start = performance.now();
872
+ const rawSource = originalSource.code;
873
+ const handlerOptions = createHandlerOptions(absoluteFile);
874
+ if (!disableJsPrecheck && shouldSkipViteJsTransform(rawSource, handlerOptions)) {
875
+ metrics.js.elapsed += measureElapsed(start);
876
+ metrics.js.transformed++;
877
+ return {
878
+ result: rawSource
879
+ };
880
+ }
881
+ const { code, linked } = await jsHandler(rawSource, runtime, handlerOptions);
882
+ metrics.js.elapsed += measureElapsed(start);
883
+ metrics.js.transformed++;
884
+ onUpdate(file, rawSource, code);
885
+ debug2("js handle: %s", file);
886
+ if (linked) {
887
+ for (const id of Object.keys(linked)) {
888
+ const linkedEntry = jsEntries.get(id);
889
+ if (linkedEntry) {
890
+ linkedSet.add(linkedEntry.fileName);
891
+ }
892
+ }
893
+ }
894
+ applyLinkedUpdates(linked);
895
+ return {
896
+ result: code
897
+ };
898
+ }
899
+ });
900
+ });
901
+ } else if (uniAppX && originalSource.type === "asset") {
902
+ const linkedSet = /* @__PURE__ */ new Set();
903
+ linkedByEntry.set(file, linkedSet);
904
+ const baseApplyLinkedUpdates = applyLinkedUpdates;
905
+ const wrappedApplyLinkedUpdates = (linked) => {
906
+ if (linked) {
907
+ for (const id of Object.keys(linked)) {
908
+ const linkedEntry = jsEntries.get(id);
909
+ if (linkedEntry) {
910
+ linkedSet.add(linkedEntry.fileName);
911
+ }
912
+ }
913
+ }
914
+ baseApplyLinkedUpdates(linked);
915
+ };
916
+ const factory = createUniAppXAssetTask(
917
+ file,
918
+ originalSource,
919
+ outDir,
920
+ {
921
+ cache,
922
+ hashKey: `${file}:js`,
923
+ hashSalt: createJsHashSalt(
924
+ runtimeSignature,
925
+ createLinkedImpactSignature(
926
+ file,
927
+ processSets.linkedImpactsByEntry,
928
+ dirtyEntries.sourceHashByFile
929
+ )
930
+ ),
931
+ createHandlerOptions,
932
+ debug: debug2,
933
+ jsHandler,
934
+ onUpdate,
935
+ runtimeSet: runtime,
936
+ applyLinkedResults: wrappedApplyLinkedUpdates,
937
+ uniAppX
938
+ }
939
+ );
940
+ jsTaskFactories.push(async () => {
941
+ const start = performance.now();
942
+ const currentSource = originalSource.source.toString();
943
+ const absoluteFile = toJsAbsoluteFilename(file, outDir);
944
+ const precheckOptions = createHandlerOptions(absoluteFile, {
945
+ uniAppX: uniAppX ?? true,
946
+ babelParserOptions: {
947
+ plugins: ["typescript"],
948
+ sourceType: "unambiguous"
949
+ }
950
+ });
951
+ if (!disableJsPrecheck && shouldSkipViteJsTransform(currentSource, precheckOptions)) {
952
+ metrics.js.elapsed += measureElapsed(start);
953
+ metrics.js.transformed++;
954
+ return;
955
+ }
956
+ await factory();
957
+ metrics.js.elapsed += measureElapsed(start);
958
+ metrics.js.transformed++;
959
+ });
647
960
  }
648
961
  }
649
962
  pushConcurrentTaskFactories(tasks, jsTaskFactories);
@@ -651,6 +964,44 @@ function createGenerateBundleHook(context) {
651
964
  for (const apply of pendingLinkedUpdates) {
652
965
  apply();
653
966
  }
967
+ state.iteration += 1;
968
+ const finalSourceHashByFile = /* @__PURE__ */ new Map();
969
+ for (const [fileName, output] of entries) {
970
+ finalSourceHashByFile.set(fileName, opts.cache.computeHash(readEntrySource(output)));
971
+ }
972
+ state.previousSourceHashByFile = finalSourceHashByFile;
973
+ state.changedByType = dirtyEntries.changedByType;
974
+ const nextLinkedByEntry = new Map(state.previousLinkedByEntry);
975
+ for (const [entryFile, linkedFiles] of linkedByEntry.entries()) {
976
+ nextLinkedByEntry.set(entryFile, linkedFiles);
977
+ }
978
+ for (const entryFile of [...nextLinkedByEntry.keys()]) {
979
+ const exists = entries.some(([fileName]) => fileName === entryFile);
980
+ if (!exists) {
981
+ nextLinkedByEntry.delete(entryFile);
982
+ }
983
+ }
984
+ state.previousLinkedByEntry = nextLinkedByEntry;
985
+ debug2(
986
+ "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)",
987
+ state.iteration,
988
+ formatMs(metrics.runtimeSet),
989
+ metrics.html.total,
990
+ metrics.html.transformed,
991
+ metrics.html.cacheHits,
992
+ formatCacheHitRate(metrics.html),
993
+ formatMs(metrics.html.elapsed),
994
+ metrics.js.total,
995
+ metrics.js.transformed,
996
+ metrics.js.cacheHits,
997
+ formatCacheHitRate(metrics.js),
998
+ formatMs(metrics.js.elapsed),
999
+ metrics.css.total,
1000
+ metrics.css.transformed,
1001
+ metrics.css.cacheHits,
1002
+ formatCacheHitRate(metrics.css),
1003
+ formatMs(metrics.css.elapsed)
1004
+ );
654
1005
  onEnd();
655
1006
  debug2("end");
656
1007
  };
@@ -763,23 +1114,56 @@ function UnifiedViteWeappTailwindcssPlugin(options = {}) {
763
1114
  let runtimeSet;
764
1115
  let runtimeSetPromise;
765
1116
  let resolvedConfig;
1117
+ let runtimeRefreshSignature;
1118
+ let runtimeRefreshOptionsKey;
1119
+ function resolveRuntimeRefreshOptions() {
1120
+ const configPath = runtimeState.twPatcher.options?.tailwind?.config;
1121
+ const signature = getRuntimeClassSetSignature(runtimeState.twPatcher);
1122
+ const optionsKey = JSON.stringify({
1123
+ appType,
1124
+ uniAppX: Boolean(uniAppX),
1125
+ customAttributesEntities,
1126
+ disabledDefaultTemplateHandler,
1127
+ configPath,
1128
+ rewriteCssImports: shouldRewriteCssImports
1129
+ });
1130
+ const changed = signature !== runtimeRefreshSignature || optionsKey !== runtimeRefreshOptionsKey;
1131
+ runtimeRefreshSignature = signature;
1132
+ runtimeRefreshOptionsKey = optionsKey;
1133
+ return {
1134
+ changed,
1135
+ signature,
1136
+ optionsKey
1137
+ };
1138
+ }
766
1139
  async function refreshRuntimeState(force) {
767
- const refreshed = await refreshTailwindRuntimeState(runtimeState, force);
1140
+ const invalidation = resolveRuntimeRefreshOptions();
1141
+ const shouldRefresh = force || invalidation.changed;
1142
+ const refreshed = await refreshTailwindRuntimeState(runtimeState, {
1143
+ force: shouldRefresh,
1144
+ clearCache: force || invalidation.changed
1145
+ });
1146
+ if (invalidation.changed) {
1147
+ debug("runtime signature changed, refresh triggered. signature: %s", invalidation.signature);
1148
+ }
768
1149
  if (refreshed) {
769
1150
  runtimeSet = void 0;
770
1151
  runtimeSetPromise = void 0;
771
1152
  }
772
1153
  }
773
1154
  async function ensureRuntimeClassSet(force = false) {
1155
+ const forceRuntimeRefresh = force || process3.env.WEAPP_TW_VITE_FORCE_RUNTIME_REFRESH === "1";
774
1156
  await refreshRuntimeState(force);
775
1157
  await runtimeState.patchPromise;
776
- if (!force && runtimeSet) {
1158
+ if (!forceRuntimeRefresh && runtimeSet) {
777
1159
  return runtimeSet;
778
1160
  }
779
- if (force || !runtimeSetPromise) {
1161
+ if (forceRuntimeRefresh || !runtimeSetPromise) {
1162
+ const invalidation = resolveRuntimeRefreshOptions();
780
1163
  const task2 = collectRuntimeClassSet(runtimeState.twPatcher, {
781
- force: force || !runtimeSet,
782
- skipRefresh: force
1164
+ force: forceRuntimeRefresh || invalidation.changed,
1165
+ skipRefresh: forceRuntimeRefresh,
1166
+ clearCache: forceRuntimeRefresh || invalidation.changed
783
1167
  });
784
1168
  runtimeSetPromise = task2;
785
1169
  }