umi项目配置runtimeChunk优化缓存实践

runtimeChunk是什么?

 webpack在打包的过程会生成runtime和manifest代码。runtime和manifest,在webpack配置中统一通过optimization.runtimeChunk配置。

 runtime:在浏览器运行过程中,webpack用来连接模块之间的代码。比如,已经加载到浏览器中的连接模块逻辑、尚未加载模块的延迟加载逻辑。

 manifest:是一个json / json文件,它包含了每个模块的唯一标识符 (模块id) ,以及模块对应的文件在输出目录中的位置 之间的映射关系,用于帮助webpack快速地查找、加载所需的模块。

 默认情况下,runtime和manifest并不会打包成单独的代码块。而嵌入在入口chunk中。在umi项目中,它就是在嵌入在umi.js中。

为什么要配置optimization.runtimeChunk?

 先简要地概括下,在umi项目开启了dynamicImport时,通过配置optimization.runtimeChunk把runtime和manifest抽离成单独的代码块,对应用的缓存效率有帮助。

 具体细节,请看以下分析:

默认配置打包存在的问题

  • 未配置optimization.runtimeChunk,默认webpack配置的打包结果:

 可以看到,除了umi.js和vendors.js以外,就是各个页面各自打包生成的文件。在此,我们以p_Solutions_edit这个页面为例,只需要关注umi.js 和p_Solutions_edit.js。

  • 现在,我们对p_Solutions_edit页面进行一些修改,比如添加一个console.log('test')并重新打包,打包结果如下:

 我们惊讶地发现,除了p_Solutions_edit.js 的hash更新了以外,umi.js的hash竟然也发生了更新。

 这意味着,每当我们改动任何一个页面中的一丁点代码,并将其发布上线之后,用户打开页面不仅需要重新下载该页面对应的js文件,还需要重新下载整个umi.js文件。

 这对于用户实际上是没有必要的,因为umi.js 只包含了antd等node_modules目录下的依赖和项目代码中一些公共目录的代码。这些依赖和代码并没有改动,完全可以直接使用用户之前缓存的umi.js (如果用户非首次访问的话)。

 而且,一般umi.js 都比较大,我自己的项目里,打包且压缩后的umi.js有接近1MB。

为什么umi.js的hash值也会更新?

 其实,umi.js 的hash发生更新的罪魁祸首就是我们之前说的runtime和manifest。默认情况下,它俩就嵌入在umi.js 里。它们保存着本次打包生成的所有文件的路径,当然路径里也包含文件的hash。所以,一旦p_Solutions_edit页面的代码有更新,打包生成的p_Solutions_edit.js的hash更新,runtime和manifest就也要更新。

 所以才导致了我们明明没有改动umi.js相关的代码,它的hash却发生了更新。

 举个栗子:第二次打包生成的umi.js中保存的文件hash:

如何避免umi.js不必要的更新?

 其实也简单,我们如果可以把runtime和manifest提取成单独的代码块,不要嵌入在umi.js里,不就可以了么?

 那么如何实现从入口chunk中抽离runtime和manifest呢?

 在单页面应用中,webpack的配置,optimization.runtimeChunk: true,可以实现抽离单独的runtime和manifest。

 请看umi具体配置:

javascript 复制代码
  chunks: ['runtime~umi', 'vendors', 'umi'],   //todo
  chainWebpack: function (config, { webpack }) {
    config.merge({
      optimization: {
        minimize: process.env.NODE_ENV === 'production',
        splitChunks: {
          chunks: 'all',
          minSize: 30000,
          minChunks: 2,
          automaticNameDelimiter: '.',
          cacheGroups: {
            vendors: {
              name: 'vendors',
              test: /[\\/]node_modules[\\/]/,
              priority: 10,
            }
          },
        },
        runtimeChunk: true   //todo
      },
    });
  },

 注意:

  1. 请务必在chunks中添加'runtime~umi',chunks里配置的是应用初始加载就需要的代码块,runtime和manifest肯定需要,不然你的umi应用会一直loading,打不开页面。

  2. splitChunks是我自己的配置,如果不需要拆包,可以不配。没有splitChunks的话,记得删掉chunks数组里的vendors。

验证效果

  • 添加以上配置之后,我们先打一次包,本次打包结果如下:

 可以看到,本次打包比以往多了一个文件,runtime~umi.hash.js,这就是我们抽离出的单独的runtime和manifest。

  • 修改p_Solutions_edit页面,再次打包,请对比umi.js 和p_Solutions_edit.js的hash:

 可以看出umi.js 的hash保持没变,只有p_Solutions_edit.js 的hash有更新。runtime~umi.js的hash也会更新。

 这样,就避免了代码发布后,用户再次打开页面,需要重新下载umi.js的问题,可以直接使用缓存的资源文件,以提升加载页面的速度。

如果这篇博客对你有帮助,麻烦点个赞~

相关推荐
小码哥_常16 小时前
一套自己部署的 IM,客户端是同一份 Flutter
前端·后端
蜗牛攻城狮19 小时前
微前端四大方案选型对比与最佳实践:qiankun、micro-app、wujie、Module Federation
前端·微前端·qiankun·前端架构·micro-app·wujie
她说可以呀20 小时前
Vue插槽
前端·javascript·vue.js
qq_4480111620 小时前
Vue + Jinja2两套模版与法冲突造成undefinedError
前端·javascript·vue.js
aixingpan20 小时前
aixingpan.cn API开发文档:前端查询夏令时和时区接口指南
前端·php
2601_9583529021 小时前
23.5×19mm 换掉一整条音频链?|A-68 集成了什么:ADC / DAC / 24.576MHz 时钟 / AEC / 波束降噪,主控仅需 6 根线
前端·音视频·ai降噪·回声消除·语音模块
志尊宝1 天前
AI原生前端开发(039):AI辅助的Nuxt 4全栈开发
前端·vue.js·ai-native
FRing031 天前
JavaScript入门到精通三十二(深拷贝、浅拷贝、递归函数)
开发语言·前端·javascript
excel1 天前
双 Token 与前端使用 Crypto 公私钥鉴权换 Token,哪种方案更好?
前端·后端
外收内放1 天前
Python基础语法练习题(73)
java·前端·python