这个插件将CSS提取到单独的文件中。它为每个包含CSS的JS文件创建一个CSS文件。CSS支持按需加载和源映射。
它建立在新的webpackv4特性(模块类型)之上,需要webpack4才能工作。
与extract-text-webpack-plugin插件相比:
-
异步加载
-
无重复编译(性能)
-
更易于使用
-
特定于CSS
开始
首先,您需要安装mini-css-extract-plugin
npm install --save-dev mini-css-extract-plugin
建议将mini-css-extract-plugin和css-loader结合使用
然后将加载程序和插件添加到您的webpack配置中。例如:
style.css
body {
background: green;
}
component.js
import './style.css';
webpack.config.js
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
plugins: [new MiniCssExtractPlugin()],
module: {
rules: [
{
test: /\.css$/i,
use: [MiniCssExtractPlugin.loader, 'css-loader'],
},
],
},
};
选项
publicPath
Type: String|Function
Default: publicPath 和 webpackOptions.output中的等同
指定目标文件的自定义公用路径。
String
webpack.config.js
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
plugins: [
new MiniCssExtractPlugin({
//与webpackOptions.output中的相同选项类似
// 这两个选项都是可选的
filename: '[name].css',
chunkFilename: '[id].css',
}),
],
module: {
rules: [
{
test: /\.css$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
publicPath: '/public/path/to/',
},
},
'css-loader',
],
},
],
},
};
Function
webpack.config.js
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
plugins: [
new MiniCssExtractPlugin({
// Options similar to the same options in webpackOptions.output
// both options are optional
filename: '[name].css',
chunkFilename: '[id].css',
}),
],
module: {
rules: [
{
test: /\.css$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
publicPath: (resourcePath, context) => {
return path.relative(path.dirname(resourcePath), context) + '/';
},
},
},
'css-loader',
],
},
],
},
};
esModule
Type: Boolean
Default: false
默认情况下,mini-css-extract-plugin生成使用CommonJS modules语法的JS模块。在某些情况下,使用ES模块是有益的,例如在模块连接和tree shaking的情况下。
您可以使用以下方法启用ES模块语法:
webpack.config.js
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
plugins: [new MiniCssExtractPlugin()],
module: {
rules: [
{
test: /\.css$/i,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
esModule: true,
},
},
'css-loader',
],
},
],
},
};
modules
Type: Object
Default: undefined
配置CSS模块。
namedExport
Type: Boolean
Default: false
启用/禁用名为export for locals的ES模块。
本地的名字被转换成camelCase。
不允许在css类名中使用JavaScript保留字。
选项
esModule和modules.namedExport在css加载程序和MiniCssExtractPlugin.loader应启用。
styles.css
.foo-baz {
color: red;
}
.bar {
color: blue;
}
index.js
import { fooBaz, bar } from './styles.css';
console.log(fooBaz, bar);
您可以使用以下方法启用名为export的ES模块:
webpack.config.js
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
plugins: [new MiniCssExtractPlugin()],
module: {
rules: [
{
test: /\.css$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
esModule: true,
modules: {
namedExport: true,
},
},
},
{
loader: 'css-loader',
options: {
esModule: true,
modules: {
namedExport: true,
localIdentName: 'foo__[name]__[local]',
},
},
},
],
},
],
},
};
示例
最小示例
webpack.config.js
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
plugins: [
new MiniCssExtractPlugin({
// Options similar to the same options in webpackOptions.output
// all options are optional
filename: '[name].css',
chunkFilename: '[id].css',
ignoreOrder: false, // Enable to remove warnings about conflicting order
}),
],
module: {
rules: [
{
test: /\.css$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
// you can specify a publicPath here
// by default it uses publicPath in webpackOptions.output
publicPath: '../',
hmr: process.env.NODE_ENV === 'development',
},
},
'css-loader',
],
},
],
},
};
publicPath选项作为函数
webpack.config.js
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
plugins: [
new MiniCssExtractPlugin({
// Options similar to the same options in webpackOptions.output
// both options are optional
filename: '[name].css',
chunkFilename: '[id].css',
}),
],
module: {
rules: [
{
test: /\.css$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
publicPath: (resourcePath, context) => {
// publicPath is the relative path of the resource to the context
// e.g. for ./css/admin/main.css the publicPath will be ../../
// while for ./css/main.css the publicPath will be ../
return path.relative(path.dirname(resourcePath), context) + '/';
},
},
},
'css-loader',
],
},
],
},
};
高级配置示例
这个插件应该只在没有style-loader生产版本上使用,特别是如果你想在开发中使用HMR。
下面是一个例子,可以让HMR处于开发阶段,也可以将您的样式提取到一个用于生产构建的文件中。
(为清楚起见,请根据您的需要调整装载机选项。)
webpack.config.js
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const devMode = process.env.NODE_ENV !== 'production';
module.exports = {
plugins: [
new MiniCssExtractPlugin({
// Options similar to the same options in webpackOptions.output
// both options are optional
filename: devMode ? '[name].css' : '[name].[hash].css',
chunkFilename: devMode ? '[id].css' : '[id].[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',
],
},
],
},
};
热模块重新加载(HMR)
mini-css-extract-plugin支持在开发过程中热重新加载实际css文件。提供了一些选项来启用标准样式表和本地范围的CSS或CSS模块的HMR。下面是用于HMR和css模块的迷你css配置示例。
当我们尝试hmr css模块时。当使用自定义块名称进行代码拆分时,不容易执行。reloadAll是一个只有在HMR不能正常工作时才应该启用的选项。css模块的核心挑战是,当代码被拆分时,块id可以并且确实与文件名不同。
webpack.config.js
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
plugins: [
new MiniCssExtractPlugin({
// Options similar to the same options in webpackOptions.output
// both options are optional
filename: '[name].css',
chunkFilename: '[id].css',
}),
],
module: {
rules: [
{
test: /\.css$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
// only enable hot in development
hmr: process.env.NODE_ENV === 'development',
// if hmr does not work, this is a forceful method.
reloadAll: true,
},
},
'css-loader',
],
},
],
},
};
生产最小化
要缩小输出,请使用类似optimize-css-assets-webpack-plugin这样的插件。设置optimization.minimizer重写webpack提供的默认值,因此请确保同时指定JS minimizer:
webpack.config.js
const TerserJSPlugin = require('terser-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
module.exports = {
optimization: {
minimizer: [new TerserJSPlugin({}), new OptimizeCSSAssetsPlugin({})],
},
plugins: [
new MiniCssExtractPlugin({
filename: '[name].css',
chunkFilename: '[id].css',
}),
],
module: {
rules: [
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, 'css-loader'],
},
],
},
};
使用预加载或内联CSS
运行时代码通过<link>或<style>标记检测已经添加的CSS。当在服务器端注入CSS进行服务器端渲染时,这可能很有用。<link>标记的href必须与用于加载CSS块的URL相匹配。data-href属性也可用于<link>和<style>。内联CSS数据时必须使用data-href。
在单个文件中提取所有CSS
CSS可以在一个CSS文件中使用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'],
},
],
},
};
基于条目提取CSS
您也可以根据webpack条目名提取CSS。如果您动态导入路由,但希望根据条目绑定CSS,这一点尤其有用。这也防止了ExtractTextPlugin的CSS重复问题。
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'],
},
],
},
};
模块文件名选项
使用moduleFilename选项,可以使用块数据自定义文件名。这在处理多个入口点并希望对给定入口点/块从文件名中获得更多控制时特别有用。在下面的示例中,我们将使用moduleFilename将生成的css输出到另一个目录中。
webpack.config.js
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
plugins: [
new MiniCssExtractPlugin({
moduleFilename: ({ name }) => `${name.replace('/js/', '/css/')}.css`,
}),
],
module: {
rules: [
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, 'css-loader'],
},
],
},
};
Long Term Caching
对于长期缓存,请使用filename: "[contenthash].css"。可选择添加[name]。
webpack.config.js
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
plugins: [
new MiniCssExtractPlugin({
filename: '[name].[contenthash].css',
chunkFilename: '[id].[contenthash].css',
}),
],
module: {
rules: [
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, 'css-loader'],
},
],
},
};
删除顺序警告
对于通过一致使用作用域或命名约定减轻了css顺序的项目,可以通过将插件的ignoreOrder标志设置为true来禁用css顺序警告。
webpack.config.js
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
plugins: [
new MiniCssExtractPlugin({
ignoreOrder: true,
}),
],
module: {
rules: [
{
test: /\.css$/i,
use: [MiniCssExtractPlugin.loader, 'css-loader'],
},
],
},
};
媒体查询插件
如果您想从提取的CSS中提取媒体查询(这样移动用户就不需要再加载桌面或平板电脑特定的CSS),您应该使用以下插件之一: