Webpack CSS extraction discussion
See original GitHub issueI really like the idea of compiled as you move as much css processing to the build step and shrink the runtime code to almost 0.
Only by a coincidence I noticed that you are trying to build a webpack plugin and would love to jump in…
My knowledge of compiled is quite limited so maybe my solution could be over simplified and might not cover all your requirements.
But so far the first POC is working with the following features:
- Entry Based Chunk Splitting (e.g. main.css and about-us.css)
- Lazy Chunk Splitting (e.g. load styles for a modal only once the modal opens)
- HMR
It works together with the following third party packages from the webpack ecosystem:
- MiniCssExtractPlugin (optional)
- HtmlWebpackPlugin (optional)
- PostCssLoader (optional)
- StyleLoader (optional)
- CssLoader
For the atomic loader flow I stole an idea from Tobias Koppers (the author of webpack)…
In case this idea works out a lot of credits go to him 😃
<u>👉 Webpack Config Demos (click to expand)</u>
Webpack config (dev):
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
devtool: false,
mode: 'development',
module: {
rules: [
{
test: /\.js$/i,
use: '@compiled/loader',
exclude: /node_modules/
},
{
test: /\.css$/i,
use: ["style-loader", "css-loader"],
},
],
},
plugins: [ new HtmlWebpackPlugin() ]
}
Webpack config (prod):
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
mode: 'production',
module: {
rules: [
{
test: /\.js$/i,
use: '@compiled/loader',
exclude: /node_modules/
},
{
test: /\.css$/i,
use: [MiniCssExtractPlugin.loader, 'css-loader'],
},
],
},
plugins: [new MiniCssExtractPlugin(), new HtmlWebpackPlugin()],
};
<u>👉 the POC of @compiled/loader (click to expand)</u>
I created a very very naive and simplified loader (~80 LOC) which is only able to extract from a styled components:
export const Button = styled.button`
border: none;
border-radius: 3px;
padding: 8px 10px;
background-color: #6554c0;
color: #fff;
font-weight: 400;
font-family: inherit;
font-size: 14px;
`
The compiled result:

The demo is also lazy loading a second component:
// After 2s load the header
setTimeout(() => {
import('./Header');
}, 2000);
The code for the header is also using the styled API:
export const Header = styled.header`
border: none;
background: purple;
color: #fff;
`
As you can see Header shares 2 atomic styles with Button.
Webpack will notices that and will create a second CSS file which will contain only the purple background color.
<u>👉 run the POC locally (click to expand)</u>
Run (dev server):
npm i
npm start
Build:
npm i
npm start
Although it is only a first draft I would love to know your feedback 😃
If you need any help to understand how exactly this draft works we could probably save some time with a screen sharing session - just ping me on twitter @jantimon - my DM is always open
Issue Analytics
- State:
- Created 3 years ago
- Reactions:8
- Comments:21

Top Related StackOverflow Question
@TxHawks yes that’s true - probably the only good way to find out is to use compiled on some larger projects…
Fela is all runtime, so it doesn’t grow beyond exactly what’s on the page at a given moment and therefore probably not a good comparison for this aspect of Complied.