tailwindlabs/tailwindcss
@tailwindcss/postcss
Active contributors: Robin, Philipp, Adam
Purpose
The PostCSS plugin. Converts Tailwind input CSS to output CSS while staying a well-behaved member of a PostCSS pipeline. Implementation: packages/@tailwindcss-postcss/src/.
Directory layout
packages/@tailwindcss-postcss/
├── package.json
├── README.md
├── tsconfig.json
├── tsup.config.ts
└── src/
├── index.ts # Plugin entry point
├── ast.ts # postCssAstToCssAst + cssAstToPostCssAst
├── postcss-fix-relative-paths/ # Sub-plugin to handle `postcss-import` quirks
└── *.test.ts # Tests + snapshotsKey abstractions
| Symbol | Description |
|---|---|
tailwindcss(opts): AcceptedPlugin |
Default export, returns a PostCSS plugin descriptor. |
CacheEntry |
Per-input-file cache holding the compiler, scanner, mtimes, ASTs. |
getContextFromCache(...) |
LRU-keyed cache lookup. |
cssAstToPostCssAst / postCssAstToCssAst |
Converters between Tailwind's internal AST and PostCSS's AST. |
fixRelativePathsPlugin |
Sub-plugin that fixes paths when postcss-import ran first. |
How it integrates with PostCSS
graph LR
A[postcss-import<br/>maybe] --> B[fixRelativePathsPlugin]
B --> C[Tailwind plugin]
C --> D[postcss → out CSS]The plugin signature is unusual because it nests two PostCSS plugins:
return {
postcssPlugin: '@tailwindcss/postcss',
plugins: [
fixRelativePathsPlugin, // pre-transform fix-up
{
// The actual Tailwind plugin
Once(root, { result }) {
// ...
},
},
],
};fixRelativePathsPlugin exists because postcss-import can run before Tailwind in a typical pipeline, which rewrites @import paths to be absolute. The fix-up walks the imported AST and re-relativizes paths so Tailwind's own @source, @plugin, and @config directives resolve against the original file location.
Caching
The plugin keeps an LRU<string, CacheEntry> (max size 50). Keys include input file path, base, and the optimize settings. Each entry caches:
mtimes— the file → mtime map for invalidation.compiler— the result ofcompileAst(...).scanner— the@tailwindcss/oxideScanner.tailwindCssAst— the static AST returned by the compiler (used to skip re-parsing).cachedPostCssAstandoptimizedPostCssAst— pre-converted outputs.fullRebuildPaths— the list of file paths that should trigger a full re-compile when their mtime changes.
When the compiler emits new dependency paths (via onDependency), they go into fullRebuildPaths. On the next Once call, the plugin compares mtimes and either reuses the cached AST or rebuilds.
AST conversion
PostCSS uses its own AST. Tailwind's compiler uses an internal AST defined in packages/tailwindcss/src/ast.ts. packages/@tailwindcss-postcss/src/ast.ts provides the bridge:
postCssAstToCssAst(root)— read PostCSS into the internal AST. Used because the input CSS arrives from PostCSS.cssAstToPostCssAst(ast, postcss)— write the internal AST back to PostCSS so downstream plugins can keep operating.
Source position information is preserved through both conversions, which is how source maps survive the round-trip.
Plugin options
type PluginOptions = {
base?: string; // default: process.cwd()
optimize?: boolean | { minify?: boolean }; // default: NODE_ENV === 'production'
transformAssetUrls?: boolean; // default: true
};base controls the project root the scanner walks and resolves @source patterns against. transformAssetUrls toggles URL rewriting for things like background-image: url(./logo.png).
Common pitfalls (and where they're handled)
postcss-importrunning first. Handled byfixRelativePathsPlugin.CHANGELOG.mdmentions a related PR #19980 ("Resolve imports relative tobasewhenresult.opts.fromis not provided").@propertypolyfill in CSS modules. A flag insideindex.tsdisables the polyfill for*.module.cssfiles because CSS modules' purity check would reject the global*rules the polyfill emits.- Source maps. The compiler's source map output is decoded by
@tailwindcss/node'stoSourceMapand attached to the PostCSS result.
Integration points
- Reads from
tailwindcssdirectly fortoCssand the AST types. - Reads from
@tailwindcss/nodeforcompileAst,env,Features,Instrumentation,optimize,Polyfills. - Reads from
@tailwindcss/oxidefor theScanner. - Returns a PostCSS plugin descriptor that any standard PostCSS host can consume.
Entry points for modification
Once(root, { result })inindex.tsis where the plugin runs per input file. Add timing or new cache keys here.fixRelativePathsPlugin/is its own subdirectory — modify ifpostcss-importinteractions change.postCssAstToCssAst/cssAstToPostCssAstare where format incompatibilities get bridged. New AST node kinds added to the compiler should map to a sensible PostCSS equivalent here.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.