tailwindlabs/tailwindcss
@tailwindcss/node
Active contributors: Robin, Philipp, Jordan
Purpose
Shared Node-only helpers used by every Node-side adapter (@tailwindcss/cli, @tailwindcss/vite, @tailwindcss/postcss, @tailwindcss/webpack). The adapters need filesystem access, JS module loading, source-map post-processing, and CSS optimization through Lightning CSS — none of which the core compiler should depend on.
This package is the shim layer that keeps the compiler portable. The core tailwindcss package has zero runtime dependencies; the Node-specific surface lives here.
Directory layout
packages/@tailwindcss-node/
├── package.json
├── README.md
├── tsconfig.json
├── tsup.config.ts
└── src/
├── index.ts # Re-exports compile, optimize, source maps
├── index.cts # CommonJS variant
├── compile.ts # Wraps tailwindcss.compile with Node-only loaders
├── env.ts # DEBUG flag, NODE_ENV detection
├── instrumentation.ts # Timing helper used by every adapter
├── instrumentation.test.ts
├── optimize.ts # Lightning CSS minification + vendor prefixing
├── source-maps.ts # toSourceMap helper
├── source-maps.test.ts
├── urls.ts # Asset URL rewriting
├── urls.test.ts
├── normalize-path.ts # Cross-platform path normalization
├── get-module-dependencies.ts # Resolve transitive deps for invalidation
├── require-cache.cts # Sync require-cache clearer
└── esm-cache.loader.mts # ESM loader that mirrors require-cache.ctsKey abstractions
| Symbol | File | Description |
|---|---|---|
compile(input, opts) |
packages/@tailwindcss-node/src/compile.ts |
Wraps tailwindcss.compile with enhanced-resolve + jiti. |
compileAst(ast, opts) |
packages/@tailwindcss-node/src/compile.ts |
Same, but takes an AST. |
Instrumentation |
packages/@tailwindcss-node/src/instrumentation.ts |
using resource + start()/end()/hit() API. |
optimize(css, opts) |
packages/@tailwindcss-node/src/optimize.ts |
Lightning CSS minify + lower modern syntax. |
toSourceMap(rawMap) |
packages/@tailwindcss-node/src/source-maps.ts |
Convert decoded source map to a JSON-encoded string. |
Features, Polyfills |
(re-exported from tailwindcss) |
Bit-sets the adapters use. |
clearRequireCache(paths) |
packages/@tailwindcss-node/src/require-cache.cts |
Drop entries from Node's require.cache. |
| ESM cache loader | packages/@tailwindcss-node/src/esm-cache.loader.mts |
Equivalent for ESM module cache. |
normalizePath(p) |
packages/@tailwindcss-node/src/normalize-path.ts |
Forward-slash-only path strings. |
env.DEBUG |
packages/@tailwindcss-node/src/env.ts |
Boolean derived from the DEBUG env variable. |
What compile() does on top of the core
The core tailwindcss.compile accepts callback-based loaders for @import and @plugin. @tailwindcss/node's wrapper plugs in real Node loaders:
loadStylesheetresolves@importtargets viaenhanced-resolve, the same resolver Webpack uses. This means TS path aliases,package.jsonexports, and conditionalstyleexports all work.loadModuleloads@pluginand@configfiles viajiti, which can run TypeScript and ESM directly without compilation.onDependency(path)is invoked for every file the resolver touched, so adapters can wire those into their host's dependency graph (Vite'saddWatchFile, Webpack'saddDependency, PostCSS'sresult.messages, the CLI's watcher subscription).
compileAst is the same wrapper around tailwindcss.compileAst and is used by @tailwindcss/postcss so it can hand in an AST it already parsed.
Instrumentation
Instrumentation is a using-compatible class that batches timing data:
using I = new Instrumentation();
I.start('Compile');
// ...
I.end('Compile');
I.hit('Some thing happened', { extra: 'data' });When the using block exits, Instrumentation flushes any open spans and (if DEBUG is on) writes a structured tree to stderr. The browser bundle uses a similar API but writes to performance.measure instead.
The class is intentionally tiny so it costs almost nothing in production builds.
optimize()
Calls Lightning CSS via bundleAsync. The function:
- Lowers modern CSS to a target compatible with the configured browserslist (defaults baked in by Lightning CSS).
- Optionally minifies output (
minify: true). - Returns
{ code, map }wheremapis a decoded source map ready to be merged via@jridgewell/remapping.
Source maps are merged through magic-string and @jridgewell/remapping before being returned to adapters.
ESM/CJS dual loading
@tailwindcss/node ships both a .mjs and a .js build via tsup (tsup.config.ts), with separate type declarations. index.cts exists so legacy CJS consumers can require it. The require-cache and esm-cache.loader files are intentionally split so the two module systems can each be flushed independently when a watched dependency changes.
Integration points
- Depends on
tailwindcss(workspace). - Depends on
enhanced-resolve(resolver),jiti(TS/ESM loader),lightningcss(optimizer),magic-string+@jridgewell/remapping+source-map-js(source map plumbing). - Re-exports
Features,Polyfills, andInstrumentationso adapters import from one place. - Used by every Node-side adapter — see cli, vite, postcss, webpack.
Entry points for modification
- Adding a new resolver condition or loader: edit
compile.ts. BothloadStylesheetandloadModuleare constructed there. - Adding a new instrumentation span type: edit
instrumentation.ts. The class is small and self-contained. - Tweaking how source maps are merged: edit
source-maps.ts.toSourceMapis the canonical conversion path. - Changing optimization defaults (e.g. browser targets): edit
optimize.ts— Lightning CSS options are configured there.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.