@tailwind-expand/swc
v0.5.2
Published
SWC plugin for tailwind-expand - expand CSS aliases in SWC-based tools
Maintainers
Readme
@tailwind-expand/swc
SWC plugin for tailwind-expand. Inlines className aliases into utility classes in Next.js with Turbopack.
Installation
pnpm add -D @tailwind-expand/swc @tailwind-expand/postcssUsage
// next.config.ts
import tailwindExpandSWC from '@tailwind-expand/swc'
const nextConfig = {
experimental: {
swcPlugins: [tailwindExpandSWC({ cssPath: './app/globals.css' })],
},
}
export default nextConfig// postcss.config.mjs
export default {
plugins: {
'@tailwind-expand/postcss': {},
'@tailwindcss/postcss': {},
},
}Options
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| cssPath | string | — | Path to CSS file containing @expand definitions (required) |
| mergerFn | (classes: string) => string | — | Function to resolve conflicting utilities (e.g., twMerge) |
| debug | boolean | false | Add data-expand attribute with expanded alias names |
With tailwind-merge and debug mode
import tailwindExpandSWC from '@tailwind-expand/swc'
import { twMerge } from 'tailwind-merge'
const nextConfig = {
experimental: {
swcPlugins: [tailwindExpandSWC({
cssPath: './app/globals.css',
mergerFn: twMerge,
debug: process.env.NODE_ENV !== 'production',
})],
},
}How It Works
The SWC plugin runs inside a WASI sandbox which cannot access the filesystem directly. This package includes a TypeScript wrapper that:
- Reads the CSS file at build time
- Extracts and expands all aliases using
@tailwind-expand/core - Passes pre-expanded aliases to the WASM plugin
The WASM plugin then transforms JSX className attributes using the provided aliases.
Development Limitation
CSS alias changes require a server restart. This is not true HMR.
Because aliases are read at config load time (not during transform), changes to @expand blocks in your CSS won't be reflected until the dev server restarts. Turbopack caches SWC transform results and doesn't expose cache invalidation APIs.
Workaround: Auto-restart with nodemon
Use nodemon to automatically restart the dev server when CSS changes:
pnpm add -D nodemonAdd to package.json (adjust watch path to match your CSS file location):
{
"scripts": {
"dev:watch": "nodemon"
},
"nodemonConfig": {
"watch": ["app/globals.css"],
"ext": "css",
"ignore": [".next", "node_modules"],
"exec": "next dev"
}
}Run pnpm dev:watch instead of pnpm dev.
Note: This restarts the entire server, so React state is lost. It's a workaround, not true HMR.
You can follow up on the discussion regarding HMR support in the Next.js repository.
Building from Source
Prerequisites
- Install Rust: https://rustup.rs/
- The
rust-toolchain.tomlwill automatically install the correct Rust version (1.83.0) and WASM target
Build
cd packages/swc
pnpm buildThis runs:
cargo build --target wasm32-wasip1 --release- Compiles Rust to WASMtsup- Builds the TypeScript wrapper
Verifying the WASM Binary
The published package includes a SHA256 checksum for the WASM binary.
Verify an installed package
cd node_modules/@tailwind-expand/swc
shasum -a 256 -c tailwind_expand_swc.wasm.sha256Generate checksum after building
pnpm checksumVerify checksum
pnpm verifyReproducible Builds
For reproducible builds, ensure:
- Same Rust version (pinned in
rust-toolchain.toml) - Same build flags:
CARGO_INCREMENTAL=0 RUSTFLAGS='-C debuginfo=0' cargo build --target wasm32-wasip1 --release
CI builds use these exact settings to ensure deterministic output.
License
MIT
