Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/slick-bears-sleep.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"weapp-tailwindcss": patch
---

修复 uni-app x H5 中已进入构建图但未命中显式 Tailwind 正向源码范围的页面,暗色等 variant 任意值类无法生成和同步转译的问题。
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { ScanSourceCandidateRootOptions, SourceCandidateCollectorOptions, SourceCandidateCollectorSnapshot, SourceCandidateFilterOptions, SourceCandidateStore } from './types-and-cache'
import type { TailwindInlineSourceCandidates, TailwindSourceEntry } from '@/tailwindcss/source-scan'
import { readFile } from 'node:fs/promises'
import { isFileMatchedByTailwindSourceEntries, resolveSourceScanPath } from '@/tailwindcss/source-scan'
import { isFileExcludedByTailwindSourceEntries, isFileMatchedByTailwindSourceEntries, resolveSourceScanPath } from '@/tailwindcss/source-scan'
import { resolveSourceCandidateScanFiles } from './scan-root'
import { addCandidateSet, cleanUrl, createSourceCandidateContentCacheKey, diffCandidateSets, extractCandidates, isSourceCandidateRequest, removeCandidateSet, resolveSourceCandidateExtension, sourceCandidateContentCache } from './types-and-cache'

Expand All @@ -10,9 +10,11 @@ export function createSourceCandidateStore(options: SourceCandidateCollectorOpti
const scanCandidatesById = new Map<string, Set<string>>()
const transformCandidatesById = new Map<string, Set<string>>()
const cssCandidatesById = new Map<string, Set<string>>()
const moduleCandidatesById = new Map<string, Set<string>>()
const scanSourceById = new Map<string, string>()
const transformSourceById = new Map<string, string>()
const cssSourceById = new Map<string, string>()
const moduleSourceById = new Map<string, string>()
const candidateCount = new Map<string, number>()
let inlineIncludedCandidates = new Set<string>()
let inlineExcludedCandidates = new Set<string>()
Expand Down Expand Up @@ -66,6 +68,15 @@ export function createSourceCandidateStore(options: SourceCandidateCollectorOpti
replaceCssLayer(normalizedId, await resolveCandidates(source, 'css'))
}

async function syncModuleSource(id: string, source: string) {
const normalizedId = cleanUrl(id)
moduleSourceById.set(normalizedId, source)
const extension = resolveSourceCandidateExtension(normalizedId)
const candidates = await resolveCandidates(source, extension)
replaceModuleLayer(normalizedId, candidates)
return new Set(candidates)
}

async function merge(id: string, source: string) {
const normalizedId = cleanUrl(id)
transformSourceById.set(normalizedId, source)
Expand Down Expand Up @@ -104,8 +115,10 @@ export function createSourceCandidateStore(options: SourceCandidateCollectorOpti
if (extension !== 'css') {
transformCandidatesById.delete(normalizedId)
cssCandidatesById.delete(normalizedId)
moduleCandidatesById.delete(normalizedId)
transformSourceById.delete(normalizedId)
cssSourceById.delete(normalizedId)
moduleSourceById.delete(normalizedId)
}
scanSourceById.set(normalizedId, source)
replaceScanLayer(normalizedId, nextCandidates)
Expand Down Expand Up @@ -196,12 +209,24 @@ export function createSourceCandidateStore(options: SourceCandidateCollectorOpti
recompute(normalizedId)
}

function replaceModuleLayer(id: string, nextCandidates: Set<string>) {
const normalizedId = cleanUrl(id)
if (nextCandidates.size === 0) {
moduleCandidatesById.delete(normalizedId)
}
else {
moduleCandidatesById.set(normalizedId, nextCandidates)
}
recompute(normalizedId)
}

function recompute(id: string) {
const normalizedId = cleanUrl(id)
const nextCandidates = new Set([
...(scanCandidatesById.get(normalizedId) ?? []),
...(transformCandidatesById.get(normalizedId) ?? []),
...(cssCandidatesById.get(normalizedId) ?? []),
...(moduleCandidatesById.get(normalizedId) ?? []),
])
replaceFinal(normalizedId, nextCandidates)
}
Expand All @@ -218,9 +243,11 @@ export function createSourceCandidateStore(options: SourceCandidateCollectorOpti
scanCandidatesById.delete(normalizedId)
transformCandidatesById.delete(normalizedId)
cssCandidatesById.delete(normalizedId)
moduleCandidatesById.delete(normalizedId)
scanSourceById.delete(normalizedId)
transformSourceById.delete(normalizedId)
cssSourceById.delete(normalizedId)
moduleSourceById.delete(normalizedId)
const previousCandidates = candidatesById.get(normalizedId)
if (!previousCandidates) {
return diffCandidateSets(previousVisibleCandidates, new Set())
Expand All @@ -238,6 +265,7 @@ export function createSourceCandidateStore(options: SourceCandidateCollectorOpti
return scanSourceById.get(normalizedId)
?? cssSourceById.get(normalizedId)
?? transformSourceById.get(normalizedId)
?? moduleSourceById.get(normalizedId)
}

function sources() {
Expand All @@ -261,12 +289,12 @@ export function createSourceCandidateStore(options: SourceCandidateCollectorOpti
return values()
}
}
if (entries?.length === 0) {
return new Set(inlineIncludedCandidates)
}
const filtered = new Set<string>()
for (const [id, candidates] of candidatesById) {
if (entries !== undefined && !isFileMatchedByTailwindSourceEntries(id, entries)) {
const isActiveModule = moduleCandidatesById.has(id)
if (entries !== undefined && (isActiveModule
? isFileExcludedByTailwindSourceEntries(id, entries)
: entries.length === 0 || !isFileMatchedByTailwindSourceEntries(id, entries))) {
continue
}
if (options.excludeEntries?.length && isFileMatchedByTailwindSourceEntries(id, options.excludeEntries)) {
Expand Down Expand Up @@ -298,18 +326,11 @@ export function createSourceCandidateStore(options: SourceCandidateCollectorOpti
}
}

if (entries?.length === 0) {
for (const candidate of inlineIncludedCandidates) {
addCandidateSource(candidate, undefined)
}
for (const candidate of inlineExcludedCandidates) {
sources.delete(candidate)
}
return sources
}

for (const [id, candidates] of candidatesById) {
if (entries !== undefined && !isFileMatchedByTailwindSourceEntries(id, entries)) {
const isActiveModule = moduleCandidatesById.has(id)
if (entries !== undefined && (isActiveModule
? isFileExcludedByTailwindSourceEntries(id, entries)
: entries.length === 0 || !isFileMatchedByTailwindSourceEntries(id, entries))) {
continue
}
if (options.excludeEntries?.length && isFileMatchedByTailwindSourceEntries(id, options.excludeEntries)) {
Expand All @@ -333,9 +354,11 @@ export function createSourceCandidateStore(options: SourceCandidateCollectorOpti
scanCandidatesById.clear()
transformCandidatesById.clear()
cssCandidatesById.clear()
moduleCandidatesById.clear()
scanSourceById.clear()
transformSourceById.clear()
cssSourceById.clear()
moduleSourceById.clear()
candidateCount.clear()
inlineIncludedCandidates.clear()
inlineExcludedCandidates.clear()
Expand All @@ -360,6 +383,8 @@ export function createSourceCandidateStore(options: SourceCandidateCollectorOpti
candidatesById: [...candidatesById.entries()].map(([id, candidates]) => [id, [...candidates]]),
cssCandidatesById: [...cssCandidatesById.entries()].map(([id, candidates]) => [id, [...candidates]]),
cssSourceById: [...cssSourceById.entries()],
moduleCandidatesById: [...moduleCandidatesById.entries()].map(([id, candidates]) => [id, [...candidates]]),
moduleSourceById: [...moduleSourceById.entries()],
scanCandidatesById: [...scanCandidatesById.entries()].map(([id, candidates]) => [id, [...candidates]]),
scanSourceById: [...scanSourceById.entries()],
sourceById: [...mergeSourcesByPriority().entries()],
Expand Down Expand Up @@ -396,6 +421,13 @@ export function createSourceCandidateStore(options: SourceCandidateCollectorOpti
}
cssCandidatesById.set(id, candidateSet)
}
for (const [id, candidates] of snapshot.moduleCandidatesById ?? []) {
const candidateSet = new Set(candidates)
if (candidateSet.size === 0) {
continue
}
moduleCandidatesById.set(id, candidateSet)
}
for (const [id, source] of snapshot.scanSourceById ?? snapshot.sourceById ?? []) {
scanSourceById.set(id, source)
}
Expand All @@ -405,10 +437,14 @@ export function createSourceCandidateStore(options: SourceCandidateCollectorOpti
for (const [id, source] of snapshot.cssSourceById ?? []) {
cssSourceById.set(id, source)
}
for (const [id, source] of snapshot.moduleSourceById ?? []) {
moduleSourceById.set(id, source)
}
const ids = new Set([
...scanCandidatesById.keys(),
...transformCandidatesById.keys(),
...cssCandidatesById.keys(),
...moduleCandidatesById.keys(),
])
for (const id of ids) {
recompute(id)
Expand All @@ -419,6 +455,7 @@ export function createSourceCandidateStore(options: SourceCandidateCollectorOpti
syncSource: sync,
sync,
syncCss,
syncModuleSource,
merge,
syncFile,
syncCurrentSource,
Expand All @@ -441,6 +478,9 @@ export function createSourceCandidateStore(options: SourceCandidateCollectorOpti

function mergeSourcesByPriority() {
const sources = new Map<string, string>()
for (const [id, source] of moduleSourceById) {
sources.set(id, source)
}
for (const [id, source] of transformSourceById) {
sources.set(id, source)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export interface SourceCandidateStore {
syncSource: (id: string, source: string) => Promise<void>
sync: (id: string, source: string) => Promise<void>
syncCss: (id: string, source: string) => Promise<void>
syncModuleSource: (id: string, source: string) => Promise<Set<string>>
merge: (id: string, source: string) => Promise<void>
syncFile: (id: string) => Promise<void>
syncCurrentSource: (id: string, source: string) => Promise<SourceCandidateChange>
Expand Down Expand Up @@ -41,6 +42,8 @@ export interface SourceCandidateCollectorSnapshot {
candidatesById: Array<[string, string[]]>
cssCandidatesById?: Array<[string, string[]]> | undefined
cssSourceById?: Array<[string, string]> | undefined
moduleCandidatesById?: Array<[string, string[]]> | undefined
moduleSourceById?: Array<[string, string]> | undefined
scanCandidatesById?: Array<[string, string[]]> | undefined
scanSourceById?: Array<[string, string]> | undefined
sourceById?: Array<[string, string]> | undefined
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ export function createUniAppXVitePlugins(options: UserDefinedOptions | InternalU
isWebGeneratorTarget: context.isWebGeneratorTarget,
jsHandler: context.jsHandler,
mainCssChunkMatcher: context.mainCssChunkMatcher,
registerModuleGraphCandidates: context.registerModuleGraphCandidates,
runtimeState: context.runtimeState,
styleHandler: context.styleHandler,
syncSourceCandidatesForHotUpdate: context.syncSourceCandidatesForHotUpdate,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ import { shouldAdaptFrameworkWatchCssBeforeCache, wrapViteCssPostTransform } fro
import { resolveWeappViteSourceRoot } from '../weapp-vite-config'
import { resolveViteWebCssCompatOptions, shouldApplyViteWebCssCompat } from '../web-css-compat'
import { createViteHmrCandidateState } from './framework-hmr-candidate-state'
import { createFrameworkModuleCandidateRegistrar } from './framework-module-candidates'
import { orderFrameworkSourceCandidatePlugins } from './framework-plugin-order'
import { createFrameworkPostPlugin } from './framework-post-plugin'
import { createFrameworkProcessedCssRegistry } from './framework-processed-css-registry'
Expand Down Expand Up @@ -416,14 +417,13 @@ ${tracedCss}`
const shouldSplitGenerateBundlePhases = () => opts.appType === 'weapp-vite' && getResolvedConfig()?.mode !== 'production'; const preGenerateBundleHook = createGenerateBundleHook({ ...generateBundleContext, processMarkupAndScripts: false, shouldProcessBundle: shouldSplitGenerateBundlePhases })
const generateBundleHook = createGenerateBundleHook({ ...generateBundleContext, ...createGenericWebProductionBundleHooks({ frameworkName: frameworkBranch.frameworkName, getHasProcessedCss: () => processedCssRegistry.getStats().viteProcessedCssAssetResults > 0, getIsWebGeneratorTarget: () => resolveCurrentGeneratorBranch().isWeb, getResolvedConfig, onEnd: opts.onEnd, onStart: opts.onStart }), shouldProcessStyles: () => !shouldSplitGenerateBundlePhases() })
const cssFinalizerOutputPlugin = createViteCssFinalizerOutputPlugin({ opts, runtimeState, ensureRuntimeClassSet, cssPipelineStrategy: frameworkCssPipelineStrategy, debug, frameworkName: frameworkBranch.frameworkName, getResolvedConfig, hmrTimingRecorder, markCssAssetProcessed, isCssAssetProcessed, isViteProcessedCssAsset, resolveCssAssetIdentity, recordCssAssetResult, recordViteProcessedCssAssetResult, getViteProcessedCssAssetResults, getRecordedGeneratorCandidates, getSourceCandidates, getSourceCandidatesForEntries, getSourceCandidateSourcesForEntries, waitForSourceCandidateSyncs: sourceScanSession.waitForPendingSyncs, frameworkRootImportShellTargetByFile, rememberMainCssSource: (file, rawSource) => cssMemory.rememberCssSource({ outputFile: file, rawSource, sourceFile: file }), getRememberedMainCssSource: cssMemory.getRememberedCssSourceEntry })
const extraPluginPlatform = frameworkBranch.getExtraPluginPlatform?.() ?? {}
const syncSourceCandidatesForHotUpdate = ctx => syncFrameworkSourceCandidatesForHotUpdate(sourceScanSession, ctx)
const extraPluginPlatform = frameworkBranch.getExtraPluginPlatform?.() ?? {}; const syncSourceCandidatesForHotUpdate = ctx => syncFrameworkSourceCandidatesForHotUpdate(sourceScanSession, ctx); const registerModuleGraphCandidates = createFrameworkModuleCandidateRegistrar({ cacheCurrent: sourceScanSession.cacheCurrent, debug, getCssHandlerOptions: transformCssHandlerOptions.getCssHandlerOptions, getGeneratorPlatform: resolveGeneratorPlatform, invalidateRecordedGeneratorCandidates, opts, runtimeState, sourceCandidateCollector, styleHandler })
const prepareTailwindGeneration = async () => {
if (sourceScanSession.shouldDiscoverAutoCssSources(autoCssSourcesDiscovered)) {
await discoverAndRegisterAutoCssSources()
} await sourceScanSession.sync()
}
const extraPlugins = frameworkBranch.createExtraPlugins?.({ customAttributesEntities, disabledDefaultTemplateHandler, ensureRuntimeClassSet, generateCss: generateTailwindCssForVitePipeline, getResolvedConfig, isEnabled: shouldEnableFrameworkExtraPlugins, isIosPlatform: extraPluginPlatform.isIosPlatform === true, isNativeAppStyleTarget: () => frameworkCssPipelineStrategy?.isNativeAppStyleTarget?.(createCssPipelineContext()) === true, isWebGeneratorTarget: () => resolveCurrentGeneratorBranch().isWeb, jsHandler, mainCssChunkMatcher, runtimeState, styleHandler, syncSourceCandidatesForHotUpdate, tailwindRootCssModuleIds, uniAppX, viteProcessedCssSourceFiles: processedCssRegistry.sourceFiles }) ?? []
const extraPlugins = frameworkBranch.createExtraPlugins?.({ customAttributesEntities, disabledDefaultTemplateHandler, ensureRuntimeClassSet, generateCss: generateTailwindCssForVitePipeline, getResolvedConfig, isEnabled: shouldEnableFrameworkExtraPlugins, isIosPlatform: extraPluginPlatform.isIosPlatform === true, isNativeAppStyleTarget: () => frameworkCssPipelineStrategy?.isNativeAppStyleTarget?.(createCssPipelineContext()) === true, isWebGeneratorTarget: () => resolveCurrentGeneratorBranch().isWeb, jsHandler, mainCssChunkMatcher, registerModuleGraphCandidates, runtimeState, styleHandler, syncSourceCandidatesForHotUpdate, tailwindRootCssModuleIds, uniAppX, viteProcessedCssSourceFiles: processedCssRegistry.sourceFiles }) ?? []
const installFrameworkWatchCssCacheAdapter = async (config) => {
if (!shouldAdaptFrameworkWatchCss()) {
return
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ export interface ViteFrameworkExtraPluginContext {
isWebGeneratorTarget: () => boolean
jsHandler: ReturnType<typeof getCompilerContext>['jsHandler']
mainCssChunkMatcher: ReturnType<typeof getCompilerContext>['mainCssChunkMatcher']
registerModuleGraphCandidates: (id: string, source: string) => Promise<Set<string>>
runtimeState: ReturnType<typeof createViteRuntimeClassSet>['runtimeState']
styleHandler: ReturnType<typeof getCompilerContext>['styleHandler']
syncSourceCandidatesForHotUpdate: (ctx: HmrContext) => Promise<void>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import type { ValidateCandidatesByGeneratorOptions } from '@/bundlers/shared/generator-css'
import type { SourceCandidateStore } from '@/bundlers/shared/source-candidates/types-and-cache'
import { validateCandidatesByGenerator } from '@/bundlers/shared/generator-css'
import { cleanUrl } from '../utils'

interface FrameworkModuleCandidateRegistrarOptions {
cacheCurrent: () => void
debug: ValidateCandidatesByGeneratorOptions['debug']
getCssHandlerOptions: (id: string) => ValidateCandidatesByGeneratorOptions['cssHandlerOptions']
getGeneratorPlatform: () => ValidateCandidatesByGeneratorOptions['generatorPlatform']
invalidateRecordedGeneratorCandidates: () => void
opts: ValidateCandidatesByGeneratorOptions['opts']
runtimeState: ValidateCandidatesByGeneratorOptions['runtimeState']
sourceCandidateCollector: Pick<SourceCandidateStore, 'syncModuleSource'>
styleHandler: ValidateCandidatesByGeneratorOptions['styleHandler']
}

export function createFrameworkModuleCandidateRegistrar(options: FrameworkModuleCandidateRegistrarOptions) {
return async (id: string, source: string) => {
await options.runtimeState.readyPromise
const candidates = await options.sourceCandidateCollector.syncModuleSource(id, source)
options.invalidateRecordedGeneratorCandidates()
options.cacheCurrent()
const cssHandlerOptions = options.getCssHandlerOptions(id)
return validateCandidatesByGenerator({
candidates,
cssHandlerOptions,
cssUserHandlerOptions: cssHandlerOptions,
debug: options.debug,
file: cleanUrl(id),
generatorPlatform: options.getGeneratorPlatform(),
opts: options.opts,
rawSource: '',
runtimeState: options.runtimeState,
styleHandler: options.styleHandler,
})
}
}
13 changes: 10 additions & 3 deletions packages/weapp-tailwindcss/src/uni-app-x/vite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ export function createUniAppXPlugins(options: CreateUniAppXPluginsOptions): Plug
disabledDefaultTemplateHandler,
isIosPlatform: providedIosPlatform,
mainCssChunkMatcher,
registerModuleGraphCandidates,
runtimeState,
styleHandler,
syncSourceCandidatesForHotUpdate,
Expand Down Expand Up @@ -266,13 +267,19 @@ export function createUniAppXPlugins(options: CreateUniAppXPluginsOptions): Plug
nativeLocalStyleModuleIds.add(cleanUrl(id))
}
harmonyApply.rememberSource(code, id, true)
const enableComponentLocalStyle = shouldEnableComponentLocalStyle()
const enablePageLocalStyle = shouldEnablePageLocalStyleForFile(id)
const resolvedConfig = getResolvedConfig()
const shouldForceRefresh = resolvedConfig?.command === 'serve' || resolvedConfig?.command === 'build'
const currentRuntimeSet: Set<string> = await ensureRuntimeClassSet(shouldForceRefresh)
const moduleGraphCandidates = enableComponentLocalStyle || enablePageLocalStyle
? await registerModuleGraphCandidates?.(id, code)
: undefined
const runtimeSet = await ensureRuntimeClassSet(shouldForceRefresh)
const currentRuntimeSet: Set<string> = moduleGraphCandidates?.size
? new Set([...runtimeSet, ...moduleGraphCandidates])
: runtimeSet
nativeHmrReloader.remember(currentRuntimeSet)
const transformUVue = await loadTransformUVue()
const enableComponentLocalStyle = shouldEnableComponentLocalStyle()
const enablePageLocalStyle = shouldEnablePageLocalStyleForFile(id)
const transformOptions = omitUndefined({
...(customAttributesEntities.length > 0 ? { customAttributesEntities } : {}),
...(disabledDefaultTemplateHandler ? { disabledDefaultTemplateHandler } : {}),
Expand Down
Loading
Loading