mini-css-extract-plugin在webpack4中代替extract-text-webpack-plugin,此插件是将 CSS 样式提取到单独的文件中。 它为每个包含 CSS 的 JS 文件创建一个 CSS 文件。即通过 JS 文件中import进来的样式文件。它支持CSS和SourceMaps的按需加载。
是建立在新的webpack v4功能(模块类型)之上,并且需要在webpack 4版本才能工作。
相比extract-text-webpack-plugin:
- 异步加载
- 没有重复的编译(性能)
- 更容易使用
- 特定于CSS
基本配置如下(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: {
// 公共路径
// 默认情况下,使用的是webpackOptions.output中publicPath
publicPath: '../',
//开发环境配置热更新
hmr: process.env.NODE_ENV === 'development',
},
},
'css-loader',
}
]
}
}
高级配置如下(既可以在开发中使用 HMR,也可以在生成版本的文件中提取样式):
//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].js' : '[name].[hash].css',
chunkFilename: devMode ? '[id].css' : '[name].[hash].css',
});
],
module: {
rules: [
{
test: /\.(sa|sc|c)ss$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
hmr: process.env.NODE_ENV === ‘development’
}
},
'css-loader',
'postcss-loader',
'sass-loader'
]
}
]
}
}
生产环境优化压缩(production)
缩小输出,要使用像optimize-css-assets-webpack-plugin这样的插件。 设置optimization.minimizer会覆盖 webpack 提供的默认值,因此确保要指定JS minimalizer:
//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({
include: /\/src/,
exclude: /\/excludes/,
cache: true,
sourceMap: true,
parallel: true,//多进程并行运行
comments: false, //禁止构建注释
}), new OptimizeCSSAssetsPlugin({})],
},
plugins: [
new MiniCssExtractPlugin({
filename: '[name].css',
chunkFilename: '[id].css',
}),
],
module: {
rules: [
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, 'css-loader'],
},
],
},
};
将所有 CSS 样式提取到单个文件中,与extract-text-webpack-plugin类似,可以使用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'],
},
],
},
};
还可以根据 webpack 的 entry name 来提取CSS,这对你动态引入路由,却想依据 entry 保存打包的 CSS 的情况十分有用。这也解决了 ExtractTextPlugin 中 CSS 重复的问题。
//webpack.config.js
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'],
},
],
},
};
特别注意:
For long term caching use filename: "[contenthash].css". Optionally add [name].
需要使用长缓存的,命名要使用 contenthash,如果直接使用 hash 的话,在 js 有改动,样式没有变动的情况下,css 会被重新打包生成新的 hash 值,这显然不是我们想要的,所以这里生产环境用 contenthash,确保 css 文件在没有改动的情况下,使用缓存文件。
参考:
https://www.npmjs.com/package/mini-css-extract-plugin