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 🙏

© 2024 – Pkg Stats / Ryan Hefner

stylex-webpack

v0.3.2

Published

The another Webpack Plugin for Facebook's StyleX

Downloads

10,722

Readme

stylex-webpack

First introduced by Frank Yan at React Conf 2020, StyleX framework agnostic CSS-in-JS system with near-zero runtime, ahead-of-time compiler, atomic CSS extraction that powers Facebook and Instagram.

Motivation

stylex offers a CSS-in-JS compiler, allowing you to write CSS in your JavaScript/JSX/TSX. However, unlike other CSS-in-JS solutions that gather and process styles within the browser, stylex will read your source code, collect your style and transform your JS/JSX/TSX, stripping runtime calls as much as possible (making the value of className a static string literal), and output CSS elsewhere.

StyleX does provide a webpack plugin. Under the hood, it will traverse through the source code, collect styles, and emit a new CSS asset during the webpack compilation. However, it does come with some limitations:

  • StyleX's official Next.js setup requires a .babelrc file, which disables Next.js' built-in SWC compiler.
  • StyleX's official Next.js plugin requires a CSS asset to pre-exist so that it can append the extracted CSS to it.

I start this project as a Proof of Concept, to see if it is possible to make a webpack plugin for ststylex that doesn't disable Next.js' SWC compiler. I have already made a similar webpack plugin for style9, which is also an AoT atomic CSS-in-JS system that is inspired by StyleX.

Unlike stylex's official webpack plugin, stylex-webpack requires you have setup css-loader and MiniCssExtractPlugin in your webpack configuration, just like your normal CSS based webpack project. stylex-webpack's built-in loader will generate a virtual CSS import containing a dummy CSS rule. This allows the MiniCssExtractPlugin to collect those virtual CSS imports and emit a CSS asset, which stylex-webpack will later inject the actual extracted CSS into at the processAssets stage.

Installation

# npm
npm i stylex-webpack
# Yarn
yarn add stylex-webpack
# pnpm
pnpm add stylex-webpack

Usage

Webpack

// webpack.config.js
const { StyleXPlugin } = require('stylex-webpack');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

module.exports = {
  module: {
    rules: [
      // Just like your normal CSS setup, a css-loader and MiniCssExtractPlugin.loader
      {
        test: /\.css$/i,
        use: [MiniCssExtractPlugin.loader, 'css-loader']
      }
    ]
  },
  plugins: [
    new StyleXPlugin({
      // stylex-webpack options goes here, see the following section for more details
    }),
    new MiniCssExtractPlugin(),
    new CssMinimizerPlugin()
    // You can also use `LightningCssMinifyPlugin` from `lightningcss-loader`
    // to replace CssMinimizerPlugin for faster CSS minification
    // https://github.com/fz6m/lightningcss-loader
  ]
};

Next.js

// next.config.js
const { withStyleX } = require('stylex-webpack/next');

module.exports = withStyleX({
  // stylex-webpack options goes here, see the following section for more details
})({
  // Your Next.js config goes here.
  reactStrictMode: true
});

Options

webpack

new StyleXPlugin({
  // stylex-webpack options

  /**
   * stylex options passed to stylex babel plugin
   *
   * @see https://stylexjs.com/docs/api/configuration/babel-plugin/
   */
  stylexOption: {
    dev: process.env.NODE_ENV === 'development',
    test: process.env.NODE_ENV === 'test'
    // Check the stylex documentation for more options
  },
  /* Specify where stylex will be imported from
   * This overrides `importSources` in the `stylexOption` above
   *
   * @default ['stylex', '@stylexjs/stylex']
   */
  stylexImports: ['stylex', '@stylexjs/stylex'],
  /**
   * Whether to use CSS layers
   *
   * @default false
   */
  useCSSLayers?: boolean,
  /**
   * Enable other CSS transformation
   *
   * Since stylex-webpack's loader only emit virtual CSS imports with dummy rules,
   * while the actual CSS is injected by the plugin after all loaders, you can not
   * use postcss-loader + PostCSS plugins. You can manually transform the CSS here.
   */
  transformCss(css) {
    const postcss = require('postcss');
    const autoprefixer = require('autoprefixer');
    /**
     * It is a known issue that stylex won't sort your at-rules and media queries.
     *
     * https://github.com/facebook/stylex/issues/455
     * https://github.com/facebook/stylex/issues/517
     *
     * For now, it is recommended to use postcss-sort-media-queries as a workaround.
     */
    const sortMediaQueries = require('postcss-sort-media-queries');

    return postcss([
      autoprefixer({
        // autoprefixer options
      }),
      sortMediaQueries({
        sort: 'mobile-first'
      })
    ]).process(css, { from: undefined }).css;

    // If you don't use custom PostCSS plugins (like `postcss-sort-media-queries`
    // mentioned above), only downleveling CSS syntax using autoprefixer, you can
    // also use LightningCSS. It is a Rust-based CSS transformer and minifier that
    // has built-in downleveling support.
    const browserslist = require('browserslist');
    const { transform, browserslistToTargets } = require('lightningcss');
    return transform({
      code: Buffer.from(css),
      targets: browserslistToTargets(browserslist('>= 0.25%'))
    }).code;

    // If you don't need to transform CSS at all, you can just return the input as-is as well.
    return css;
  }
});

Next.js

withStyleX({
  // The same options as the webpack plugin, but with a few differences
  stylexOption: {
    /**
     * You don't have to specify `dev` here. `stylex-webpack` will automatically read
     * Next.js building mode and set `dev` accordingly.
     */
    // dev: process.env.NODE_ENV === 'development',
  },
  /**
   * You don't have to specify `transformCss` here. `stylex-webpack` will automatically
   * read your PostCSS configuration and apply it here, just like how Next.js does.
   *
   * Under the hood, `withStyleX` uses Next.js built-in PostCSS config reader to
   * maintain the consistency with Next.js' built-in PostCSS support.
   */
  // transformCss(css) {}
})

It is recommended to use postcss-sort-media-queries as a workaround for stylex's known issue with sorting at-rules and media queries. You can configure it in your PostCSS configuration file, and stylex-webpack will automatically apply your PostCSS configuration to the extracted CSS just like Next.js' built-in PostCSS support.

// postcss.config.js

/** @type {Record<'plugins', import('postcss').AcceptedPlugin[]>} */
module.exports = {
  plugins: [
    [
      require.resolve('postcss-sort-media-queries'),
      {
        sort: 'mobile-first' // default value
      }
    ],

    // Next.js will disable its built-in default PostCSS configuration you
    // create `postcss.config.js`, which you can add it back:

    /* --- Start of Next.js built-in default PostCSS configuration --- */
    require.resolve('next/dist/compiled/postcss-flexbugs-fixes'),
    [
      require.resolve('next/dist/compiled/postcss-preset-env'),
      {
        browsers: ['defaults'],
        autoprefixer: {
          // Disable legacy flexbox support
          flexbox: 'no-2009'
        },
        // Enable CSS features that have shipped to the
        // web platform, i.e. in 2+ browsers unflagged.
        stage: 3,
        features: {
          'custom-properties': false
        }
      }
    ]
    /* --- End of Next.js built-in default PostCSS configuration --- */
  ]
};

Author

stylex-webpack © Sukka, Released under the MIT License. Authored and maintained by Sukka with help from contributors (list).

Personal Website · Blog · GitHub @SukkaW · Telegram Channel @SukkaChannel · Twitter @isukkaw · Mastodon @[email protected] · Keybase @sukka