Vue项目build打包webpack优化

  • webpack-bundle-analyzer
  • 路由懒加载
  • 去除map文件
  • 给chunk命名
  • lodash按需加载
  • 优化elementUI
  • 优化echarts
  • CDN加载
  • 文件说明
  • app.js
  • chunk-vendors.js


webpack-bundle-analyzer

打包分析工具
1、首先安装模块

npm i webpack-bundle-analyzer -D

2、在Vue-Cli3中配置

// vue.config.js
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin

module.exports = {
	chainWebpack: config => {
		if (process.env.NODE_ENV === 'production') {
	      config
	        .plugin('webpack-bundle-analyzer')
	        .use(BundleAnalyzerPlugin)
	    }
	...
}

3、执行以下命令即可查看

npm run build

查看效果

npm拉包单独配置镜像_Vue


查看地址为http://127.0.0.1:8888/注:因为在vue.config.js中限制了process.env.NODE_ENV === 'production'环境,所以只有在npm run build打包的时候才会执行,否则默认是都执行,也就是npm run serve运行的时候也会执行,显然这不是我们想要的结果。

在打包好的线上项目中看我们的文件大小跟这里的数据基本一致

npm拉包单独配置镜像_打包优化_02


生成的dist/js目录下的文件

npm拉包单独配置镜像_Vue_03


最终打包生成的js/chunk-vendor.js大小为2.09M。

路由懒加载

之前在router.js文件中,采用的静态引入的方式

import assetList from './pages/asset-manage/asset-list'

{
	path: 'xxx/asset-list',
	name: 'asset-list',
	component: assetList 
}

改为懒加载模式

{
	path: 'xxx/asset-list',
	name: 'asset-list',
	component: () => import('./pages/asset-manage/asset-list')
}

以函数的形式动态引入,这样就可以把各自的路由文件分别打包,只有在解析给定的路由时才会下载路由组件

npm拉包单独配置镜像_Vue_04


npm拉包单独配置镜像_npm拉包单独配置镜像_05


文件中看到生成了很多的代码chunk文件,这样就能做到在跳转到指定路由时才加载对应的文件,而不是都集中在一个大的文件中,首屏加载的时候就需要下载这个大文件。

此时,生成的js/chunk-vendor.js大小为1.58M

去除map文件

文件中我们看到很多map文件,因为项目打包后,代码都是经过压缩加密的,如果运行报错输出的错误信息无法准确得知是哪里的代码报错,这个文件就可以让我们查到具体报错的位置。
为了保证我们打包后的代码不暴露源码,就需要我们将map文件隐藏掉,如何做呢?

// vue.config.js
module.exports = {
	productionSourceMap: process.env.NODE_ENV === 'production' ? false : true
}

npm拉包单独配置镜像_Vue_06

给chunk命名

chunkFileName是不能灵活自定义,这当然不能忍了,于是便有了魔术注释法!
上面看到打包生成的文件都是chunk-hash.js的格式,如果想要自定义chunk文件怎么处理呢?
还记得这么多chunk是怎么出来的么?对,之前我们把路由文件进行了修改,修改成按需加载,下面进一步修改

// router.js
{
   path: '/assetManage/assetList',
   name: 'asset-list',
   meta: {
     breadCrumb: ['资产管理', '资产列表'],
     navCode: 'asset-list'
   },
   component: () => import(/* webpackChunkName: 'asset' */ './pages/asset-manage/asset-list')
}
// vue.config.js
module.exports = {
	configureWebpack: {
    output: {
      chunkFilename: 'js/[name].[chunkhash].chunk.js'
    }
  }
}

这样打包生成的文件

npm拉包单独配置镜像_webpack_07


其他的文件如果也想命名都可以使用这种方法。相同name的会合并成一个文件。

lodash按需加载

import {pick} from 'lodash'
import _ from 'lodash'

// 都改成按需引入
import pick from 'lodash/pick'

优化elementUI

完成上面工作后可以很明显的看到elementUI占了很大的部分
之前我们引入elementUI

// main.js
import elementUI from 'element-ui'

Vue.use(elementUI)

现在我们改成

// main.js
import { Dropdown, 
  DropdownMenu, 
  ...
  Table } from 'element-ui'
  
Vue.use(Dropdown)
Vue.use(DropdownMenu)
...
Vue.use(Table)

优化echarts

采用按需加载
之前引入

// main.js
import echarts from 'echarts'

Vue.prototype.$echarts = echarts

现在我们改成按需加载

// 使用到的文件bar.vue
import echarts from 'echarts/lib/echarts'

require('echarts/lib/chart/bar')
require('echarts/lib/component/tooltip')
require('echarts/lib/component/title')

CDN加载

在Vue项目中,引入到工程中的所有js、css文件编译时会打包进vendor文件中,浏览器在加载该文件之后才能开始显示首屏,若是引入的库众多,那么vendor.js就会过大,影响首屏体验。
CDN加载就是将工程中引用的外部js、css文件剥离开,不编译到vendor.js中,而是用资源的形式引用,这样浏览器可以使用多个线程加载外部的库文件。
下面是使用普通加载方式得到的打包后文件的分布

// main.js
import echarts from 'echarts'
Vue.prototype.$echarts = echarts
// 使用的.vue文件
this.echartsObj = this.$echarts.init(document.getElementById(this.id))

npm拉包单独配置镜像_加载_08


下面我们将echarts使用外部资源引入的方式看看优化后的效果

// vue.config.js
module.exports = {
  configureWebpack: {
    externals: {
      echarts: 'echarts'
    }
  }
}
// index.html

<!-- 引入外部echarts资源 -->
<script src="https://cdn.bootcss.com/echarts/4.1.0/echarts.min.js"></script>
// main.js
// 将这里引入的echarts注释
// import echarts from 'echarts'
// Vue.prototype.$echarts = echarts
// 使用的.vue文件
this.echartsObj = echarts.init(document.getElementById(this.id))

打包后

npm拉包单独配置镜像_加载_09


从1.6M–>825.99KB

Nice!

CDN加载资源方式的原理是:通过 import echarts from 'echarts' 这种导入方式拿到的变量 echarts,CDN加载(通过插入 script 标签引入资源的方式)后会将变量挂载到全局 window 中,这样就可以在项目中通过 window.echarts 直接使用,或简写为 echarts

所以,如果你的项目中某个资源通过 CDN 加载的方式插入后,在控制台中通过 window.xxx 的方式拿不到变量,说明你的资源有问题。

如果工程很大,首屏时间很长的话可以使用CDN加载VueVuexVue-Router等,提升首屏体验。

在vue-cli + element-ui 项目中,如果通过 CDN 方式加载 vue:

  • 项目中仍然需要 npm i vue 安装 Vue,否则需要手动配置 VueLoaderPlugin 去解析 .vue 文件。
  • element-ui 的全局变量是 ELEMENT
  • 多语言中 element-ui 的多语言挂载在 ELEMENT.lang.xxx

文件说明

app.js

对于chunk文件我们知道就是我们懒加载时不同路由文件的内容,那么还有一个app.js文件,这个文件是打包的各项依赖的集合,比如我们在项目入口文件main.js文件中引入了vuevue-routeraxios等依赖,具体内容可以通过上面的webpack-bundle-analyzer分析工具查看。

chunk-vendors.js

这里也是引入的组件,只是把一些大组件代码拆分到了这里。具体内容也可以通过webpack-bundle-analyzer工具分析查看,我们看到我们的element-ui就在这里。