Skip to main content

Installation

Runtime

All uses of StyleX require the runtime package to be installed.

npm install --save @stylexjs/stylex

Compiler

The recommended way to use StyleX in development and production is with the build-time compiler.

Development

For development, you need only to configure the Babel plugin so that styles are processed at compile-time. The plugin will compile styles and insert runtime style injection code into your JavaScript modules.

npm install --save-dev @stylexjs/babel-plugin
// babel.config.js
import styleXPlugin from '@stylexjs/babel-plugin';

const config = {
plugins: [
[
styleXPlugin,
{
dev: true,
// Set this to true for snapshot testing
// default: false
test: false,
// Required for CSS variable support
unstable_moduleResolution: {
// type: 'commonJS' | 'haste'
// default: 'commonJS'
type: 'commonJS',
// The absolute path to the root directory of your project
rootDir: __dirname,
},
},
],
],
};

export default config;

Production

Production use of StyleX should extract CSS to an external file. This can be done with any bundler that supports Babel, using the metadata generated by the StyleX plugin. See the API reference for more details on the @stylexjs/babel-plugin API.

To make this easier for commonly used packages and meta-frameworks, StyleX provides (experimental) plugins for Webpack, Rollup, Next.js and esbuild.

Rollup
npm install --save-dev @stylexjs/rollup-plugin
rollup.config.js
import stylexPlugin from '@stylexjs/rollup-plugin';

const config = {
input: './index.js',
output: {
file: './.build/bundle.js',
format: 'es',
},
// Ensure that the stylex plugin is used before Babel
plugins: [stylexPlugin({
// Required. File path for the generated CSS file.
fileName: './.build/stylex.css',
// default: false
dev: false,
// prefix for all generated classNames
classNamePrefix: 'x',
// Required for CSS variable support
unstable_moduleResolution: {
// type: 'commonJS' | 'haste'
// default: 'commonJS'
type: 'commonJS',
// The absolute path to the root directory of your project
rootDir: __dirname,
},
})],
};

export default config;
Webpack
npm install --save-dev @stylexjs/webpack-plugin
webpack.config.js
const StylexPlugin = require('@stylexjs/webpack-plugin');
const path = require('path');

const config = (env, argv) => ({
entry: {
main: './src/index.js',
},
output: {
path: path.resolve(__dirname, '.build'),
filename: '[name].js',
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: 'babel-loader',
},
],
},
plugins: [
// Ensure that the stylex plugin is used before Babel
new StylexPlugin({
filename: 'styles.[contenthash].css',
// get webpack mode and set value for dev
dev: argv.mode === 'development',
// Use statically generated CSS files and not runtime injected CSS.
// Even in development.
runtimeInjection: false,
// optional. default: 'x'
classNamePrefix: 'x',
// Required for CSS variable support
unstable_moduleResolution: {
// type: 'commonJS' | 'haste'
// default: 'commonJS'
type: 'commonJS',
// The absolute path to the root directory of your project
rootDir: __dirname,
},
}),
],
cache: true,
});

module.exports = config;
Next.js
npm install --save-dev @stylexjs/nextjs-plugin @stylexjs/babel-plugin rimraf
package.json
{
"scripts": {
...,
"predev": "rimraf .next",
"prebuild": "rimraf .next"
}
}
.babelrc.js
module.exports = {
presets: ["next/babel"],
plugins: [
[
"@stylexjs/babel-plugin",
{
dev: process.env.NODE_ENV === "development",
test: process.env.NODE_ENV === "test",
runtimeInjection: false,
genConditionalClasses: true,
treeshakeCompensation: true,
unstable_moduleResolution: {
type: "commonJS",
rootDir: __dirname,
},
},
],
],
};
next.config.mjs
/** @type {import('next').NextConfig} */
import stylexPlugin from "@stylexjs/nextjs-plugin";

const nextConfig = {};

const __dirname = new URL(".", import.meta.url).pathname;
export default stylexPlugin({
rootDir: __dirname,
})(nextConfig);
esbuild
npm install --save-dev @stylexjs/esbuild-plugin
build.mjs
import esbuild from 'esbuild';
import stylexPlugin from '@stylexjs/esbuild-plugin';
import path from 'path';
import { fileURLToPath } from 'url';

const __dirname = path.dirname(fileURLToPath(import.meta.url));

esbuild.build({
entryPoints: ['src/index.js'],
bundle: true,
outfile: './build/bundle.js',
minify: true,
plugins: [
stylexPlugin({
// If set to 'true', bundler will inject styles in-line
// Do not use in production
dev: false,
// Required. File path for the generated CSS file
generatedCSSFileName: path.resolve(__dirname, 'build/stylex.css'),
// Aliases for StyleX package imports
// default: '@stylexjs/stylex'
stylexImports: ['@stylexjs/stylex'],
// Required for CSS variable support
unstable_moduleResolution: {
// type: 'commonJS' | 'haste'
// default: 'commonJS'
type: 'commonJS',
// The absolute path to the root of your project
rootDir: __dirname,
},
}),
],
})

Please refer to the StyleX examples apps for demonstrations on how to use each of these plugins.

Local development only

Do not use in Production

You should not use @stylexjs/dev-runtime in production. It has a significant performance cost and should only be used for local development without a compiler. This runtime lacks features otherwise available when using the compiler.

To start using StyleX without having to configure a compiler and build process, you can install the local development runtime.

npm install --save-dev @stylexjs/dev-runtime

You must configure the runtime and use the returned StyleX API in the rest of your code.

import makeStyleX from '@stylexjs/dev-runtime';

export const stylex = makeStyleX({
classNamePrefix: 'x',
dev: true,
test: false,
});

Catch mistakes with ESLint

The StyleX compiler does not validate your styles and will compile many invalid styles. You should use the ESLint plugin to catch these mistakes when you author your styles.

npm install --save-dev @stylexjs/eslint-plugin
.eslintrc.js
module.exports = {
plugins: ["@stylexjs"],
rules: {
"@stylexjs/valid-styles": "error",
},
};