浅谈webpack优化

移动端项目,需要严格控制包的大小,不然影响用户体验,所以需要对webpack进行优化
本文档主要介绍自己初次体验webpack优化的一些知识点。

敲黑板

包分析工具

便于分析哪些包有问题,哪些包体积过大等现象
vue-cli内置包分析工具

// webpack.prod.conf.js
if (config.build.bundleAnalyzerReport) {
  const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
  webpackConfig.plugins.push(new BundleAnalyzerPlugin())
}

可以通过在package.json添加命令开启包分析工具,默认8888端口

"analyze": "NODE_ENV=production npm_config_report=true npm run build"

vue-cli 默认配置 打包思路

vue-cli默认配置将node_modules里的依赖都打进vendor中,有一些弊端

  • 引入的模块越多,vendor文件越大
  • 提取公共文件目的是,一次打包,之后文件尽可能被浏览器缓存下来,不能每次打包都去改变hash值
  • 这个vendor文件将node_modules中所有依赖都进行抽离,之后维护如果添加新的模块或者删除一些没有用的模块,那么vendor的hash值会发生变化,不利于浏览器缓存

项目中,我主要通过CommonsChunkPlugin插件对webpack进行优化,将本来1M的包,最后只有300+kb

CommonsChunkPlugin

  • 会将项目中引入的node_modules中的模块抽离出来
new webpack.optimize.CommonsChunkPlugin({
  name: 'vendor',
  minChunks: function (module) {
    // this assumes your vendor imports exist in the node_modules directory
    return module.context && module.context.includes('node_modules');
  }
});
  • 提取公共模块,如果没有添加或者删除公共模块,则hash值不变,首次加载被浏览器缓存
  • 尽量将项目中不变的依赖包 抽离出一个文件,保证后续引入别的依赖包,此文件hash值不变化
  • 下图中将vue vuex vue-router vant继续抽离出一个文件

代码如下,两种写法

// 方法一 对module.context进行过滤
new webpack.optimize.CommonsChunkPlugin({
    names: "common",
     minChunks: function(module, count) {
       if (module.resource && /^.*\.(css|scss)$/.test(module.resource)) {
         return false;
       }
       return module.context && 
         (module.context.includes("vue") ||
         module.context.includes("vant") ||
         module.context.includes("vuex") ||
         module.context.includes("vue-router"));
     }
   }),
// 方法二
// webpack.base.conf 文件  将公共模块,写入入口
entry: {
   app: './src/main.js',
   common: ['vue', 'vuex', 'vue-router', 'vant']
},
// webpack.prod.conf 
new webpack.optimize.CommonsChunkPlugin({
   name: 'common',
   minChunks: Infinity // 除了入口的模块,其他模块都不打包进入common
}),

修改router,目的修改打包之后的js文件,便于跟踪

通过下面对每个路由进行修改,添加webpackChunkName,打包出来每个模块的js名称会根据自己设定的来
除此之外,还需要同步修改webpack.prod.conf.jsoutput的配置

output: {
   path: config.build.assetsRoot,
   filename: utils.assetsPath('js/[name].[chunkhash].js'),
   chunkFilename: utils.assetsPath('js/[name].[chunkhash].js')
 },
component: () => import(/* webpackChunkName: "home" */ '@/containers/home.vue'),

浅谈webpack优化

对minChunks理解

当entry属性的值为对象时,作为多个入口的文件们,每个都是一个chunk

minChunks:number

某个模块最少被多少个入口文件依赖,当大于等于设定的值,就会被打入公共包,小于这个值,该模块就会被和每个入口打包在一起

minChunks:infinity

不会把任何依赖的模块提取出来打入公共包

minChunks:默认值

如果没有设置,则为默认值,只有被所有入口文件所依赖,则提取出来打公共包

代码分割

  • 分离业务代码和第三方库 (vendor)
  • 按需加载 (利用路由中 import() 语法 component: () => import('@/components/Hello'))

    • 首页首次加载的时候如果不需要就不加载,等加载到响应路由再去加载相关资源
    • 减少首屏加载时间
  • 根据模块的相对路径生成一个四位数的hash作为模块id

    • webpack里每个模块都有一个module id
    • HashedModuleIdsPlugin 模块根据相对路径生成一个四位数hash作为模块id,引入新的模块,不影响module id,只要模块路径不改变
    • new webpack.HashedModuleIdsPlugin()

参考文章

webpack
commonsChunkPlugin
demo

希望此文对大家有帮助,欢迎吐槽

相关推荐