vue/cli多页面打包配置优化之code split

2,259 阅读3分钟
webpack打包优化

webpack生产环境的打包优化手段有很多,其中code split是最重要的。

  • 可以将node_modules中代码单独打包一个chunk最终输出;
  • 自动分析多入口chunk中有没有公共的文件,如果有会单独打包为一个chunk
  • import动态导入语法:能将某个文件单独打包。

通常情况下,用vue/cli生成的工程用默认的配置就可以达到一个自动的代码分割优化,但是多页面情况下并不完善。

默认配置

目前vue2.x的脚手架工程仍然使用webpack4,因此我们首先查看工程自带的生产环境配置,输入命令vue inspect --mode production >> webpack.prod.config.js,可以看到默认的代码分割配置如下:

   optimization: {
     splitChunks: {
       cacheGroups: {
         vendors: {
           name: 'chunk-vendors',
           test: /[\/]node_modules[\/]/,
           priority: -10,
           chunks: 'initial'
         },
         common: {
           name: 'chunk-common',
           minChunks: 2,
           priority: -20,
           chunks: 'initial',
           reuseExistingChunk: true
         }
       }
     },

如果是单页面的话其实没有什么问题,这个默认配置优化足够,只要在路由处配置动态加载即可。但是多页面的工程每个页面经常会引入不同的第三方库,chunk-vendors就会把所有的库都打包进去,造成体积过大,每个页面都会加载另一个页面的代码,而其并不需要。下面用最简单的一个多页面配置来演示下。

  • 页面1使用elmentui

main.js

 import Vue from 'vue'
 import App from './App.vue'
 import ElementUI from 'element-ui'
 import 'element-ui/lib/theme-chalk/index.css'
 import './plugins/directives'
 ​
 Vue.use(ElementUI)
 Vue.config.productionTip = false
 ​
 new Vue({
   render: h => h(App)
 }).$mount('#app')
 ​
 ​

App.vue

 <template>
   <div id="app">
     <el-button type="primary">使用ElementUi</el-button>
   </div>
 </template>
 ​
 <style lang="less">
 @import './assets/css/global.less';
 ​
 #app {
   font-family: @font-family-regular;
   -webkit-font-smoothing: antialiased;
   -moz-osx-font-smoothing: grayscale;
   text-align: center;
   color: #2c3e50;
 }
 </style>
  • 页面2使用ant design:

main2.js

 import Vue from 'vue'
 import App from './App2'
 import Antd from 'ant-design-vue'
 import 'ant-design-vue/dist/antd.css'
 import './plugins/directives'
 ​
 Vue.use(Antd)
 ​
 Vue.config.productionTip = false
 ​
 new Vue({
   render: h => h(App)
 }).$mount('#app')
 ​

App2.vue

 <template>
   <div id="app">
     <a-button type="primary">使用Ant Design of Vue</a-button>
   </div>
 </template>
 ​
 <script>
 export default {
 ​
 }
 </script>
 ​
 <style lang="less">
 @import './assets/css/global.less';
 ​
 #app {
   font-family: @font-family-regular;
   -webkit-font-smoothing: antialiased;
   -moz-osx-font-smoothing: grayscale;
   text-align: center;
   color: #2c3e50;
 }
 ​
 #nav {
   padding: 30px;
 ​
   a {
     font-weight: bold;
     color: #2c3e50;
 ​
     &.router-link-exact-active {
       color: #42b983;
     }
   }
 }
 </style>
 ​

执行默认配置打包:

image-20211115194344528

我们可以看到chunk-vendors巨大无比,当然因为为了方便这里都是全量引入的ui组件库,这个优化暂且不管,主要原因还是两个页面的两个组件库都打包进去了,这明显是不合理的。

修改默认配置

既然是打包了这两个页面的第三方库,那我们就修改配置为两个页面都引用的第三方库才打包进vendors中,

   chainWebpack: config => {
     config.optimization.splitChunks({
       minSize: 1,
       cacheGroups: {
         vendors: {
           name: 'chunk-vendors',
           test: /[\/]node_modules[\/]/,
           minChunks: 2, // 添加被引用次数
           priority: -10,
           chunks: 'initial'
         },
         common: {
           name: 'chunk-common',
           minChunks: 2,
           priority: -20,
           chunks: 'initial',
           reuseExistingChunk: true
         }
       }
     })
   }

再试着打包一次:

image-20211115195536003

可以看到chunk-vendors的体积大为减少,页面的chunk都增加了很多,也就是把各自引用的第三方库打包到了各自的chunk中去。

还有这边chunk-common也单独出现了,是因为这里修改了minSize为1,默认的是3000,因此最开始打包的时候就没单独打包出来,这里只是做个示例看一下,因为两个页面都引入了vue的公共指令,所以会被单独打包。

总结

webpack的线上优化手段还有很多,code split是最基础也是最强大的,但是也需要结合其他手段,比如这里示例每个chunk仍然很大,还可以用dllexternals等方法来处理。