mini-css-extract-plugin具体配置

2,739 阅读4分钟

「这是我参与11月更文挑战的第4天,活动详情查看:2021最后一次更文挑战

看到很多webpack配置都看到配置mini-css-extract-plugin,所以想着去了解它,然后在自己的webpack配置中去使用。 官网介绍:本插件会将 CSS 提取到单独的文件中,为每个包含 CSS 的 JS 文件创建一个 CSS 文件,并且支持 CSS 和 SourceMaps 的按需加载。

一个简单的使用例子

const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
  plugins: [new MiniCssExtractPlugin()],
  module: {
    rules: [
      {
        test: /.css$/i,
        use: [MiniCssExtractPlugin.loader, "css-loader"],
      },
    ],
  },
};

了解每一个选项

然后就开始去了解它可配置的选项:下面贴上官网的配置表格

选项名类型默认值描述
filename{String|Function}[name].css此选项决定了输出的每个 CSS 文件的名称
chunkFilename{String|Function}based on filename此选项决定了非入口的 chunk 文件名称
ignoreOrder{Boolean}false移除 Order 警告
insert{String|Function}var head = document.getElementsByTagName("head")[0];head.appendChild(linkTag);在指定位置将 非初始(由 async 修饰) 的 CSS chunk 插入 link 标签
attributes{Object}{}非初始(由 async 修饰) 的 CSS chunk 所处的 link 标签添加自定义属性
linkType{String|Boolean}text/css允许使用自定义 link 类型加载异步 chunk
runtime{Boolean}true允许启动/禁用 runtime 生成
experimentalUseImportModule{Boolean}undefined使用实验性的 webpack API 来执行模块,而非子代编译器

第一个参数比较好理解,当看到第二参数的时候,有点蒙,然后看到解释说:

机制类似于 output.chunkFilename

然后转战output.chunkFilename

output.chunkFilename

此选项决定了非初始(non-initial)chunk 文件的名称 也就是除了入口文件外,所产生的chunk文件

chunk

那么chunk又是什么呢?

Chunk是Webpack打包过程中,一堆module的集合。我们知道Webpack的打包是从一个入口文件开始,也可以说是入口模块,入口模块引用这其他模块,模块再引用模块。Webpack通过引用关系逐个打包模块,这些module就形成了一个Chunk。

如果我们有多个入口文件,可能会产出多条打包路径,一条路径就会形成一个Chunk。出了入口entry会产生Chunk,还有两种途径,

产生Chunk的三种途径
  1. entry入口
  2. 异步加载模块
  3. 代码分割(code spliting)

[id]、[name]

然后看到之前都是用的[name],不知道[id]是什么,所以又去了解了[id]。

其中[name]代表entry设置中对应的键名index,[id]代表webpack打包中自动给各个模块所设置的模块id(内部 chunk id);
[name]如果设置,则为此 chunk 的名称,否则使用 chunk 的 ID。

output.filename

有关可取的值的详细信息,请查看 output.filename 选项。 所以,又去了解了output.filename
此选项决定了每个输出 bundle 的名称。这些 bundle 将写入到 output.path 选项指定的目录下。
此选项不会影响那些「按需加载 chunk」的输出文件。它只影响最初加载的输出文件。对于按需加载的 chunk 文件,请使用 output.chunkFilename 选项来控制输出。
当看到使用函数返回filename 请确保已阅读过 指南 - 缓存 的详细信息。这里涉及更多步骤,不仅仅是设置此选项。

缓存

又去了解缓存,然后配置了下面这些配置

 optimization: {
        moduleIds: 'deterministic', // 不论是否添加任何新的本地依赖(本地创建文件,不是引外面的文件,比如lodash),对于前后两次构建,vendor hash 都应该保持一致
        splitChunks: {
            chunks: 'all' // 移除了重复的依赖模块,并且将其从 main bundle 中移除,减轻了大小
        },
        runtimeChunk: 'single', // Webpack在浏览器端运行时需要的代码单独抽离到一个文件,将 runtime 代码拆分为一个单独的 chunk。将其设置为 single 来为所有 chunk 创建一个 runtime bundle:
        splitChunks: {
            // 我们可以看到 main 不再含有来自 node_modules 目录的 vendor 代码
            cacheGroups: {
                vendor: {
                    test: /[\\/]node_modules[\\/]/,
                    name: 'vendors',
                    chunks: 'all'
                }
            }
        }
    },
最后配置

最终了解各个方面之后,就做了下面的配置,和js的目录格式统一

plugins: [
        new miniCssExtractPlugin({
            filename: 'css/[name].[contenthash].css', // 设置导出css名称,[name]占位符对应chunkName
            chunkFilename: (pathData) => {
                // 此选项决定了非入口的 chunk 文件名称
                return (
                    pathData.chunk.name !== 'main' &&
                    'css/[id]/[id].[contenthash].css'
                )
            },
            // 一个官方维护人员的回复如下,简单的说,就是在js里css的引入顺序导致的问题,多个css的在js里的引入顺序不同,就会提示这个警告。例如,在1.js 里,引入的顺序是a.css, b.css; 在2.js里,引入顺序是b.css,a.css, 出现了这种引入顺序不同,就导致了警告。在两个js里把引入顺序调成一致,就没问题了。在1.js和2.js里的引入顺序都调整成a.css, b.css 就没有那个警告了。
            ignoreOrder: true // 对于通过使用 scoping 或命名约定来解决 css order 的项目,可以通过将插件的 ignoreOrder 选项设置为 true 来禁用 css order 警告。
        })
    ]