vue 项目优化. jpeg
vue 项目打包后文件总是很大, 首先得确定到底是哪里导致了首屏渲染如此之慢?
image
打开 Chrome Network 面板, 勾上 Disable cache 选项, 刷新页面观察资源加载情况, 发现罪魁祸首就是 webpack 打包生成的 App.JS 和 vendor.JS, 其中 vendor.JS 大小达到了 1.2M, 下载时间超过 20 秒, App.JS 也快到 1M, 而 manifest.JS 不是很大. vendor.JS 主要是把 node_modules 里所用到的 modules 都合并成一个 JS 了, 所以比较大. 而我们也希望将业务代码和第三方引用分开打包. manifest.JS 包含 webpack 的 runtime 代码和 module manifest 代码, 作用是防止修改了代码但是没有修改第三方库文件导致第三方库文件也打包的问题.
通过查一些资料, 我们从以下几个方面去优化:
开启 gzip 压缩功能
引入 CDN
路由懒加载
某些第三方组件按需加载而不是全部加载
较小的图片资源用 base64 嵌入 src 中, 减少 http 请求
1.gzip 压缩
这个是需要后端配合设置的, 首先我们来了解一下什么是 gzip?
gzip 是 GNUzip 的缩写, 最早用于 UNIX 系统的文件压缩.
HTTP 协议上的 gzip 编码是一种用来改进 Web 应用程序性能的技术, Web 服务器和客户端 (浏览器) 必须共同支持 gzip.
目前主流的浏览器, Chrome,Firefox,IE 等都支持该协议.
常见的服务器如 Apache,Nginx,IIS 同样支持, gzip 压缩效率非常高, 通常可以达到 70% 的压缩率, 也就是说, 如果你的网页有 30K, 压缩之后就变成了 9K 左右
我后端是用的 koa, 开启 gzip 非常简单, 首先 NPM install compression 安装中间件, 然后在 App.JS 里添加 use 使用即可:
- var compression = require('compression');
- var App = express();
- App.use(compression())
重启服务, 观察网络面板里面的 response header, 如果看到如下红圈里的字段则表明 gzip 开启成功
image
2. 引入 CDN
CDN(内容分发网络), 是一种公共服务, 他本身有很多台位于不同地域, 接入不同运营商的服务器, 而所谓的使用 CDN 实质上就是让 CDN 作为网站的门面, 用户访问到的是 CDN 服务器, 而不是直接访问到网站. 由于 CDN 内部对 TCP 的优化, 对静态资源的缓存, 预取, 加上用户访问 CDN 时, 会被智能地分配到最近的节点, 降低大量延迟, 让访问速度可以得到很大提升一个原则是尽量将比较大的第三方库放到 cdn 上去以减少请求时间,
在我的项目中, 我将 vue,vuex,vue-router,vant 都放到了 cdn 上, 具体操作是打开 BootCDN 或者 https://www.jsdelivr.com / 然后搜索关键字并 copy 链接粘贴到 index.html 的 body 闭合标签前, 如下图
image
注意选取 min.JS(体积最小), 然后在 webpack.base.conf.JS 里设置 externals 选项, 目的是不打包这些选项, 由于 index.HTML 中 script 的引入, 比如 vue 就会有一个全局变量 Vue 存在, 因此这里 external 的 value 就是 Vue
- externals: {
- 'vue': 'Vue', // 左侧 vue 是我们自己引入时候要用的, 右侧是开发依赖库的主人定义的不能修改
- 'vue-router': 'VueRouter',
- 'axios': 'axios',
- 'qs': 'Qs',
- 'vant': 'vant',
- 'es6-promise': 'ES6Promise',
- 'vue-baidu-map': 'VueBaiduMap',
- 'weixin-js-sdk': 'jWeixin',
- },
cdn 使用后优势是巨大的, 观察 network 面板, 时间几乎都在 50ms 以下
image
3. 路由懒加载
路由懒加载也叫延迟加载, 即在需要的时候进行加载, 随用随载. 像 vue 这种单页面应用, 如果没有应用懒加载, 运用 webpack 打包后的文件将会异常的大, 造成进入首页时, 需要加载的内容过多, 时间过长, 会出现长时间的白屏, 即使做了 loading 也是不利于用户体验, 而运用懒加载则可以将页面进行划分, 需要的时候加载页面, 可以有效的分担首页所承担的加载压力, 减少首页加载用时.
Vue 官网的示例如下, 采用异步组件和 webpack 的 code-splitting 结合
image
因此在项目中, 进入 router 的 index.JS 中, 将原来的 import Comp from '@/component/xxx'改为如下, vue-router 的配置项还是保持不变
- {
- path: '/index',
- name: "index",
- component: resolve => require(['../page/home/Index.vue'], resolve),
- meta: {title: '首页'}
- },
- {
- path: '/personal',
- name: 'personal',
- component: resolve => require(['../page/personal/PersonalCenter.vue'], resolve),
- meta: {title: '我的'}
- },
4. 第三方按需加载
这个在另一个项目里面用到了, 项目里面使用的 echarts, 只用到了一个柱状图组件, 其余的都没有用到, 但是这样 import 后打包时却会把整个 echarts 都打入包内, 造成空间浪费
import echarts from 'echarts
因此只需要 import 用到的组件即可, 如下, 这样就可以减少很多不必要的体积
- import echarts from 'echarts/lib/echars'
- import 'echarts/lib/chart/bar'
- import 'echarts/lib/component/legend'
- import 'echarts/lib/component/title'
5. 图片转 base64
小图片可以转为 base64 字符串然后嵌入 img 的 src 中, 节省 http 请求数量, webpack 中用 url-loader 处理, limit 控制了图片转 base64 的阈值, 小于该值就转 base64
- {
- test: /\.(PNG|jpe?g|gif|svg)(\?.*)?$/,
- loader: 'url-loader',
- options: {
- limit: 10000,
- name: utils.assetsPath('img/[name].[hash:7].[ext]')
- }
- },
6. 优化后性能
经过上述优化后, 首页打开时间迅速下降, DomContentLoaded 用时不到 10s,load 完全加载用时不到 4s, 耗时较多的是几张背景大图, 本来体积就大, 后续考虑放到 cdn 上.
image
ps:webpack-bundle-analyzer 是神器, 能够有效分析出包占用的体积情况~ 下图是最终优化后的包组成结构图, 最初打包的结构图比下图大很多, 主要多了 vue,vue-router,vuex 模块.
image
整个优化就完成啦~
恭喜你, 又掌握了一个新技能~
来源: http://www.jianshu.com/p/c611b1003f5e