From 545401469dc342893e42dae66747e3008082457a Mon Sep 17 00:00:00 2001 From: Philipp Spiess Date: Tue, 3 Dec 2024 10:28:51 +0100 Subject: [PATCH] Postcss: Run plugin in `Once` hook (#15273) Closes #15138 This PR changes the postcss client to run in the `Once` hook instead of `OnceExit`. This makes sure the postcss order in v4 matches that of v3. Conceptually this also makes more sense, since we expect tailwindcss to be run as one of the first plugins in the pipeline (where `OnceExit` would run it almost at the end). To make sure it's still possible to use `postcss-import` before and have it resolve to the right paths, we also needed to change the `postcss-fix-relative-paths` plugin to run in the `Once` order (`postcss-import` also uses `Once` order so the order). ## Test Plan This issue had many ways in which it can manifest. I added a unit test to ensure the plugin order works but here's a concrete example when using the postcss plugin in Vite. ### Before Image `url()`s were not properly handled since the postcss plugin to transform these was run before Tailwind CSS could generate the class for it: Screenshot 2024-12-02 at 14 55 42 ### After Screenshot 2024-12-02 at 14 53 52 --------- Co-authored-by: Jordan Pittman --- CHANGELOG.md | 2 + .../@tailwindcss-postcss/src/index.test.ts | 60 ++++++++++++++++++- packages/@tailwindcss-postcss/src/index.ts | 2 +- .../src/postcss-fix-relative-paths/index.ts | 6 +- 4 files changed, 64 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1d460d1ac..aace62b6e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Ensure absolute `url()`s inside imported CSS files are not rebased when using `@tailwindcss/vite` - Fix issues with dev servers using Svelte 5 with the Vite plugin ([#15274](https://github.com/tailwindlabs/tailwindcss/issues/15274)) - Fix resolution of imported CSS files in Vite SSR builds ([#15279](https://github.com/tailwindlabs/tailwindcss/issues/15279)) +- Ensure other plugins can run after `@tailwindcss/postcss` ([#15273](https://github.com/tailwindlabs/tailwindcss/pull/15273)) +- Rebase `url()` inside imported CSS files when using Vite with the `@tailwindcss/postcss` extension ([#15273](https://github.com/tailwindlabs/tailwindcss/pull/15273)) ### Added diff --git a/packages/@tailwindcss-postcss/src/index.test.ts b/packages/@tailwindcss-postcss/src/index.test.ts index 02ab23bea..50f72a13d 100644 --- a/packages/@tailwindcss-postcss/src/index.test.ts +++ b/packages/@tailwindcss-postcss/src/index.test.ts @@ -2,7 +2,6 @@ import dedent from 'dedent' import { unlink, writeFile } from 'node:fs/promises' import postcss from 'postcss' import { afterEach, beforeEach, describe, expect, test } from 'vitest' -// @ts-ignore import tailwindcss from './index' // We give this file path to PostCSS for processing. @@ -248,3 +247,62 @@ test('bail early when Tailwind is not used', async () => { }" `) }) + +test('runs `Once` plugins in the right order', async () => { + let before = '' + let after = '' + let processor = postcss([ + { + postcssPlugin: 'before', + Once(root) { + before = root.toString() + }, + }, + tailwindcss({ base: `${__dirname}/fixtures/example-project`, optimize: { minify: false } }), + { + postcssPlugin: 'after', + Once(root) { + after = root.toString() + }, + }, + ]) + + let result = await processor.process( + css` + @theme { + --color-red-500: red; + } + .custom-css { + color: theme(--color-red-500); + } + `, + { from: inputCssFilePath() }, + ) + + expect(result.css.trim()).toMatchInlineSnapshot(` + ":root { + --color-red-500: red; + } + + .custom-css { + color: red; + }" + `) + expect(before).toMatchInlineSnapshot(` + "@theme { + --color-red-500: red; + } + .custom-css { + color: theme(--color-red-500); + }" + `) + expect(after).toMatchInlineSnapshot(` + ":root { + --color-red-500: red; + } + + .custom-css { + color: red; + }" + `) +}) diff --git a/packages/@tailwindcss-postcss/src/index.ts b/packages/@tailwindcss-postcss/src/index.ts index 6720dfea0..a1759f9f4 100644 --- a/packages/@tailwindcss-postcss/src/index.ts +++ b/packages/@tailwindcss-postcss/src/index.ts @@ -55,7 +55,7 @@ function tailwindcss(opts: PluginOptions = {}): AcceptedPlugin { { postcssPlugin: 'tailwindcss', - async OnceExit(root, { result }) { + async Once(root, { result }) { env.DEBUG && console.time('[@tailwindcss/postcss] Total time in @tailwindcss/postcss') let inputFile = result.opts.from ?? '' let context = getContextFromCache(inputFile, opts) diff --git a/packages/@tailwindcss-postcss/src/postcss-fix-relative-paths/index.ts b/packages/@tailwindcss-postcss/src/postcss-fix-relative-paths/index.ts index 2b88014a3..68dcb5551 100644 --- a/packages/@tailwindcss-postcss/src/postcss-fix-relative-paths/index.ts +++ b/packages/@tailwindcss-postcss/src/postcss-fix-relative-paths/index.ts @@ -67,10 +67,8 @@ export default function fixRelativePathsPlugin(): Plugin { return { postcssPlugin: 'tailwindcss-postcss-fix-relative-paths', - AtRule: { - source: fixRelativePath, - plugin: fixRelativePath, - config: fixRelativePath, + Once(root) { + root.walkAtRules(/source|plugin|config/, fixRelativePath) }, } }