Giter Site home page Giter Site logo

sukkaw / style9-webpack Goto Github PK

View Code? Open in Web Editor NEW
18.0 3.0 2.0 694 KB

The another Webpack Plugin for Atomic CSS-in-JS implementation style9

Home Page: https://github.com/johanholmerin/style9

License: MIT License

TypeScript 98.70% JavaScript 0.65% CSS 0.64%
css typescript css-in-js webpack atomic-css

style9-webpack's Introduction

style9-webpack

Created by Johan Holmerin, style9 is a CSS-in-JS compiler inspired by Facebook's stylex, with near-zero runtime, atomic CSS extraction, and TypeScript support. Framework agnostic.

style9-webpack is an alternative webpack plugin for style9.

Motivation

ATTENTION! Please please please read this first before you install style9-webpack!

style9 is a CSS-in-JS compiler, which means you will write your CSS in your JavaScript/JSX/TSX. But unlike other CSS-in-JS solutions, style9 provides an AoT Compiler. style9 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. For more details about how style9 works, please check out style9's documentation.

style9 does provide a webpack plugin. It uses webpack-virtual-modules under the hood. During the compilation, style9 collects your styles and writes collected CSS into virtual modules. MiniCssExtractPlugin later will extract those virtual css files.

However, webpack-virtual-modules doesn't work well with Next.js. Next.js launches multiple webpack compiler instances to compile its server-side and client-side code separately. And webpack-virtual-modules just doesn't work when it is being shared between multiple webpack compiler instances.

I start this project as a Proof of Concept, to see if it is possible to make a webpack plugin for style9 that doesn't require webpack-virtual-modules. I use the virtualFileLoader idea from Vanilla Extract, another CSS-in-JS compiler. You can find the implementation of Vanilla Extract's virtualFileLoader here.

You most likely want to use style9's built-in webpack plugin instead. It works well for most cases. style9-webpack is just a Proof of Concept. But if you are using Next.js 13, and you are having trouble with style9's built-in Next.js plugin, you can give style9-webpack a shot.

Differences

The main differences between style9's built-in webpack plugin and style9-webpack are as follows:

style9-webpack loader doesn't have an inlineLoader option

style9's built-in webpack loader has an inlineLoader option. It allows you to chain other webpack loaders (like css-loader) to process the collected virtual css, like this:

module.exports = {
  module: {
    rules: [
      {
        test: /\.(tsx|ts|js|mjs|jsx)$/,
        use: [{
          loader: Style9Plugin.loader,
          options: {
            inlineLoader: `!${MiniCssExtractPlugin.loader}!css-loader`,
            ...otherStyle9Options
          }
        }]
      }
      // ...
    ];
  });
}

style9-webpack doesn't support this approach. Instead, you will need add an extra rule to provide your loaders:

module.exports = {
  module: {
    rules: [
      {
        test: /\.(tsx|ts|js|mjs|jsx)$/,
        use: [{
          loader: Style9Plugin.loader,
          options: {
            // Now style9-webpack will use "xxxx.style9.css" as the virtual css filenames
            virtualFileName: '[path][name].[hash:base64:7].style9.css',
            ...otherStyle9Options
          }
        }]
      },
      // And you create another rule to match the virtual css files. Now you can apply loaders to them.
      {
        test: /\.style9.css$/i,
        use: [MiniCssExtractPlugin.loader, 'css-loader']
      },
      // ...
    ];
  });
}

style9-webpack doesn't support Gatsby

You should use style9's built-in gatsby plugin instead. See style9's documentation for usage with Gatsby.

Installation

# NPM
npm i style9-webpack
# Yarn
yarn add style9-webpack
# PNPM
pnpm add style9-webpack

Usage

Webpack

// webpack.config.js
const Style9Plugin = require('style9-webpack');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

module.exports = {
  // Collect all styles in a single file - required
  optimization: {
    splitChunks: {
      cacheGroups: {
        styles: {
          name: 'styles',
          type: 'css/mini-extract',
          chunks: 'all',
          enforce: true,
        }
      }
    }
  },
  module: {
    rules: [
      {
        test: /\.(tsx|ts|js|mjs|jsx)$/,
        use: Style9Plugin.loader,
        options: {
          virtualFileName: '[path][name].[hash:base64:7].style9.css', // {string?} optional, default is '[path][name].style9.css'
          parserOptions: {}, // {import('@babel/core').ParserOptions} optional, default is `{ plugins: ['typescript', 'jsx'] }`
          minifyProperties: process.env.NODE_ENV === 'production', // {boolean?} optional, default is false, recommended to enable this option in production
          incrementalClassnames: false, // {boolean?} optional, default is false
        }
      },
      {
        test: /\.style9.css$/i,
        use: [MiniCssExtractPlugin.loader, 'css-loader']
      }
    ]
  },
  plugins: [
    new Style9Plugin(),
    new MiniCssExtractPlugin()
  ]
};

Next.js

// next.config.js
const withStyle9 = require('style9-webpack/next');

module.exports = withStyle9({
  parserOptions: {}, // // {import('@babel/core').ParserOptions} optional, default is `{ plugins: ['typescript', 'jsx'] }`
  minifyProperties: process.env.NODE_ENV === 'production', // {boolean?} optional, default is false, recommended to enable this option in production
  incrementalClassnames: false, // {boolean?} optional, default is false
})({
  // Your Next.js config goes here.
});

Next.js (appDir)

Currently, style9-webpack/next doesn't work well with Next.js appDir when "style9.create" is used in Server Components, due to a Next.js internal implementation detail. See #1 for more information.

In the meantime, you can use style9-webpack/next-appdir instead. It is a plugin specially designed to workaround the Next.js internal implementation quirk and can work with Next.js 13 beta appDir perfectly.

// next.config.js
const withStyle9 = require('style9-webpack/next-appdir');

module.exports = withStyle9({
  parserOptions: {}, // // {import('@babel/core').ParserOptions} optional, default is `{ plugins: ['typescript', 'jsx'] }`
  minifyProperties: process.env.NODE_ENV === 'production', // {boolean?} optional, default is false, recommended to enable this option in production
  incrementalClassnames: false, // {boolean?} optional, default is false
})({
  // Your Next.js config goes here.
});

Author

style9-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

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.