StyleX with Vite
@stylexjs/unplugin integrates directly with Vite to compile StyleX code,
aggregate the generated CSS, and append it to the CSS assets Vite emits. How you
load the CSS/runtime in development depends on whether your entry point is an
HTML file or a React (JS/TS) module.
Installation
Start by installing the StyleX unplugin package:
- npm
- pnpm
- yarn
- bun
npm install --save-dev @stylexjs/unplugin
pnpm add -D @stylexjs/unplugin
yarn add -D @stylexjs/unplugin
bun add -D @stylexjs/unplugin
Configuration
Add the plugin to your Vite configuration and provider the StyleX configuration options.
// vite.config.ts
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import stylex from '@stylexjs/unplugin';
export default defineConfig({
plugins: [
stylex.vite({
// StyleX configuration options
useCSSLayers: true,
dev: process.env.NODE_ENV === 'development',
runtimeInjection: false,
// ...
lightningcssOptions: {
// Options for lightningcss which postprocesses the generated CSS
}
}),
react()
],
});
CSS entrypoint
In almost all cases, it is useful to have at least one CSS file that is imported by a component that is part of every route, such as the root layout component. The StyleX unplugin package's vite plugin will inject the generated CSS in the existing CSS asset.
This CSS file is also a good place for any CSS resets or global styles that you may want.
Dev-server and Hot Reloading
If your Vite setup uses an HTML file as the entry point, you should not need any further build setup. However, if your entry point is a React component, you may need to load some virtual modules to enable hot reloading.
We recommend encapsulating this in a special client component file like this:
// src/app/DevStyleXInject.tsx
'use client';
import { useEffect } from 'react';
function DevStyleXInjectImpl() {
useEffect(() => {
if (import.meta.env.DEV) {
// @ts-ignore
import('virtual:stylex:css-only');
}
}, []);
return <link rel="stylesheet" href="/virtual:stylex.css" />;
}
export function DevStyleXInject({ cssHref }: { cssHref: string }) {
return import.meta.env.DEV ? (
<DevStyleXInjectImpl />
) : (
<link rel="stylesheet" href={cssHref} />
);
}
The dynamic import is wrapped in an additional check for import.meta.env.DEV to ensure that it is not bundled in production.
And then, this component can be used in the <head> section of your document layout component:
// src/app/Document.tsx (excerpt)
import { DevStyleXInject } from './DevStyleXInject';
export function Layout({ children }: { children: React.ReactNode }) {
return (
<html>
<head>
{/* ... */}
<DevStyleXInject cssHref="/stylex.css" />
{/* ... */}
</head>
<body>
<div id="root">{children}</div>
</body>
</html>
)
);
The virtual:stylex.css file will load the generated CSS, and the virtual:stylex:runtime file will
refetch it on every HTML event to enable hot reloading.
Framework-specific guides
Documentation for specific Vite-based setups and frameworks is provided in the following pages, along with smaller framework-specific details for each.