前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Vue 的打包优化之路Vue的打包优化之路

Vue 的打包优化之路Vue的打包优化之路

作者头像
MrTreasure
发布2018-12-24 14:22:51
2.3K0
发布2018-12-24 14:22:51
举报

Vue的打包优化之路

场景分析

一个结构简单 依赖蛮多的可视化项目,用到的库有

  1. vue + vue-router + vuex + axios
  2. echarts + 全省份地图文件 + 中国地图文件
  3. elementui
  4. moment(后面被date-fns代替)
  5. lodash lodash-decorator(用到了装饰器)

ECharts的JSON地图文件占了很大一部分,大概有1.96MB gzip以后900KB,这一部分是没有办法做处理的。然后ECharts也应该使用按需加载

接着是依赖的一些公共库,比如Vue全家桶,这部分是可以提取到 cdn 的

最后是一些类似 lodash moment的工具库,可能只引用到了部分功能,但是默认会加载全部包,这样是不划算的。lodash moment默认都不支持 three-shake 因此需要手动按需加载或者使用更小体积的库。

先来看看默认没有经过优化的打包分析

默认配置

只做了简单的异步路由加载,各种库均没有按需引用

vue-bundle-1.png

这一个地方在体积处理上没有更好的优化办法

vue-bundle-2.png

这里可以看到ECharts的库占了很大一部分 然后是 moment elementui这些库

vue-bundle-3.png

初步优化

因为业务的需求 需要用到地图相关信息所以这部分体积是没法减少的。但是并不是初次进入页面就需要加载这些文件。我们知道 ECharts 是通过 ECharts.registerMap('china', China) 注册地图的。 这个注册是可选的,并且仅仅是地图相关的组件会用到,因此我们单独封装这个地图组件,在组件内部注册,并通过异步路由切割,达到分片的目的

//...
import China from 'echarts/map/json/china.json'
import provinceList from './provinceList.json'

// 注册地图
ECharts.registerMap('china', China)
provinceList.forEach(pro => {
  const map = require('echarts/map/json/province/' + pro.path)
  ECharts.registerMap(pro.py, map)
})

@Component
export default class AreaChart extens Vue {}
//...

另外一个优化点在于默认引入 ECharts 是引入全部的 import * as ECharts from 'echarts' 我们只需要部分组件,因此单独定义一个echarts文件, 这样我们所有引用 ECharts的文件,都改为引用这个文件就实现了按需加载

# echarts.ts
import ECharts from 'echarts/lib/echarts'

import 'echarts/lib/chart/bar'
import 'echarts/lib/chart/line'
import 'echarts/lib/chart/pie'
import 'echarts/lib/chart/funnel'
import 'echarts/lib/chart/scatter'
import 'echarts/lib/component/title'
import 'echarts/lib/component/legend'
import 'echarts/lib/component/tooltip'
import 'echarts/lib/component/axisPointer'
import 'echarts/lib/component/visualMap'
import 'echarts/lib/component/markLine'
import 'echarts/lib/component/markPoint'
import 'echarts/lib/component/markArea'
import 'echarts/lib/component/geo'

export { ECharts }

在 vendors 中还有 moment 这个很大其实我只用到了moment(current).subtract(1, 'day').format('YYYY-MM-DD') 这几个基本功能, 这样的使用引入全部 moment 是不值得,因此改为了 date-fns 然后按需引入了部分功能。上面代码等价转换为 format(subDays(parse(now), 8), 'YYYY-MM-DD') 然而我们只需要按需引入这三个函数就ok了

vue-bundle-4.png

vue-bundle-5.png

vue-bundle-6.png

moment 也被替换为了date-fns

vue-bundle-8.png

vue-bundle-9.png

CDN进一步优化

在初步优化完成后,我们发现 vue 全家桶以及 elemenUI i仍然占了很大一部分 vendors 体积,这部分代码是不变的,但会随着每次 vendor 打包改变 hash 重新加载。我们可以使用 cdn 剔除这部分不经常变化的

另外一方面我们的页面很小,但是因为异步路由加载分割了好几块。小碎片的加载也是影响浏览器性能要素之一,我们通过更改打包策略解决

使用 webpack-cdn-plugin 插件

WebpackCDNPlugin

过去我们外部引入 CDN 需要手动编写 index.html 模板,在里面指定加载的版本,通过这个插件就能自动的把指定的公共库写入到 index.html 模板里,目前的文档有坑,我已经提了PR

需要注意的是,通过CDN引入,在使用 VueRouter Vuex ElmentUI 的时候要改下写法。CDN会它们挂载到window上,因此不再使用 Vue.use(xxx)

import Vue from 'vue'
import VueRouter from 'vue-router'

if (!window.VueRouter) Vue.use(VueRouter)

更改打包策略

通过webpack-chunk-name 合并一些包

const A1 = () => import(/* webpackChunkName: "A" */ '@/views/A1')
const A2 = () => import(/* webpackChunkName: "A" */ '@/views/A2')
const A3 = () => import(/* webpackChunkName: "A" */ '@/views/A3')

[图片上传失败...(image-61ee85-1544087237201)]

剔除全家桶以后,剩下的需要首次加载 vendor 就很小了

优化后的数据

(只显示gzip大小)

Vendors

Echarts

Moment or date-fns

默认打包

601.48kb

195.41kb

66.45kb

初步优化

410.66kb

104.87kb

7kb

CDN优化

206.78kb

104.85kb

7kb

优化的意义与思路

我们优化的目的除了写KPI和升职答辩外,最主要的就是提升用户的体验。

提升首次访问的渲染速度。影响首次渲染速度除了代码上的优化之外就是网络传输的速度。

代码上能优化的地方不多,主要考虑的就是网络传输。

一方面是要考虑打包后的体积,从这个维度来考虑,我们可以通过按需引用以及 CDN。按需引用方便理解效果也比较显著,而使用 CDN 的好处有以下几个方面

  1. 抽离出公共包避免每次打包加快打包速度。分离公共库以后,每次重新打包就不会再把这些打包进 vendors 文件中,即使更改了 hash 用户也只需要获取改变的部分
  2. cdn 具有复用的效果。网站A B 都引用同一份资源(版本路径都相同),那么用户访问了A网站以后浏览器缓存了这部分资源,访问B网站时就可以直接复用,减少不必要的加载
  3. CDN减轻自己服务器的访问压力,并且能实现资源的并行下载。浏览器对 src 资源的加载是并行的(执行是按照顺序的), 通过不同的域名加载资源提高很多的加载速度

另一方面应该减少需要加载包的数量,特别是体积较小的碎片包。在初次优化之后,我们发现很多自己写的组件只占了很小的体积,却仍然分割成了独立的块。我们便可以将这些碎片包打包成一个包,减少请求次数。

最后

从没有优化到最后使用CDN优化,可以显著的发现打包后的文件大小减少。如果我们的应用有很高的 pv 每一点优化到最后都能节省很多的流量。从数值上看到优化的效果,对于程序员来说也是蛮有成就感的。 以上就是关于打包优化的一点分享

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018.12.06 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Vue的打包优化之路
    • 场景分析
      • 默认配置
        • 初步优化
          • CDN进一步优化
            • 使用 webpack-cdn-plugin 插件
            • 更改打包策略
          • 优化后的数据
            • 优化的意义与思路
              • 最后
              相关产品与服务
              内容分发网络 CDN
              内容分发网络(Content Delivery Network,CDN)通过将站点内容发布至遍布全球的海量加速节点,使其用户可就近获取所需内容,避免因网络拥堵、跨运营商、跨地域、跨境等因素带来的网络不稳定、访问延迟高等问题,有效提升下载速度、降低响应时间,提供流畅的用户体验。
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档