Skip to main content

@stylexjs/unplugin

Universal bundler plugin for StyleX built on top of unplugin. It compiles StyleX modules, aggregates the generated CSS, and appends the result to an emitted CSS asset (or creates stylex.css as a fallback). Adapters are available for Vite/Rollup, Webpack/Rspack, and esbuild.

Install:

npm i -D @stylexjs/unplugin

Usage by bundler

Vite

// vite.config.ts
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import stylex from '@stylexjs/unplugin';

export default defineConfig({
plugins: [stylex.vite({ useCSSLayers: true }), react()],
});
  • Keep stylex.vite() before framework plugins to preserve Fast Refresh.
  • Provide a CSS entry so Vite emits an asset for the plugin to append to.
  • Dev virtual modules:
    • /virtual:stylex.css — aggregated CSS endpoint.
    • virtual:stylex:runtime — JS runtime for hot CSS reloads.
    • virtual:stylex:css-only — JS shim that only triggers CSS reloads. Add <link rel="stylesheet" href="/virtual:stylex.css" /> and either a <script type="module" src="/@id/virtual:stylex:runtime"> tag or a import('virtual:stylex:runtime') call from a client shim in dev.

Webpack

// webpack.config.js
const stylex = require('@stylexjs/unplugin').default;
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

module.exports = {
module: {
rules: [
// JS/TS loader here
{ test: /\.css$/, use: [MiniCssExtractPlugin.loader, 'css-loader'] },
],
},
plugins: [stylex.webpack({ useCSSLayers: true }), new MiniCssExtractPlugin()],
};

Use a CSS extractor so Webpack emits a stylesheet for StyleX to append to.

Rspack

const rspack = require('@rspack/core');
const stylex = require('@stylexjs/unplugin').default;

module.exports = {
plugins: [
stylex.rspack({}),
new rspack.CssExtractRspackPlugin({ filename: 'index.css' }),
],
};

Rollup

// rollup.config.mjs
import stylex from '@stylexjs/unplugin';

export default {
plugins: [stylex.rollup({ useCSSLayers: true })],
};

esbuild

import esbuild from 'esbuild';
import stylex from '@stylexjs/unplugin';

esbuild.build({
entryPoints: ['src/App.jsx'],
bundle: true,
metafile: true, // lets the plugin find CSS outputs
plugins: [stylex.esbuild({ useCSSLayers: true })],
});

Options (shared)

All options from @stylexjs/babel-plugin are forwarded. The unplugin adds:

  • dev (boolean): defaults to NODE_ENV === 'development'. Forces dev or prod transforms.
  • importSources (string[] | {from: string, as: string}[], default ['stylex', '@stylexjs/stylex']): packages that export StyleX APIs. Also used to auto-exclude dependencies from Vite optimizeDeps/SSR.
  • useCSSLayers (boolean, default false): wrap output in @layer blocks.
  • enableLTRRTLComments (boolean): include /* @ltr */ and /* @rtl */ annotations when emitting directional CSS.
  • legacyDisableLayers (boolean): disable layer usage when emitting CSS (legacy behavior).
  • lightningcssOptions (object): passthrough options for lightningcss.
  • cssInjectionTarget ((fileName: string) => boolean): pick which emitted CSS asset to append to. Defaults to preferring index.css/style.css or the first CSS asset; falls back to creating stylex.css if none exist.
  • externalPackages (string[], default []): additional packages inside node_modules that should be transformed as if they were app code (useful if they ship StyleX).
  • devPersistToDisk (boolean, default false, Vite): persist collected rules to node_modules/.stylex/rules.json so multiple dev environments (RSC/SSR) can share CSS.
  • devMode ('full' | 'css-only' | 'off', default 'full', Vite): controls which dev middleware/virtual modules are exposed.
  • treeshakeCompensation (boolean): adds a safe side-effect import to prevent bundlers from removing StyleX themes/vars. Defaults to true for Vite/Rollup adapters.

Notes

  • Each output bundle receives its own aggregated StyleX CSS. When no CSS asset exists, the plugin emits stylex.css alongside the bundle.
  • When using CSS extraction plugins (Webpack/Rspack), ensure they run so there is a concrete stylesheet to append to.
  • For dev HMR, include the virtual stylesheet link in your HTML shell. If script tags are blocked by your framework’s asset handling, import the runtime from a tiny client shim instead of using a <script src> tag.