Webpack4缓存相关配置

{app.params.name}} {app.params.name}} {app.params.name}}

关于webpack的缓存相关配置,我用我之前文章的项目来做下实践

git clone https://github.com/durban89/webpack4-react16-reactrouter-demo.git react-webpack-demo && cd react-webpack-demo
npm install


提取模板(Extracting Boilerplate)

npm install --save-dev webpack-manifest-plugin

添加如下代码
引入

const ManifestPlugin = require('webpack-manifest-plugin');

在plugins中加入

new ManifestPlugin(),

plugins中结果如下

plugins: [
  new CleanWebpackPlugin(['dist']),
  new HtmlWebpackPlugin({
    title: 'React + ReactRouter Demo',
    filename: './index.html', // 调用的文件
    template: './index.html', // 模板文件
  }),
  new webpack.DefinePlugin({
    'process.env.NODE_ENV': JSON.stringify('development'),
  }),
  new ExtractTextPlugin({
    filename: '[name].[hash].bundle.css',
  }),
  new ManifestPlugin(),
],

new ExtractTextPlugin({
  filename: '[name].bundle.css',
}),

改为

new ExtractTextPlugin({
  filename: '[name].[hash].bundle.css',
}),

再将

output: {
  filename: '[name].bundle.js',
  chunkFilename: '[name].bundle.js',
  path: path.resolve(__dirname, 'dist'),
  publicPath: '/',
},

改为

output: {
  filename: '[name].[hash].bundle.js',
  chunkFilename: '[name].[hash].bundle.js',
  path: path.resolve(__dirname, 'dist'),
  publicPath: '/',
},

这次我们执行

npx webpack --config webpack.dev.js

然后看下打包效果

Hash: 88fb183afd5b8cdbb10b
Version: webpack 4.12.0
Time: 2748ms
Built at: 2018-06-14 17:43:46
                              Asset       Size  Chunks             Chunk Names
 app.88fb183afd5b8cdbb10b.bundle.js   1.17 MiB     app  [emitted]  app
   0.88fb183afd5b8cdbb10b.bundle.js   10.9 KiB       0  [emitted]
   1.88fb183afd5b8cdbb10b.bundle.js     11 KiB       1  [emitted]
   2.88fb183afd5b8cdbb10b.bundle.js   10.1 KiB       2  [emitted]
app.88fb183afd5b8cdbb10b.bundle.css  233 bytes     app  [emitted]  app
                       ./index.html  439 bytes          [emitted]
                      manifest.json  366 bytes          [emitted]

多了一个manifest.json
在项目目录下面查看下这个文件

cat ./dist/manifest.json

 

{
  "app.js": "/app.88fb183afd5b8cdbb10b.bundle.js",
  "app.css": "/app.88fb183afd5b8cdbb10b.bundle.css",
  "0.88fb183afd5b8cdbb10b.bundle.js": "/0.88fb183afd5b8cdbb10b.bundle.js",
  "1.88fb183afd5b8cdbb10b.bundle.js": "/1.88fb183afd5b8cdbb10b.bundle.js",
  "2.88fb183afd5b8cdbb10b.bundle.js": "/2.88fb183afd5b8cdbb10b.bundle.js",
  "./index.html": "/./index.html"
}


这个文件干嘛用,后面说

根据官方的说法

将第三方库(library)(例如 lodash 或 react)提取到单独的 vendor chunk 文件中,是比较推荐的做法,这是因为,它们很少像本地的源代码那样频繁修改。因此通过实现以上步骤,利用客户端的长效缓存机制,可以通过命中缓存来消除请求,并减少向服务器获取资源,同时还能保证客户端代码和服务器端代码版本一致。

但是目前官网的实例不起作用了,经过我的实践当前webpack的版本已经使用了新的逻辑,具体操作如下
我们先配置webpack.dev.js
添加如下配置

optimization: {
  splitChunks: {
    chunks: 'initial', // 必须三选一: "initial" | "all"(默认就是all) | "async"
    minSize: 0, // 最小尺寸,默认0
    minChunks: 1, // 最小 chunk ,默认1
    maxAsyncRequests: 1, // 最大异步请求数, 默认1
    maxInitialRequests: 1, // 最大初始化请求书,默认1
    name: () => {}, // 名称,此选项可接收 function
    cacheGroups: { // 这里开始设置缓存的 chunks
      priority: '0', // 缓存组优先级 false | object |
      vendor: { // key 为entry中定义的 入口名称
        chunks: 'initial', // 必须三选一: "initial" | "all" | "async"(默认就是异步)
        test: /react|lodash/, // 正则规则验证,如果符合就提取 chunk
        name: 'vendor', // 要缓存的 分隔出来的 chunk 名称
        minSize: 0,
        minChunks: 1,
        enforce: true,
        maxAsyncRequests: 1, // 最大异步请求数, 默认1
        maxInitialRequests: 1, // 最大初始化请求书,默认1
        reuseExistingChunk: true, // 可设置是否重用该chunk(查看源码没有发现默认值)
      },
    },
  },
},

entry中加入

vendor: [
  'react',
  'react-dom',
  'redux',
],

然后执行

npx webpack --config webpack.dev.js

得到类似如下输出

Hash: 29ff4803e0ac98b32c1c
Version: webpack 4.12.0
Time: 2641ms
Built at: 2018-06-14 17:51:36
                                Asset       Size  Chunks             Chunk Names
   app.29ff4803e0ac98b32c1c.bundle.js   1.17 MiB     app  [emitted]  app
vendor.29ff4803e0ac98b32c1c.bundle.js    735 KiB  vendor  [emitted]  vendor
     0.29ff4803e0ac98b32c1c.bundle.js   10.9 KiB       0  [emitted]
     1.29ff4803e0ac98b32c1c.bundle.js     11 KiB       1  [emitted]
     2.29ff4803e0ac98b32c1c.bundle.js   10.1 KiB       2  [emitted]
  app.29ff4803e0ac98b32c1c.bundle.css  233 bytes     app  [emitted]  app
                         ./index.html  524 bytes          [emitted]
                        manifest.json  423 bytes          [emitted]


多了一个vendor.29ff4803e0ac98b32c1c.bundle.js这个文件 同时app.29ff4803e0ac98b32c1c.bundle.js的大小也减小了


模块标识符(Module Identifiers)

从上面的实践中我们发现我们其实是没有更改代码的但是文件中hash的值却变化了
根据官网的描述

这是因为每个 module.id 会基于默认的解析顺序(resolve order)进行增量。也就是说,当解析顺序发生变化,ID 也会随之改变。因此,简要概括:

 

main bundle 会随着自身的新增内容的修改,而发生变化。
vendor bundle 会随着自身的 module.id 的修改,而发生变化。
manifest bundle 会因为当前包含一个新模块的引用,而发生变化。
第一个和最后一个都是符合预期的行为 -- 而 vendor 的 hash 发生变化是我们要修复的。幸运的是,可以使用两个插件来解决这个问题。第一个插件是 NamedModulesPlugin,将使用模块的路径,而不是数字标识符。虽然此插件有助于在开发过程中输出结果的可读性,然而执行时间会长一些。第二个选择是使用 HashedModuleIdsPlugin,推荐用于生产环境构建:

由于我们现在改的是webpack.dev.js,我们用来实践下
在plugins中添加如下代码

new webpack.NamedModulesPlugin(),

然后

npx webpack --config webpack.dev.js

看下打包效果

Hash: 29ff4803e0ac98b32c1c
Version: webpack 4.12.0
Time: 2813ms
Built at: 2018-06-14 17:57:59
                                Asset       Size  Chunks             Chunk Names
   app.29ff4803e0ac98b32c1c.bundle.js   1.17 MiB     app  [emitted]  app
vendor.29ff4803e0ac98b32c1c.bundle.js    735 KiB  vendor  [emitted]  vendor
     0.29ff4803e0ac98b32c1c.bundle.js   10.9 KiB       0  [emitted]
     1.29ff4803e0ac98b32c1c.bundle.js     11 KiB       1  [emitted]
     2.29ff4803e0ac98b32c1c.bundle.js   10.1 KiB       2  [emitted]
  app.29ff4803e0ac98b32c1c.bundle.css  233 bytes     app  [emitted]  app
                         ./index.html  524 bytes          [emitted]
                        manifest.json  423 bytes          [emitted]

可以修改下CounterComponet.jsx后在执行

npx webpack --config webpack.dev.js

再看下打包效果

Hash: 3cf568e90b38c1c3c339
Version: webpack 4.12.0
Time: 2709ms
Built at: 2018-06-14 17:59:00
                                Asset       Size  Chunks             Chunk Names
   app.3cf568e90b38c1c3c339.bundle.js   1.17 MiB     app  [emitted]  app
vendor.3cf568e90b38c1c3c339.bundle.js    735 KiB  vendor  [emitted]  vendor
     0.3cf568e90b38c1c3c339.bundle.js   10.9 KiB       0  [emitted]
     1.3cf568e90b38c1c3c339.bundle.js     11 KiB       1  [emitted]
     2.3cf568e90b38c1c3c339.bundle.js   10.1 KiB       2  [emitted]
  app.3cf568e90b38c1c3c339.bundle.css  233 bytes     app  [emitted]  app
                         ./index.html  524 bytes          [emitted]
                        manifest.json  423 bytes          [emitted]

结果还是都变化了,奇怪,我们试下生产环境的方式
将webpack.dev.js的相关的改动我们在webpack.prod.js中也做下修改,然后再试下【注意生产环境我们用new webpack.HashedModuleIdsPlugin()】
分别执行

npm run build

第一次输出类似如下

Hash: e0b25a1605f0da8569c1
Version: webpack 4.12.0
Time: 9622ms
Built at: 2018-06-14 18:14:57
                                    Asset       Size  Chunks             Chunk Names
     1.62c80f16d58866af39d9.bundle.js.map      5 KiB       1  [emitted]
         0.a81f2d5fe8a554f19db1.bundle.js   5.32 KiB       0  [emitted]
         2.4bb6ea90727a9917c466.bundle.js   6.23 KiB       2  [emitted]
    vendor.153d0cc454d09104782f.bundle.js    106 KiB       3  [emitted]  vendor
       app.e7d2f7719c957e5c378e.bundle.js    217 KiB       4  [emitted]  app
            main.e7d2f7719c957e5c378e.css  290 bytes       4  [emitted]  app
     0.a81f2d5fe8a554f19db1.bundle.js.map   4.13 KiB       0  [emitted]
         1.62c80f16d58866af39d9.bundle.js   6.34 KiB       1  [emitted]
     2.4bb6ea90727a9917c466.bundle.js.map   5.08 KiB       2  [emitted]
vendor.153d0cc454d09104782f.bundle.js.map    271 KiB       3  [emitted]  vendor
   app.e7d2f7719c957e5c378e.bundle.js.map    644 KiB       4  [emitted]  app
        main.e7d2f7719c957e5c378e.css.map  106 bytes       4  [emitted]  app
                             ./index.html  518 bytes          [emitted]
                            manifest.json  845 bytes          [emitted]

第二次我们修改CounterComponent.jsx,然后再试下结果输出类似如下

Hash: 3102790f92604ffd6406
Version: webpack 4.12.0
Time: 13758ms
Built at: 2018-06-14 18:17:58
                                    Asset       Size  Chunks             Chunk Names
     1.62c80f16d58866af39d9.bundle.js.map      5 KiB       1  [emitted]
         0.44264f48cf81d76c34f3.bundle.js   5.32 KiB       0  [emitted]
         2.4bb6ea90727a9917c466.bundle.js   6.23 KiB       2  [emitted]
    vendor.153d0cc454d09104782f.bundle.js    106 KiB       3  [emitted]  vendor
       app.2d7ccb1930e41d2c5c9b.bundle.js    217 KiB       4  [emitted]  app
            main.2d7ccb1930e41d2c5c9b.css  290 bytes       4  [emitted]  app
     0.44264f48cf81d76c34f3.bundle.js.map   4.13 KiB       0  [emitted]
         1.62c80f16d58866af39d9.bundle.js   6.34 KiB       1  [emitted]
     2.4bb6ea90727a9917c466.bundle.js.map   5.08 KiB       2  [emitted]
vendor.153d0cc454d09104782f.bundle.js.map    271 KiB       3  [emitted]  vendor
   app.2d7ccb1930e41d2c5c9b.bundle.js.map    644 KiB       4  [emitted]  app
        main.2d7ccb1930e41d2c5c9b.css.map  106 bytes       4  [emitted]  app
                             ./index.html  518 bytes          [emitted]
                            manifest.json  845 bytes          [emitted]

可以看出来变动的之后
0.xxxx.bundle.js这个文件
看来这个hash的变化针对的只是生产环境,不过这个也可以了,频繁改动只对生产环境的影响比较大

我们将生产环境的构建配置中的

new webpack.HashedModuleIdsPlugin()

替换为

new webpack.NamedModulesPlugin()

可以再试下,效果跟HashedModuleIdsPlugin是一样的只不过文件大小会有些差别

项目地址

https://github.com/durban89/webpack4-react16-reactrouter-demo.git
tag:v_1.0.10

 


版权声明

durban 创作并维护的 Gowhich 博客采用 创作共用保留署名-非商业-禁止演绎4.0国际许可证。

本文首发于 Gowhich 博客( https://www.gowhich.com ),版权所有,侵权必究。

本文永久链接: https://www.gowhich.com/blog/836

comments powered by Disqus