webpack中的chunk

Chunk 是什么?

chunk 表示一个文件,默认情况下 webpack 的输入是一个入口文件,输出也是一个文件, 这个文件就是一个 chunk,chunkId 就是产出时给每个文件一个唯一标识 id,chunkhash 就是文件内容的 md5 值,name 就是在 entry 中指定的 key 值。 先来看一张图:

这张图是简单打包的结果。一般运行结果和这个差不多可能文件更大一些,更多一些,但 是也是这几部分构成的。 里面有两个字段,一个 chunks, 另外一个 chunk names; 要解释这两个字段是需要配置 文件来进行解释的。

webpack.config.js
const path = require('path');
module.exports = {
    mode: 'development',
    entry: {
        bundle: './src/index.js',
        fun: './src/func.js'
    },
    output: {
        filename: '[name][hash]',
        path: path.resolve(__dirname, 'dist')
    }
}

在上述代码中,我们在 entry 中设置的 对象中的 key 值,也就是 bundle,以及 fun 就 是我们给与入口文件的命名,一个 key 对应一个 chunk 文件。在输出的时候,在 output ,[name]表示用原有的 chunk 名称[hash] 利用 md5 命名的目的用于浏览器的缓存机 制。

这个 chunk 的名称的计算过程:

  • 1. 先打开根目录下的 webpack.config.js
  • 2. 找 entry(入口)属性的值
  • 3. 进入到 bundle.js 里,如果依赖其他文件,再找到其他文件
  • 4. 把 bundle.js 与依赖的其他文件合并成一个 js 文件
  • 5. 在 webpack.config.js 里找到 output(出口)属性
  • 6. 解析 output 里的 path 与 filename 属性的值,如果有 hash 在加上 hash 的值
  • 7. 把第 4 步合并成的 js 文件放到 dist 文件夹里,并起个名字叫 bundle.js 或者 (bundle.xxxx(此处为 hash 值).js)

注意:

  • 1、当 entry 为数组的时候,webpack 会把数组里所有文件打包成一个 js 文件
  • 2、当 entry 为对象的时候,webpack 会把对象里的文件分别打包成多个文件

这里在多说一些关于 webpack 中的 hash 的内容。

浏览器为了优化体验,会有缓存机制。如果浏览器判断当前资源没有更新,就不会去服务 端下载,而是直接使用本地资源。在 webpack 的构建中,我们通常使用给文件添加后缀值 来改名以及提取公共代码到不会改变的 lib 包中来解决新资源缓存问题。这个东西就是 hash 也就是我们所说的 md5。 如上面配置,在我们的打包结果中就会出现:

在上面,我们看到,我们配置的 hash 值,然后打包出的是一个长串字符串,这边的的长 度我们可以指定,比如配置为:

webpack.config.js
// ...
    output: {
        filename: '[name][hash:5]',
        path: path.resolve(__dirname, 'dist')
    }
// ...

这样打包出来的就是 5 位的 hash 字符串,我们看到这边 bundle 模块打包出的和 fun 模块 打包出的 hash 值是一样的,这个是什么原因呢?

对于 webpack 来说,它是一个打包编译的过程,也就是一个 compilation 的过程,这个 标识符,标识的就是这个打包的过程。这样就很好解释了模块标识符的概念就是在相同编 译打包过程中的模块所共有的标识符,也就是说同一过程产出的产物的 hash 值都是一样 的,也就解释了上面的过程。

这里会出现一个问题:

这个问题就是:如果都使用 hash 的话,所有文件的 hash 都是一样的,而且每次修改任 何一个文件,所有文件名的 hash 值都将改变。所以一旦修改了任何一个文件,整个项目 的文件缓存都将失效。

我们本着网络优化的思想去做浏览器缓存,但是当我们服务器修改一个文件重新打包的时 候。所有的文件名称都会发生变化,本应该缓存的内容也并没有缓存。这并不是我们想要 的,那该怎么办?

既然 hash 的用法有这种缺陷,那是否有更好的办法,使只有被修改了的文件的文件名 hash 值修改呢?答案就是使用 chunkhash

当我们把配置文件中的 hash 换成 chunkhash 的时候,like this:

webpack.config.js
// ...
    output: {
        filename: '[name][chunkhash:5]',
        path: path.resolve(__dirname, 'dist')
    }
// ...

会发现我们修改那个文件,那个文件就会重新打包 之前的打包结果:

    Asset        Size        Chunks        Chunk Names
 bundle4e992   3.78 KiB   bundle [emitted]    bundle
   fun49599    3.78 KiB     fun [emitted]       fun

Entrypoint bundle = bundle4e992
Entrypoint fun = fun49599

修改 func 的内容后的打包结果:

    Asset        Size        Chunks        Chunk Names
  bundle4e992  3.78KiB  bundle [emitted]      bundle
   funec2df    3.78KiB   fun [emitted]         fun

Entrypoint bundle = bundle4e992
Entrypoint fun = funec2df

发现只有我们修改的 chunk fun 发生变化,进行重新打包。这个也是符合预期的 对于 CSS 来说,JS 引入的 CSS 发生变化,也会重新 hash,这个时候无论 chunkhash,还 是 hash 都不好用,那该怎么办呢?

使用 mini-css-tract-plugin 中定义的 contenthash 来进行打包,来解决以上问题。

webpack.config.js
// ...
{
    test: /\.css$/,
    use: [{
        loader: MiniCssTractPlugin.loader
    }, 'css-loader']
},
// ...
webpack.config.js
// ... 
    plugins: [
        new MiniCssTractPlugin({
            filename: "[name].[contenthash:5].css"
        })
    ]
// ...

 

猜你喜欢

转载自blog.csdn.net/weixin_40851188/article/details/89888822