AnnVoV / blog

24 stars 2 forks source link

webpack 长缓存相关阅读笔记 #21

Open AnnVoV opened 5 years ago

AnnVoV commented 5 years ago

这是一篇阅读笔记,重点推荐阅读下面3篇文章: 1.Predictable long term caching with Webpack https://medium.com/webpack/predictable-long-term-caching-with-webpack-d3eee1d3fa31 2.手摸手合理地带你使用webpack4 上 https://segmentfault.com/a/1190000015919863 3.手摸手带你合理使用webpack4 下 https://segmentfault.com/a/1190000015919928

我的总结:

参考资料: 1.Predictable long term caching with Webpack (重点参考) https://medium.com/webpack/predictable-long-term-caching-with-webpack-d3eee1d3fa31 2.希望做浏览器长缓存?关于Webpack生成的Hash,你应该知道这些 https://segmentfault.com/a/1190000011980729 3.手摸手合理地带你使用webpack4 上 https://segmentfault.com/a/1190000015919863 4.手摸手带你合理使用webpack4 下 (重点参考) https://segmentfault.com/a/1190000015919928 5.webpack4 之SplitChunksPlugin https://juejin.im/post/5af15e895188256715479a9a 6.webpack4 持久缓存小结 https://juejin.im/post/5a705f6cf265da3e36418dc5 7.http1 与 http2 的差别?以及http2的优势 https://medium.com/@factoryhr/http-2-the-difference-between-http-1-1-benefits-and-how-to-use-it-38094fa0e95b 8.如何理解http2 的多路复用 https://segmentfault.com/q/1010000005167289 9.HTTP/2.0 相比1.0有哪些重大改进? https://www.zhihu.com/question/34074946

下面列举一些文中提到的一些问题:

在配置的路由模块里,我们新加一个异步模块,模块的chunkhash都发生了变化

因为新加入了一个模块,导致我们的模块的id顺序已经发生了变化了,所以导致我们打包出来的文件内容都发生了改变,所以我们需要使用另一个插件去替代id来命名的方式

解决方案: 1.在我们的路由里面,我们需要命名chunk 异步组件参考文档: https://router.vuejs.org/zh/guide/advanced/lazy-loading.html

const Foo = () => import(/* webpackChunkName: "group-foo" */ './Foo.vue')
const Bar = () => import(/* webpackChunkName: "group-foo" */ './Bar.vue')
const Baz = () => import(/* webpackChunkName: "group-foo" */ './Baz.vue')

用这种注释的方式,我们最终得到的组件是以group-foo命名的,并且这3个异步组件打包到了一起

2.我们要开启namedChunks namedModules 让模块依赖不是用id去命名,这样就不会有添加一个组件,其他组件就收到影响的问题了 webpack4 默认在生产环境下开启了namedModules 和 namedChunks,webpack3 我们使用的是 webpack.NamedModulesPlugin 来解决这个问题的

IMAGE

当添加了externals 时,0号文件顺序变了,导致vendor又变了

查看文章: https://medium.com/webpack/predictable-long-term-caching-with-webpack-d3eee1d3fa31

webpack4 下面几个配置的区别

RuntimeChunks

将模块的映射列表从app.js 中抽取出来了,只要设置

{
  runtimeChuk: true
}

其实我们发现打包生成的 runtime.js非常的小,gzip 之后一般只有几 kb,但这个文件又经常会改变,我们每次都需要重新请求它,它的 http 耗时远大于它的执行时间了,所以建议不要将它单独拆包,而是将它内联到我们的 index.html 之中(index.html 本来每次打包都会变)。

这里我选用了 script-ext-html-webpack-plugin,主要是因为它还支持preload和 prefetch,正好需要就不想再多引用一个插件了,你完全可以使用 inline-manifest-webpack-plugin或者 assets-webpack-plugin等来实现相同的效果。

HashedModuleIdsPlugin

这个之前也提到了,我们的模块的id 是自增的, 这就导致了,添加一个模块或者删除一个模块,都会影响当前的id, 这就导致了引入一个文件就会使原先的缓存失效了 image

webpack4里有一个HashedModuleIdsPlugin 这个和 NamedModulesPlugin的区别 NamedModulesPlugin 直接使用了模块的路径作为原先的模块id, 而使用HashedModuleIdsPlugin 会使用hash过的路径作为模块id image

NamedModulesPlugin 和 HashedModuleIdsPlugin 原理是相同的,将文件路径作为 id,只不过没有把路径 hash 而已,适用于开发环境方便调试。不建议在生产环境配置,因为这样不仅会增加文件的大小(路径一般偶读比较长),更重要的是为暴露你的文件路径。

同理,我们在固定moduleId的时候,同时也要固定chunkId 因为我们增加chunk 或者减少chunk的时候,也会导致顺序乱掉

webpack4 内置的打包策略

它内置的代码分割策略是:

所以有一些小的组件,即使被多个页面进行了引用,但它如果本身比较小(比如只有5k),还是会被分别打包到各自使用的组件中。 【理由】5k的代码在gzip压缩之后,可能只有1.5k左右,你为了这1.5k却要花费额外的http请求,是不值得的

但有些场景下这些规则可能就显得不怎么合理了。比如我有一个管理后台,它大部分的页面都是表单和 Table,我使用了一个第三方 table 组件,几乎后台每个页面都需要它,但它的体积也就 15kb,不具备单独拆包的标准,它就这样被打包到每个页面的 bundle 中了,这就很浪费资源了。这种情况下建议把大部分页面能共用的组件单独抽出来,合并成一个component-vendor.js的包(后面会介绍)。

优化分包策略

配置参考:

  // ...
  optimization: {
      splitChunks: {
        chunks: 'all',
        cacheGroups: {
          // 类似原先的CommonChunksPlugin
          libs: {
              name: 'chunk-libs',
              test: /[\\/]node_modules[\\/]/,
              priority: 10, // 注意这里的权重
              chunks: 'initial', // ?这个配置不了解 有 all async initial
          },
          elementUI: {
              name: 'chunk-elementUI',
              priority: 20, // 权重要大于上面的10
              test: /[\\/]node_modules[\\/]element-ui[\\/]/,
          },
          commons: {
              name: 'chunk-commons',
              test: resolve("src/components"), // 可自定义拓展你的规则
              priority: 5,
              reuseExistingChunk: true
          }   
        }
    }
  }

博弈

优化是一个博弈的过程,是让首次加载快一点还是更多的利用cache。拆包的时候不要过分的追求颗粒化,如果什么都单独打成一个bundle,会导致请求过多受到阻塞。但是如果是在http2的情况下,那我们的打包策略又可以有新的改变了