@sylphx/babel-plugin-silk
Zero-runtime Babel plugin for Silk CSS-in-TypeScript
Compiles css() calls to static class names at build-time, achieving true zero-runtime overhead.
Features
- ✅ True Zero Runtime for static styles
- ✅ Atomic CSS generation (one class per property)
- ✅ Partial Compilation for mixed static/dynamic styles
- ✅ Production Optimization with short class names
- ✅ Framework Agnostic works with any bundler
Installation
npm install --save-dev @sylphx/babel-plugin-silk
bun add --dev @sylphx/babel-plugin-silk
Usage
Babel Configuration
{
"plugins": ["@sylphx/babel-plugin-silk"]
}
With Options
{
"plugins": [
[
"@sylphx/babel-plugin-silk",
{
"production": true,
"classPrefix": "",
"importSources": ["@sylphx/silk"]
}
]
]
}
How It Works
Static Styles (Full Compilation)
import { css } from '@sylphx/silk'
const button = css({ bg: 'red', p: 4 })
const button = 'silk_bg_red_a7f3 silk_p_4_b2e1'
const button = 'a7f3b2c1'
.silk_bg_red_a7f3 { background-color: red; }
.silk_p_4_b2e1 { padding: 1rem; }
Dynamic Styles (Partial Compilation)
const button = css({ bg: props.color, p: 4 })
const button = css({ bg: props.color }, 'silk_p_4_b2e1')
.silk_p_4_b2e1 { padding: 1rem; }
Static properties are extracted at build-time, dynamic properties remain at runtime.
Options
production | boolean | false | Enable production optimizations |
classPrefix | string | 'silk' (dev), '' (prod) | Class name prefix |
importSources | string[] | ['@sylphx/silk'] | Import sources to transform |
functions | string[] | ['css'] | Function names to transform |
Integration with Bundlers
Vite
import { defineConfig } from 'vite'
import { transformSync } from '@babel/core'
import babelPluginSilk from '@sylphx/babel-plugin-silk'
export default defineConfig({
plugins: [
{
name: 'vite-plugin-silk',
transform(code, id) {
if (!id.endsWith('.tsx') && !id.endsWith('.ts')) return null
const result = transformSync(code, {
filename: id,
plugins: [babelPluginSilk],
})
const css = result?.metadata?.silk?.cssRules
.map(([_, rule]) => rule)
.join('\n')
return {
code: result?.code,
map: result?.map,
}
},
},
],
})
Next.js
module.exports = {
experimental: {
swcPlugins: [
['@sylphx/babel-plugin-silk', { production: true }]
]
}
}
Webpack
module.exports = {
module: {
rules: [
{
test: /\.(ts|tsx)$/,
use: {
loader: 'babel-loader',
options: {
plugins: ['@sylphx/babel-plugin-silk']
}
}
}
]
}
}
API
Metadata Format
The plugin emits metadata via result.metadata.silk:
interface SilkMetadata {
cssRules: Array<[className: string, cssRule: string]>
classNames: string[]
version: string
}
Example
const result = transformSync(code, {
plugins: [babelPluginSilk]
})
const css = result.metadata.silk.cssRules
.map(([_, rule]) => rule)
.join('\n')
fs.writeFileSync('output.css', css)
Supported Features
- ✅ Static property values
- ✅ Spread operators (static objects)
- ✅ Property shorthands (
bg, p, m, etc.)
- ✅ Spacing units (Tailwind-style:
p: 4 → 1rem)
- ✅ Pseudo-selectors (
_hover, _focus)
- ✅ Responsive values (
{ base: '100%', md: '50%' })
- ⏳ Container queries (coming soon)
- ⏳ Variants and recipes (coming soon)
Limitations
- Only transforms
css() calls from configured import sources
- Renamed imports not supported (must import as
css)
- Dynamic spreads not supported
- Imported style objects require inline definition
Development
bun run build
bun test
bun run dev
License
MIT © SylphX Ltd