babel-plugin-styled-components is a Babel plugin that enhances the styled-components CSS-in-JS library with essential development and production optimizations. It provides consistent component className hashing across environments (critical for server-side rendering), improves debugging through automatic component annotation, and offers various minification strategies for styles and tagged template literals.
npm install --save-dev babel-plugin-styled-componentsThis is a Babel plugin, so it's configured in your Babel configuration file rather than imported directly:
{
"plugins": ["babel-plugin-styled-components"]
}With options:
{
"plugins": [
[
"babel-plugin-styled-components",
{
"displayName": true,
"ssr": true,
"fileName": true,
"minify": true,
"transpileTemplateLiterals": true,
"pure": false,
"cssProp": true
}
]
]
}The plugin automatically transforms styled-components code during Babel compilation:
// Input code
import styled from 'styled-components';
const Button = styled.button`
padding: 12px 24px;
background-color: #007bff;
color: white;
border: none;
border-radius: 4px;
`;
// After plugin transformation (when displayName: true, ssr: true)
const Button = styled.button.withConfig({
displayName: "Button",
componentId: "sc-1h2k3j4-0"
})`
padding: 12px 24px;
background-color: #007bff;
color: white;
border: none;
border-radius: 4px;
`;The plugin is built on Babel's visitor pattern and operates through several key components:
displayNameAndId: Adds displayName and componentId to styled componentspureAnnotation: Adds /#PURE/ annotations for tree-shakingminify: Minifies CSS content in template literalstemplateLiterals: Transpiles template literals for performance optimizationtranspileCssProp: Transforms JSX css prop into styled-components callsThe plugin can be used programmatically with Babel's transform API:
import babel from '@babel/core';
import styledComponentsPlugin from 'babel-plugin-styled-components';
const code = `
import styled from 'styled-components';
const Button = styled.button\`color: blue;\`;
`;
const result = babel.transformSync(code, {
plugins: [
[styledComponentsPlugin, {
displayName: true,
ssr: true,
minify: true
}]
]
});
console.log(result.code);The plugin exports a single default function that returns a Babel plugin configuration.
/**
* Main plugin function that returns Babel plugin configuration
* @param babel - Babel API object containing types (t) and other utilities
* @returns Babel plugin configuration with inherits and visitor properties
*/
declare function babelPluginStyledComponents(babel: {
types: typeof t;
}): {
inherits: any;
visitor: {
Program(path: any, state: any): void;
CallExpression(path: any, state: any): void;
TaggedTemplateExpression(path: any, state: any): void;
};
};
export default babelPluginStyledComponents;
/**
* Internal visitor functions (not directly exposed but part of the plugin's behavior)
*/
interface VisitorFunctions {
displayNameAndId(types: any): (path: any, state: any) => void;
pureAnnotation(types: any): (path: any, state: any) => void;
minify(types: any): (path: any, state: any) => void;
templateLiterals(types: any): (path: any, state: any) => void;
transpileCssProp(types: any): (path: any, state: any) => void;
assignStyledRequired(types: any): (path: any, state: any) => void;
}
/**
* State object passed to visitor functions
*/
interface PluginState {
opts: BabelPluginOptions;
file: any;
customImportName?: string;
styledRequired?: string;
}Configure the plugin behavior through Babel options. All options are optional with sensible defaults.
interface PluginOptions {
/** Add displayName to styled components for better debugging (default: true) */
displayName?: boolean;
/** Enable server-side rendering support with consistent className hashing (default: true) */
ssr?: boolean;
/** Use filename context for generating component displayNames (default: true) */
fileName?: boolean;
/** Array of filenames considered meaningless when generating component names (default: ['index']) */
meaninglessFileNames?: string[];
/** Prefix for component identifiers (default: '') */
namespace?: string;
/** Patterns to match import paths that should trigger plugin transformations (default: []) */
topLevelImportPaths?: string[];
/** Enable minification of CSS inside tagged template literals (default: true) */
minify?: boolean;
/** Enable transpilation of template literals to optimize runtime performance (default: true) */
transpileTemplateLiterals?: boolean;
/** Add /*#__PURE__*/ annotations for better tree-shaking (default: false) */
pure?: boolean;
/** Enable transformation of css prop in JSX elements (default: true) */
cssProp?: boolean;
}Automatically adds displayName properties to styled components for better debugging experience in React DevTools.
Configuration:
{
"plugins": [
[
"babel-plugin-styled-components",
{
"displayName": true,
"fileName": true,
"meaninglessFileNames": ["index", "styles"]
}
]
]
}Example transformation:
// Input: src/components/Button/index.js
const Button = styled.button`color: blue;`;
// Output:
const Button = styled.button.withConfig({
displayName: "Button",
componentId: "sc-1h2k3j4-0"
})`color: blue;`;Ensures consistent className hashing between client and server environments, preventing hydration mismatches.
Configuration:
{
"plugins": [
[
"babel-plugin-styled-components",
{
"ssr": true,
"namespace": "myapp"
}
]
]
}Features:
Removes unnecessary whitespace and comments from CSS template literals to reduce bundle size.
Configuration:
{
"plugins": [
[
"babel-plugin-styled-components",
{
"minify": true
}
]
]
}Example transformation:
// Input:
const Button = styled.button`
/* Button styles */
padding: 12px 24px;
background: linear-gradient(
to right,
#007bff,
#0056b3
);
`;
// Output (minified):
const Button = styled.button`padding:12px 24px;background:linear-gradient(to right,#007bff,#0056b3);`;Transpiles template literals to more efficient runtime representations for better performance.
Configuration:
{
"plugins": [
[
"babel-plugin-styled-components",
{
"transpileTemplateLiterals": true
}
]
]
}Features:
Transforms JSX css prop into styled-components calls, enabling inline styling with full styled-components features.
Configuration:
{
"plugins": [
[
"babel-plugin-styled-components",
{
"cssProp": true
}
]
]
}Example transformation:
// Input:
<div css="color: red; font-size: 16px;">Hello</div>
// Output:
<StyledComponent css="color: red; font-size: 16px;">Hello</StyledComponent>Adds pure annotations to help bundlers eliminate unused styled-components code.
Configuration:
{
"plugins": [
[
"babel-plugin-styled-components",
{
"pure": true
}
]
]
}Example transformation:
// Input:
const Button = styled.button`color: blue;`;
// Output:
const Button = /*#__PURE__*/ styled.button`color: blue;`;Restricts plugin transformations to specific import paths, useful for mono-repos or custom styled-components implementations.
Configuration:
{
"plugins": [
[
"babel-plugin-styled-components",
{
"topLevelImportPaths": [
"@mycompany/styled-components",
"@mycompany/styled-components/*"
]
}
]
]
}Only styled-components imported from the specified paths will be transformed by the plugin.
/** Plugin configuration options interface */
interface BabelPluginOptions {
displayName?: boolean;
ssr?: boolean;
fileName?: boolean;
meaninglessFileNames?: string[];
namespace?: string;
topLevelImportPaths?: string[];
minify?: boolean;
transpileTemplateLiterals?: boolean;
pure?: boolean;
cssProp?: boolean;
}
/** Babel plugin function signature */
type BabelPlugin = (babel: BabelAPI) => {
inherits: any;
visitor: BabelVisitor;
};
/** Babel API object structure */
interface BabelAPI {
types: BabelTypes;
template: any;
version: string;
}
/** State object passed through visitor functions */
interface PluginState {
opts: BabelPluginOptions;
file: BabelFile;
customImportName?: string;
styledRequired?: string;
}
/** File object containing compilation context */
interface BabelFile {
opts: {
filename: string;
};
path: any;
code: string;
get(key: string): any;
set(key: string, value: any): void;
}
/** Visitor function signature */
type VisitorFunction = (path: any, state: PluginState) => void;
/** Visitor method factories */
interface VisitorFactories {
displayNameAndId(types: BabelTypes): VisitorFunction;
pureAnnotation(types: BabelTypes): VisitorFunction;
minify(types: BabelTypes): VisitorFunction;
templateLiterals(types: BabelTypes): VisitorFunction;
transpileCssProp(types: BabelTypes): VisitorFunction;
assignStyledRequired(types: BabelTypes): VisitorFunction;
}
/** Detection utility functions */
interface DetectionUtils {
isStyled(types: BabelTypes): (tag: any, state: PluginState) => boolean;
isHelper(types: BabelTypes): (tag: any, state: PluginState) => boolean;
isCSSHelper(types: BabelTypes): (tag: any, state: PluginState) => boolean;
isCreateGlobalStyleHelper(types: BabelTypes): (tag: any, state: PluginState) => boolean;
isKeyframesHelper(types: BabelTypes): (tag: any, state: PluginState) => boolean;
isWithThemeHelper(types: BabelTypes): (tag: any, state: PluginState) => boolean;
isUseTheme(types: BabelTypes): (tag: any, state: PluginState) => boolean;
isPureHelper(types: BabelTypes): (tag: any, state: PluginState) => boolean;
isValidTopLevelImport(path: string, state: PluginState): boolean;
importLocalName(name: string, state: PluginState, options?: {
cacheIdentifier?: string;
bypassCache?: boolean;
}): string | false;
}
/** Option utility functions */
interface OptionUtils {
useDisplayName(state: PluginState): boolean;
useSSR(state: PluginState): boolean;
useFileName(state: PluginState): boolean;
useMeaninglessFileNames(state: PluginState): string[];
useMinify(state: PluginState): boolean;
useTranspileTemplateLiterals(state: PluginState): boolean;
useNamespace(state: PluginState): string;
usePureAnnotation(state: PluginState): boolean;
useCssProp(state: PluginState): boolean;
useTopLevelImportPathMatchers(state: PluginState): Array<(pattern: string) => boolean>;
}
/** Main plugin export */
declare const plugin: BabelPlugin;
export default plugin;