Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/sukkaw/style9-webpack
The another Webpack Plugin for Atomic CSS-in-JS implementation style9
https://github.com/sukkaw/style9-webpack
atomic-css css css-in-js typescript webpack
Last synced: 12 days ago
JSON representation
The another Webpack Plugin for Atomic CSS-in-JS implementation style9
- Host: GitHub
- URL: https://github.com/sukkaw/style9-webpack
- Owner: SukkaW
- License: mit
- Created: 2023-01-14T06:44:18.000Z (almost 2 years ago)
- Default Branch: master
- Last Pushed: 2024-04-28T06:26:44.000Z (7 months ago)
- Last Synced: 2024-10-20T01:12:14.616Z (24 days ago)
- Topics: atomic-css, css, css-in-js, typescript, webpack
- Language: TypeScript
- Homepage: https://github.com/johanholmerin/style9
- Size: 678 KB
- Stars: 19
- Watchers: 3
- Forks: 3
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# style9-webpack
Created by Johan Holmerin, [style9](https://github.com/johanholmerin/style9) is a CSS-in-JS compiler inspired by Facebook's [stylex](https://www.youtube.com/watch?v=9JZHodNR184), 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](https://github.com/johanholmerin/style9/blob/master/docs/How-it-works.md).
style9 does provide a webpack plugin. It uses [`webpack-virtual-modules`](https://github.com/sysgears/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](https://github.com/vercel/next.js/issues/44266). 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](https://github.com/vanilla-extract-css/vanilla-extract), another CSS-in-JS compiler. You can find the implementation of Vanilla Extract's `virtualFileLoader` [here](https://github.com/vanilla-extract-css/vanilla-extract/blob/aabb5869a626b7d966814ec8bc322a0392b77561/packages/webpack-plugin/src/virtualFileLoader.ts).
**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:
```js
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:
```js
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](https://github.com/johanholmerin/style9/blob/master/docs/Bundler-plugins.md#gatsby) for usage with Gatsby.
## Installation
```sh
# NPM
npm i style9-webpack
# Yarn
yarn add style9-webpack
# PNPM
pnpm add style9-webpack
```## Usage
### Webpack
```js
// 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
```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.
```js
// 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](https://github.com/SukkaW), Released under the [MIT](./LICENSE) License.
Authored and maintained by Sukka with help from contributors ([list](https://github.com/SukkaW/style9-webpack/graphs/contributors)).> [Personal Website](https://skk.moe) · [Blog](https://blog.skk.moe) · GitHub [@SukkaW](https://github.com/SukkaW) · Telegram Channel [@SukkaChannel](https://t.me/SukkaChannel) · Twitter [@isukkaw](https://twitter.com/isukkaw) · Mastodon [@[email protected]](https://acg.mn/@sukka) · Keybase [@sukka](https://keybase.io/sukka)