tailwindcss() — tailwindcss Function Reference
Architecture documentation for the tailwindcss() function in index.ts from the tailwindcss codebase.
Entity Profile
Dependency Diagram
graph TD f3a29437_b991_0a27_2561_a76b3f340642["tailwindcss()"] 525f9b1d_e75d_ad7c_3b49_01821e25c231["fixRelativePathsPlugin()"] f3a29437_b991_0a27_2561_a76b3f340642 -->|calls| 525f9b1d_e75d_ad7c_3b49_01821e25c231 c78ab683_6025_5887_816f_238f52c7b72d["getContextFromCache()"] f3a29437_b991_0a27_2561_a76b3f340642 -->|calls| c78ab683_6025_5887_816f_238f52c7b72d c90ec073_0241_abd8_3427_8edf14bd20d2["postCssAstToCssAst()"] f3a29437_b991_0a27_2561_a76b3f340642 -->|calls| c90ec073_0241_abd8_3427_8edf14bd20d2 af90c185_29a2_6c4c_ef06_b18f00f7655c["toCss()"] f3a29437_b991_0a27_2561_a76b3f340642 -->|calls| af90c185_29a2_6c4c_ef06_b18f00f7655c 112073d3_66c7_8610_9209_6e6a56fb828b["cssAstToPostCssAst()"] f3a29437_b991_0a27_2561_a76b3f340642 -->|calls| 112073d3_66c7_8610_9209_6e6a56fb828b style f3a29437_b991_0a27_2561_a76b3f340642 fill:#6366f1,stroke:#818cf8,color:#fff
Relationship Graph
Source Code
packages/@tailwindcss-postcss/src/index.ts lines 71–363
function tailwindcss(opts: PluginOptions = {}): AcceptedPlugin {
let base = opts.base ?? process.cwd()
let optimize = opts.optimize ?? process.env.NODE_ENV === 'production'
let shouldRewriteUrls = opts.transformAssetUrls ?? true
return {
postcssPlugin: '@tailwindcss/postcss',
plugins: [
// We need to handle the case where `postcss-import` might have run before
// the Tailwind CSS plugin is run. In this case, we need to manually fix
// relative paths before processing it in core.
fixRelativePathsPlugin(),
{
postcssPlugin: 'tailwindcss',
async Once(root, { result, postcss }) {
using I = new Instrumentation()
let inputFile = result.opts.from ?? ''
let isCSSModuleFile = inputFile.endsWith('.module.css')
DEBUG && I.start(`[@tailwindcss/postcss] ${relative(base, inputFile)}`)
// Bail out early if this is guaranteed to be a non-Tailwind CSS file.
{
DEBUG && I.start('Quick bail check')
let canBail = true
root.walkAtRules((node) => {
if (
node.name === 'import' ||
node.name === 'reference' ||
node.name === 'theme' ||
node.name === 'variant' ||
node.name === 'config' ||
node.name === 'plugin' ||
node.name === 'apply' ||
node.name === 'tailwind'
) {
canBail = false
return false
}
})
if (canBail) return
DEBUG && I.end('Quick bail check')
}
let context = getContextFromCache(postcss, inputFile, opts)
let inputBasePath = path.dirname(path.resolve(inputFile))
// Whether this is the first build or not, if it is, then we can
// optimize the build by not creating the compiler until we need it.
let isInitialBuild = context.compiler === null
async function createCompiler() {
DEBUG && I.start('Setup compiler')
if (context.fullRebuildPaths.length > 0 && !isInitialBuild) {
clearRequireCache(context.fullRebuildPaths)
}
context.fullRebuildPaths = []
DEBUG && I.start('PostCSS AST -> Tailwind CSS AST')
let ast = postCssAstToCssAst(root)
DEBUG && I.end('PostCSS AST -> Tailwind CSS AST')
DEBUG && I.start('Create compiler')
let compiler = await compileAst(ast, {
from: result.opts.from,
base: inputBasePath,
shouldRewriteUrls,
onDependency: (path) => context.fullRebuildPaths.push(path),
// In CSS Module files, we have to disable the `@property` polyfill since these will
// emit global `*` rules which are considered to be non-pure and will cause builds
// to fail.
polyfills: isCSSModuleFile ? Polyfills.All ^ Polyfills.AtProperty : Polyfills.All,
})
DEBUG && I.end('Create compiler')
DEBUG && I.end('Setup compiler')
return compiler
}
try {
// Setup the compiler if it doesn't exist yet. This way we can
// guarantee a `build()` function is available.
context.compiler ??= createCompiler()
if ((await context.compiler).features === Features.None) {
return
}
let rebuildStrategy: 'full' | 'incremental' = 'incremental'
// Track file modification times to CSS files
DEBUG && I.start('Register full rebuild paths')
{
for (let file of context.fullRebuildPaths) {
result.messages.push({
type: 'dependency',
plugin: '@tailwindcss/postcss',
file: path.resolve(file),
parent: result.opts.from,
})
}
let files = result.messages.flatMap((message) => {
if (message.type !== 'dependency') return []
return message.file
})
files.push(inputFile)
for (let file of files) {
let changedTime = fs.statSync(file, { throwIfNoEntry: false })?.mtimeMs ?? null
if (changedTime === null) {
if (file === inputFile) {
rebuildStrategy = 'full'
}
continue
}
let prevTime = context.mtimes.get(file)
if (prevTime === changedTime) continue
rebuildStrategy = 'full'
context.mtimes.set(file, changedTime)
}
}
DEBUG && I.end('Register full rebuild paths')
if (
rebuildStrategy === 'full' &&
// We can re-use the compiler if it was created during the
// initial build. If it wasn't, we need to create a new one.
!isInitialBuild
) {
context.compiler = createCompiler()
}
let compiler = await context.compiler
if (context.scanner === null || rebuildStrategy === 'full') {
DEBUG && I.start('Setup scanner')
let sources = (() => {
// Disable auto source detection
if (compiler.root === 'none') {
return []
}
// No root specified, use the base directory
if (compiler.root === null) {
return [{ base, pattern: '**/*', negated: false }]
}
// Use the specified root
return [{ ...compiler.root, negated: false }]
})().concat(compiler.sources)
// Look for candidates used to generate the CSS
context.scanner = new Scanner({ sources })
DEBUG && I.end('Setup scanner')
}
DEBUG && I.start('Scan for candidates')
let candidates = compiler.features & Features.Utilities ? context.scanner.scan() : []
DEBUG && I.end('Scan for candidates')
if (compiler.features & Features.Utilities) {
DEBUG && I.start('Register dependency messages')
// Add all found files as direct dependencies
// Note: With Turbopack, the input file might not be a resolved path
let resolvedInputFile = path.resolve(base, inputFile)
for (let file of context.scanner.files) {
let absolutePath = path.resolve(file)
// The CSS file cannot be a dependency of itself
if (absolutePath === resolvedInputFile) {
continue
}
result.messages.push({
type: 'dependency',
plugin: '@tailwindcss/postcss',
file: absolutePath,
parent: result.opts.from,
})
}
// Register dependencies so changes in `base` cause a rebuild while
// giving tools like Vite or Parcel a glob that can be used to limit
// the files that cause a rebuild to only those that match it.
for (let { base: globBase, pattern } of context.scanner.globs) {
// Avoid adding a dependency on the base directory itself, since it
// causes Next.js to start an endless recursion if the `distDir` is
// configured to anything other than the default `.next` dir.
if (pattern === '*' && base === globBase) {
continue
}
if (pattern === '') {
result.messages.push({
type: 'dependency',
plugin: '@tailwindcss/postcss',
file: path.resolve(globBase),
parent: result.opts.from,
})
} else {
result.messages.push({
type: 'dir-dependency',
plugin: '@tailwindcss/postcss',
dir: path.resolve(globBase),
glob: pattern,
parent: result.opts.from,
})
}
}
DEBUG && I.end('Register dependency messages')
}
DEBUG && I.start('Build utilities')
let tailwindCssAst = compiler.build(candidates)
DEBUG && I.end('Build utilities')
if (context.tailwindCssAst !== tailwindCssAst) {
if (optimize) {
DEBUG && I.start('Optimization')
DEBUG && I.start('AST -> CSS')
let css = toCss(tailwindCssAst)
DEBUG && I.end('AST -> CSS')
DEBUG && I.start('Lightning CSS')
let optimized = optimizeCss(css, {
minify: typeof optimize === 'object' ? optimize.minify : true,
})
DEBUG && I.end('Lightning CSS')
DEBUG && I.start('CSS -> PostCSS AST')
context.optimizedPostCssAst = postcss.parse(optimized.code, result.opts)
DEBUG && I.end('CSS -> PostCSS AST')
DEBUG && I.end('Optimization')
} else {
// Convert our AST to a PostCSS AST
DEBUG && I.start('Transform Tailwind CSS AST into PostCSS AST')
context.cachedPostCssAst = cssAstToPostCssAst(postcss, tailwindCssAst, root.source)
DEBUG && I.end('Transform Tailwind CSS AST into PostCSS AST')
}
}
context.tailwindCssAst = tailwindCssAst
DEBUG && I.start('Update PostCSS AST')
root.removeAll()
root.append(
optimize
? context.optimizedPostCssAst.clone().nodes
: context.cachedPostCssAst.clone().nodes,
)
// Trick PostCSS into thinking the indent is 2 spaces, so it uses that
// as the default instead of 4.
root.raws.indent = ' '
DEBUG && I.end('Update PostCSS AST')
DEBUG && I.end(`[@tailwindcss/postcss] ${relative(base, inputFile)}`)
} catch (error) {
// An error requires a full rebuild to fix
context.compiler = null
// Ensure all dependencies we have collected thus far are included so that the rebuild
// is correctly triggered
for (let file of context.fullRebuildPaths) {
result.messages.push({
type: 'dependency',
plugin: '@tailwindcss/postcss',
file: path.resolve(file),
parent: result.opts.from,
})
}
// We found that throwing the error will cause PostCSS to no longer watch for changes
// in some situations so we instead log the error and continue with an empty stylesheet.
console.error(error)
if (error && typeof error === 'object' && 'message' in error) {
throw root.error(`${error.message}`)
}
throw root.error(`${error}`)
}
},
},
],
}
}
Domain
Subdomains
Source
Frequently Asked Questions
What does tailwindcss() do?
tailwindcss() is a function in the tailwindcss codebase.
What does tailwindcss() call?
tailwindcss() calls 5 function(s): cssAstToPostCssAst, fixRelativePathsPlugin, getContextFromCache, postCssAstToCssAst, toCss.
Analyze Your Own Codebase
Get architecture documentation, dependency graphs, and domain analysis for your codebase in minutes.
Try Supermodel Free