diff --git a/integrations/postcss/config.test.ts b/integrations/postcss/config.test.ts index b81924e0c..9bcc3a22c 100644 --- a/integrations/postcss/config.test.ts +++ b/integrations/postcss/config.test.ts @@ -156,6 +156,14 @@ test( 'color: blue', ]) + // While working on this test we noticed that it was failing in about 1-2% + // of the runs. We tracked this down to being a proper `delete + // require.cache` call for the `my-color.js` file but for some reason + // reading it will result in the previous contents. + // + // To work around this, we give postcss some time to stabilize. + await new Promise((resolve) => setTimeout(resolve, 500)) + await fs.write('my-color.js', js`module.exports = 'red'`) await fs.expectFileToContain('dist/out.css', [ diff --git a/packages/@tailwindcss-cli/src/commands/build/index.ts b/packages/@tailwindcss-cli/src/commands/build/index.ts index 663fa9b9e..f5cf61591 100644 --- a/packages/@tailwindcss-cli/src/commands/build/index.ts +++ b/packages/@tailwindcss-cli/src/commands/build/index.ts @@ -226,8 +226,8 @@ export async function handle(args: Result>) { `, args['--input'] ?? base, ) + clearRequireCache(fullRebuildPaths) fullRebuildPaths = cssImportPaths - clearRequireCache() // Create a new compiler, given the new `input` compiler = await compile(input) diff --git a/packages/@tailwindcss-node/src/require-cache.cts b/packages/@tailwindcss-node/src/require-cache.cts index 96f8f0e0e..8c56abfea 100644 --- a/packages/@tailwindcss-node/src/require-cache.cts +++ b/packages/@tailwindcss-node/src/require-cache.cts @@ -1,5 +1,5 @@ -export function clearRequireCache() { - for (const key in require.cache) { +export function clearRequireCache(files: string[]) { + for (const key of files) { delete require.cache[key] } } diff --git a/packages/@tailwindcss-postcss/src/index.ts b/packages/@tailwindcss-postcss/src/index.ts index cf6fc0006..41fc4ee20 100644 --- a/packages/@tailwindcss-postcss/src/index.ts +++ b/packages/@tailwindcss-postcss/src/index.ts @@ -84,7 +84,7 @@ function tailwindcss(opts: PluginOptions = {}): AcceptedPlugin { let inputBasePath = path.dirname(path.resolve(inputFile)) function createCompiler() { - clearRequireCache() + clearRequireCache(context.fullRebuildPaths) context.fullRebuildPaths = [] return compile(root.toString(), { loadPlugin: async (pluginPath) => { diff --git a/packages/@tailwindcss-vite/src/index.ts b/packages/@tailwindcss-vite/src/index.ts index d20ba9b36..a05b90a7f 100644 --- a/packages/@tailwindcss-vite/src/index.ts +++ b/packages/@tailwindcss-vite/src/index.ts @@ -17,6 +17,7 @@ export default function tailwindcss(): Plugin[] { let scanner: Scanner | null = null let changedContent: { content: string; extension: string }[] = [] let candidates = new Set() + let fullRebuildPaths: string[] = [] // In serve mode this is treated as a set — the content doesn't matter. // In build mode, we store file contents to use them in renderChunk. @@ -84,7 +85,8 @@ export default function tailwindcss(): Plugin[] { async function generateCss(css: string, inputPath: string, addWatchFile: (file: string) => void) { let inputBasePath = path.dirname(path.resolve(inputPath)) - clearRequireCache() + clearRequireCache(fullRebuildPaths) + fullRebuildPaths = [] let { build, globs } = await compile(css, { loadPlugin: async (pluginPath) => { if (pluginPath[0] !== '.') { @@ -93,8 +95,10 @@ export default function tailwindcss(): Plugin[] { let resolvedPath = path.resolve(inputBasePath, pluginPath) addWatchFile(resolvedPath) + fullRebuildPaths.push(resolvedPath) for (let file of getModuleDependencies(resolvedPath)) { addWatchFile(file) + fullRebuildPaths.push(file) } return import(pathToFileURL(resolvedPath).href + '?id=' + Date.now()).then( (m) => m.default ?? m, @@ -108,8 +112,10 @@ export default function tailwindcss(): Plugin[] { let resolvedPath = path.resolve(inputBasePath, configPath) addWatchFile(resolvedPath) + fullRebuildPaths.push(resolvedPath) for (let file of getModuleDependencies(resolvedPath)) { addWatchFile(file) + fullRebuildPaths.push(file) } return import(pathToFileURL(resolvedPath).href + '?id=' + Date.now()).then( (m) => m.default ?? m,