npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@stylexswc/unplugin

v0.18.0

Published

Universal StyleX plugin for Vite, webpack, Rspack, Rollup, esbuild, Farm, Rsbuild, Nuxt, and Astro, powered by a Rust NAPI-RS/SWC compiler.

Readme

@stylexswc/unplugin

Universal StyleX plugin for Vite, webpack, Rspack, Rollup, esbuild, Farm, Rsbuild, Nuxt, and Astro — powered by a Rust compiler (NAPI-RS + SWC). Part of the StyleX SWC Plugin workspace.

Built on unplugin, this package gives every major bundler the same StyleX integration: it compiles your StyleX code with @stylexswc/rs-compiler, a Rust implementation of the StyleX transform, and extracts the generated CSS. Your StyleX code stays exactly the same — only the build step changes, with per-file transforms 2x to 5x faster than Babel (performance).

This is a community project and is not affiliated with Meta. It tracks the official StyleX releases

and requires Node.js 20 or newer.

Installation

npm install --save-dev @stylexswc/unplugin

The Rust compiler (@stylexswc/rs-compiler) is installed automatically as a dependency. Your application still needs the StyleX runtime:

npm install @stylexjs/stylex

Usage

Import the entry point matching your build tool and add it to the plugin list. A working example for each bundler lives in the apps/{pluginName}-unplugin-example folders.

// vite.config.ts
import StylexRsPlugin from '@stylexswc/unplugin/vite';

export default defineConfig({
  plugins: [StylexRsPlugin({/* options */})],
});

// rollup.config.js
import StylexRsPlugin from '@stylexswc/unplugin/rollup';

export default {
  plugins: [StylexRsPlugin({/* options */})],
};

// webpack.config.js
module.exports = {
  /* ... */
  plugins: [require('@stylexswc/unplugin/webpack')({/* options */})],
};

// rspack.config.js
module.exports = {
  /* ... */
  plugins: [require('@stylexswc/unplugin/rspack')({/* options */})],
};

// nuxt.config.js
export default defineNuxtConfig({
  modules: [['@stylexswc/unplugin/nuxt', {/* options */}]],
});

This module works for both Nuxt 2 and Nuxt Vite

// vue.config.js
module.exports = {
  configureWebpack: {
    plugins: [require('@stylexswc/unplugin/webpack')({/* options */})],
  },
};

// esbuild.config.js
import { build } from 'esbuild';
import StylexRsPlugin from '@stylexswc/unplugin/esbuild';

build({
  plugins: [StylexRsPlugin()],
});

Plugin Options

Basic Options

rsOptions

  • Type: Partial<StyleXOptions>
  • Optional
  • Description: StyleX compiler options passed to @stylexswc/rs-compiler. For the standard options, see the official StyleX documentation.

[!NOTE] The include and exclude options are exclusive to the Rust compiler and are not available in the official StyleX Babel plugin.

rsOptions.include
  • Type: (string | RegExp)[]
  • Optional
  • Description: Glob patterns or regular expressions selecting the files to transform. When specified, only files matching at least one pattern are transformed. Patterns are matched against paths relative to the current working directory.
rsOptions.exclude
  • Type: (string | RegExp)[]
  • Optional
  • Description: Glob patterns or regular expressions excluding files from the transform. A file matching any exclude pattern is skipped even if it matches an include pattern. Patterns are matched against paths relative to the current working directory.

fileName

  • Type: string
  • Default: 'stylex.css'
  • Description: Name of the generated CSS file.

useCSSLayers

  • Type: UseLayersType
  • Default: false
  • Description: Wraps the generated CSS in cascade layers for better style isolation.

extractCSS

  • Type: boolean
  • Default: true
  • Description: Controls whether the generated CSS is extracted into a separate file.

pageExtensions

  • Type: string[]
  • Default: ['js', 'jsx', 'ts', 'tsx', 'mjs', 'mts']
  • Description: File extensions to process for StyleX transformations.

transformCss

  • Type: CSSTransformer
  • Optional
  • Description: Transforms the extracted StyleX CSS before it is emitted or injected. Matches the @stylexswc/webpack-plugin API. Use it to run the generated CSS through PostCSS, Lightning CSS, a minifier, or any custom post-processing step.
type CSSTransformer = (
  css: string,
  filePath: string | undefined
) => string | Buffer | Promise<string | Buffer>;
import postcss from 'postcss';
import autoprefixer from 'autoprefixer';

StylexRsPlugin({
  async transformCss(css) {
    const result = await postcss([autoprefixer]).process(css, {
      from: undefined,
    });
    return result.css;
  },
});

The filePath argument identifies the CSS destination and is bundler-specific:

  • webpack/rspack/rollup injection: the output asset name (e.g. app.css)
  • esbuild disk writes: the absolute path of the written file
  • Vite placeholder replacement: the id of the CSS module being loaded
  • generated assets: the configured fileName, with [hash] left unresolved (the hash is computed from the transformed CSS, so it cannot be known earlier)
  • undefined when no destination is known

[!NOTE] Buffer results are decoded as UTF-8. Results are memoized per filePath while the input CSS is unchanged, so the callback must be a pure function of its arguments — the same input may be served from cache instead of invoking the callback again.

useCssPlaceholder

  • Type: boolean | string
  • Default: false
  • Description: Injects the generated CSS into an existing CSS file via a placeholder marker.
    • When set to true, the plugin looks for the default @stylex; marker
    • When set to a string, the plugin uses that string as the custom marker

Routing the StyleX output through a real CSS file has practical benefits:

  • The generated CSS goes through the bundler's CSS pipeline (PostCSS, Lightning CSS, css-loader, and so on)
  • Deterministic builds — no race conditions or hash instability from virtual modules
  • All CSS follows the same processing rules and bundling strategy
  • CSS can be code-split and optimized alongside other stylesheets
  • The same approach works for Vite, webpack, Rspack, esbuild, Rollup, and Farm

How to use it:

  1. Create a CSS file with a marker (e.g. global.css):
/* global.css */
:root {
  --brand-color: #663399;
}

body {
  margin: 0;
  font-family: system-ui, sans-serif;
}

@stylex;
  1. Import the CSS file in your entry point:
// src/main.ts
import './global.css';
import { App } from './App';
  1. Configure the plugin with useCssPlaceholder:
// vite.config.ts (or webpack.config.js, rspack.config.js, etc.)
import StylexRsPlugin from '@stylexswc/unplugin/vite';
import { defineConfig } from 'vite';

export default defineConfig({
  plugins: [
    StylexRsPlugin({
      useCssPlaceholder: true, // Uses default '@stylex;' marker
      useCSSLayers: true,
    }),
  ],
});

Or with a custom marker string:

/* global.css */
:root {
  --brand-color: #663399;
}

/* INJECT_STYLEX_HERE */
StylexRsPlugin({
  useCssPlaceholder: '/* INJECT_STYLEX_HERE */',
  useCSSLayers: true,
});

The plugin replaces the marker with the generated StyleX CSS during the build.

[!NOTE] When useCssPlaceholder is enabled, the plugin no longer injects CSS automatically into HTML or emits a separate stylex.css file. The CSS goes into your specified CSS file instead.

[!IMPORTANT] Migration from useViteCssPipeline

The useViteCssPipeline option (which used virtual CSS modules) has been replaced by useCssPlaceholder. The new approach uses real CSS files instead of virtual modules, which provides better compatibility across all bundlers, no race conditions or timing issues, and deterministic builds with stable hashes. To migrate, create a CSS file with a marker and set useCssPlaceholder: true (or use a custom marker string).

Example Configuration

// vite.config.ts
import StylexRsPlugin from '@stylexswc/unplugin/vite';
import { defineConfig } from 'vite';

export default defineConfig({
  plugins: [
    StylexRsPlugin({
      rsOptions: {
        dev: process.env.NODE_ENV !== 'production',
        include: ['src/**/*.{ts,tsx}', 'components/**/*.{ts,tsx}'],
        exclude: ['**/*.test.*', '**/*.stories.*', '**/__tests__/**'],
      },
      useCSSLayers: true,
      useCssPlaceholder: true,
    }),
  ],
});

Path Filtering Examples

Include only specific directories:

StylexRsPlugin({
  rsOptions: {
    include: ['src/**/*.tsx', 'app/**/*.tsx'],
  },
});

Exclude test and build files:

StylexRsPlugin({
  rsOptions: {
    exclude: ['**/*.test.*', '**/*.spec.*', '**/dist/**'],
  },
});

Exclude node_modules except specific packages (negative lookahead):

StylexRsPlugin({
  rsOptions: {
    exclude: [/node_modules(?!\/@stylexjs)/],
  },
});

Transform only specific packages from node_modules:

StylexRsPlugin({
  rsOptions: {
    include: [
      'src/**/*.{ts,tsx}',
      'node_modules/@stylexjs/open-props/**/*.js',
      'node_modules/@my-org/design-system/**/*.js',
    ],
    exclude: ['**/*.test.*'],
  },
});

Combined include and exclude (exclude takes precedence):

StylexRsPlugin({
  rsOptions: {
    include: ['src/**/*.{ts,tsx}'],
    exclude: ['**/__tests__/**', '**/__mocks__/**'],
  },
});

FAQ

Should I use this package or the bundler-specific plugin?

If you are on Vite, esbuild, Farm, Rsbuild, Nuxt, or Astro, this is the package to use. For webpack and Rspack, the dedicated @stylexswc/webpack-plugin and @stylexswc/rspack-plugin packages offer a few deeper integrations (loader ordering, cache groups); this plugin covers the common cases with one consistent API. For Next.js, use @stylexswc/nextjs-plugin.

Do I still need @stylexjs/babel-plugin?

No. This plugin replaces the Babel plugin in your build. You only keep @stylexjs/stylex as your app's runtime dependency, and your stylex.create / stylex.props code does not change.

How do I run the generated CSS through PostCSS or Tailwind pipelines?

Either pass a transformCss function, or enable useCssPlaceholder so the generated CSS lands in a real CSS file and flows through your bundler's normal CSS pipeline.

Does hot module replacement work?

Yes. The plugin participates in each bundler's standard transform pipeline, so style changes update through the dev server like any other module.

Is this an official StyleX package?

No. It is a community-maintained alternative to the official tooling and is not affiliated with or supported by Meta.

Documentation

License

MIT — see LICENSE