What is mini-css-extract-plugin?
The mini-css-extract-plugin is a plugin for webpack that extracts CSS into separate files. It creates a CSS file per JS file which contains CSS. It supports on-demand-loading of CSS and SourceMaps. It requires webpack 4 to function.
What are mini-css-extract-plugin's main functionalities?
Extract CSS into separate files
This feature allows you to extract CSS from your bundle into a separate file, which can be loaded independently.
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader'
]
}
]
},
plugins: [
new MiniCssExtractPlugin({
filename: '[name].css',
chunkFilename: '[id].css'
})
]
};
Lazy loading of CSS files
This feature enables on-demand loading of CSS by splitting the CSS into chunks and loading them when needed.
import(/* webpackChunkName: 'style' */ './style.css').then(() => {
// Use style.css
});
SourceMap support
This feature allows you to generate source maps for the CSS files, which is helpful for debugging purposes.
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
sourceMap: true
}
},
{
loader: 'css-loader',
options: {
sourceMap: true
}
}
]
}
]
},
plugins: [
new MiniCssExtractPlugin({
filename: '[name].css',
chunkFilename: '[id].css'
})
]
};
Other packages similar to mini-css-extract-plugin
extract-text-webpack-plugin
This package is similar to mini-css-extract-plugin but was used for webpack 3 and earlier. It is now deprecated in favor of mini-css-extract-plugin, which is designed for webpack 4 and later.
style-loader
This package injects CSS into the DOM using multiple <style> tags. It is often used in development environments for hot module replacement but does not extract CSS into separate files.
sass-loader
While sass-loader itself does not extract CSS, it is commonly used in conjunction with mini-css-extract-plugin to compile Sass/SCSS files into CSS and then extract it into separate files.
This plugin extracts CSS into separate files. It creates a CSS file per JS file which contains CSS. It supports On-Demand-Loading of CSS and SourceMaps.
It builds on top of a new webpack v4 feature (module types) and requires webpack 4 to work.
Compared to the extract-text-webpack-plugin:
- Async loading
- No duplicate compilation (performance)
- Easier to use
- Specific to CSS
TODO:
Install
npm install --save-dev mini-css-extract-plugin
Usage
Configuration
Minimal example
webpack.config.js
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
plugins: [
new MiniCssExtractPlugin({
filename: "[name].css",
chunkFilename: "[id].css"
})
],
module: {
rules: [
{
test: /\.css$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
publicPath: '../'
}
},
"css-loader"
]
}
]
}
}
Advanced configuration example
This plugin should be used only on production
builds without style-loader
in the loaders chain, especially if you want to have HMR in development
.
Here is an example to have both HMR in development
and your styles extracted in a file for production
builds.
(Loaders options left out for clarity, adapt accordingly to your needs.)
webpack.config.js
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const devMode = process.env.NODE_ENV !== 'production'
module.exports = {
plugins: [
new MiniCssExtractPlugin({
filename: devMode ? '[name].css' : '[name].[hash].css',
chunkFilename: devMode ? '[id].css' : '[id].[hash].css',
})
],
module: {
rules: [
{
test: /\.(sa|sc|c)ss$/,
use: [
devMode ? 'style-loader' : MiniCssExtractPlugin.loader,
'css-loader',
'postcss-loader',
'sass-loader',
],
}
]
}
}
Minimizing For Production
While webpack 5 is likely to come with a CSS minimizer built-in, with webpack 4 you need to bring your own. To minify the output, use a plugin like optimize-css-assets-webpack-plugin. Setting optimization.minimizer
overrides the defaults provided by webpack, so make sure to also specify a JS minimizer:
webpack.config.js
const UglifyJsPlugin = require("uglifyjs-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin");
module.exports = {
optimization: {
minimizer: [
new UglifyJsPlugin({
cache: true,
parallel: true,
sourceMap: true
}),
new OptimizeCSSAssetsPlugin({})
]
},
plugins: [
new MiniCssExtractPlugin({
filename: "[name].css",
chunkFilename: "[id].css"
})
],
module: {
rules: [
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
"css-loader"
]
}
]
}
}
Features
Using preloaded or inlined CSS
The runtime code detects already added CSS via <link>
or <style>
tag.
This can be useful when injecting CSS on server-side for Server-Side-Rendering.
The href
of the <link>
tag has to match the URL that will be used for loading the CSS chunk.
The data-href
attribute can be used for <link>
and <style>
too.
When inlining CSS data-href
must be used.
Similar to what extract-text-webpack-plugin does, the CSS
can be extracted in one CSS file using optimization.splitChunks.cacheGroups
.
webpack.config.js
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
optimization: {
splitChunks: {
cacheGroups: {
styles: {
name: 'styles',
test: /\.css$/,
chunks: 'all',
enforce: true
}
}
}
},
plugins: [
new MiniCssExtractPlugin({
filename: "[name].css",
})
],
module: {
rules: [
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
"css-loader"
]
}
]
}
}
You may also extract the CSS based on the webpack entry name. This is especially useful if you import routes dynamically
but want to keep your CSS bundled according to entry. This also prevents the CSS duplication issue one had with the
ExtractTextPlugin.
const path = require('path');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
function recursiveIssuer(m) {
if (m.issuer) {
return recursiveIssuer(m.issuer);
} else if (m.name) {
return m.name;
} else {
return false;
}
}
module.exports = {
entry: {
foo: path.resolve(__dirname, 'src/foo'),
bar: path.resolve(__dirname, 'src/bar')
},
optimization: {
splitChunks: {
cacheGroups: {
fooStyles: {
name: 'foo',
test: (m,c,entry = 'foo') => m.constructor.name === 'CssModule' && recursiveIssuer(m) === entry,
chunks: 'all',
enforce: true
},
barStyles: {
name: 'bar',
test: (m,c,entry = 'bar') => m.constructor.name === 'CssModule' && recursiveIssuer(m) === entry,
chunks: 'all',
enforce: true
}
}
}
},
plugins: [
new MiniCssExtractPlugin({
filename: "[name].css",
})
],
module: {
rules: [
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
"css-loader"
]
}
]
}
}
Long Term Caching
For long term caching use filename: "[contenthash].css"
. Optionally add [name]
.
Maintainers
License