style9-webpack
v0.5.2
Published
The another Webpack Plugin for Atomic CSS-in-JS implementation style9
Downloads
2,657
Maintainers
Readme
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 https://github.com/SukkaW/style9-webpack/issues/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