I'll admit, it's not a catchy name. Compatible with Webpack 1.x and 2.x.
Sometimes you want to separate your monolithic stylesheets into multiple files; maybe to excise critical styles or split into lazy loadable bundles.
To do this you need multiple entry points and so any context created while building each stylesheet is lost. For a flat dependency tree this may not be a problem but for more complex projects where multiple components share dependencies it can be; think duplicated output and context switching to check where or if a dependency is already used... not fun!
This plugin enables you to maintain a single entry point but mark specific blocks of rules to be extracted into separate files.
First install the plugin and save it to your package manifest dev dependencies:
npm i --save-dev extract-css-block-webpack-plugin
Next apply the plugin via your webpack config. The plugin can only be used with separate stylesheets and therefore must be added after the extract text plugin:
const ExtractCssBlockPlugin = require('extract-css-block-webpack-plugin')
const ExtractTextPlugin = require('extract-text-webpack-plugin')
module.exports = {
...
module: {
loaders: [
{
test: /\.css$/,
loader: ExtractTextPlugin.extract(['css', 'sass'])
}
]
},
plugins: [
new ExtractTextPlugin('[name]'),
new ExtractCssBlockPlugin()
]
}
The plugin accepts a map of options, currently there is only one:
Option | Description | Default |
---|---|---|
match |
Filters files to transform | /\.css$/ |
To mark blocks of rules as targets for extraction use 'loud' (!
) start and end comments. For example, given this Sass main.scss
entry point:
@import "shared-ui/variables";
@import "shared-ui/functions";
@import "shared-ui/mixins";
/*! start:critical.css */
@import "shared-ui/component/normalize";
@import "shared-ui/component/grid";
@import "shared-ui/component/typography";
/*! end:critical.css */
@import "component/tabs";
@import "component/modal";
@import "layout/list-page";
@import "layout/content-page";
/*! start:comments.css */
@import "component/comments";
@import "component/comment-form";
/*! end:comments.css */
Webpack will write 3 stylesheets:- main.css
, critical.css
and comments.css
.
Blocks may be nested:
/*! start:header.css */
.header {
padding: 10px 20px;
background: #333;
color: #FFF;
}
/*! start:header-menu.css */
.header-menu {
list-style: none;
margin: 0 15px;
}
/*! end:header-menu.css */
.header-logo {
float: left;
border: 0;
}
/*! end:header.css */
Blocks may also be used many times and their contents will be aggregated:
/*! start:header.css */
.header {
padding: 10px 20px;
background: #333;
color: #FFF;
}
/*! end:header.css */
.header-menu {
list-style: none;
margin: 0 15px;
}
/*! start:header.css */
.header-logo {
float: left;
border: 0;
}
/*! end:header.css */
To enable source maps ensure that webpack, the CSS plugin and any preceeding pre-processors have source maps enabled:
module.exports = {
...
module: {
loaders: [
{
test: /\.css$/,
loader: ExtractTextPlugin.extract(['css?sourceMap', 'sass?sourceMap'])
}
]
},
devtool: 'source-map'
}
There is a PostCSS version of this plugin available but as PostCSS is not designed to write multiple files it is a bit hacky.