在日常的 Vue 项目开发中,随着业务的日渐负责,代码量的日益增加,随之带来的问题就是打包后的 vendor.js 体积过大,导致加载时空白页时间过长,给用户的体验太差。为此我们需要减少 vendor.js 的体积,从本质上来解决这种问题。
这里大概例举几个在项目中实际用到过的方法,优化后的 js 大概缩小了 50% 左右,效果还是挺明显的。
1,webpack externals
为什么要配置 externals
官方解释:webpack 中的 externals 配置提供了不从 bundle 中引用依赖的方式。解决的是,所创建的 bundle 依赖于那些存在于用户环境 (consumer environment) 中的依赖。
比如我们会在项目中引用各种第三方的 js 文件,如 jquery,vue,axios 等,如果我们在打包时排除这些依赖,则可以大大减小文件的大小,提高页面加载速度,配置方法如下:
// 在 index.js 中引入资源
<script src="jquery.js"></script>
<script src="vuex.js"></script>
module.exports = {
...
output: {...},
externals : {
jquery: 'jQuery'
'vue': 'Vue',
}
...
}
这样就剥离了那些不需要改动的依赖模块,换句话,下面展示的代码还可以正常运行:
import $ from 'jquery';
import Vue from 'vue'
这样不仅之前对第三方库的用法方式不变,还把第三方库剥离出 webpack 的打包中,从而加速 webpack 的打包速度。
2,组件按需加载
这也是可以优化的点。如果频繁使用了第三方组件 /UI 库,如我的项目中经常使用了 element-ui 组件库,如果全部引入,项目体积非常大,这时可以按需引入组件。
首先,我们需要安装 babel-plugin-component
npm install babel-plugin-component -D
然后,将.babelrc 修改为:
{"presets": [["es2015", { "modules": false}]],
"plugins": [
[
"component",
{
"libraryName": "element-ui",
"styleLibraryName": "theme-chalk"
}
]
]
}
然后引入部分组件,这样一来,就不需要引入样式了,插件会帮我们处理。
// main.js
import Vue from 'vue'
import {Dialog, Loading} from 'element-ui'
[Dialog, Loading].forEach((comp) => {Vue.use(comp);
})
3,路由懒加载
当打包构建应用时,JavaScript 包会变得非常大,影响页面加载。如果我们能把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件,这样就更加高效了。
方法一
const login = () => import('@/components/login')
const router = new VueRouter({
routes: [{ path: '/login', component: login}
]
})
注意:这个时候我们需要安装 babel-plugin-syntax-dynamic-import 插件,这样打包时才会识别该语法
方法二
有时候我们想把某个路由下的所有组件都打包在同个异步块 (chunk) 中。只需要使用 命名 chunk,一个特殊的注释语法来提供 chunk name (需要 Webpack > 2.4)。
const Foo = () => import(/* webpackChunkName: "group-foo" */ './Foo.vue')
const Bar = () => import(/* webpackChunkName: "group-foo" */ './Bar.vue')
const Baz = () => import(/* webpackChunkName: "group-foo" */ './Baz.vue')
4,数据缓存——keep-alive
VUE2.0 中提供了一个 keep-alive 方法,可以用来缓存组件,避免多次加载相应的组件,减少性能的消耗。
举例:用户浏览 A 页面,待 A 页面的资源都加载完毕了,用户通过路由跳转到了 B 页面,之后又退回到了 A 页面,如果没有特殊处理的话,A 页面的资源会重新加载一遍,造成资源浪费;若我们做了缓存,则可以减少请求的次数,极高用户体验。
1,缓存部分页面
<keep-alive>
<router-view v-if="$route.meta.keepAlive"></router-view>
</keep-alive>
<router-view v-if="!$route.meta.keepAlive"></router-view>
// router 设置如下
routers:[
{ path: '/home',
name: home,
meta: {keepAlive: true} // 设置为 true 表示需要缓存,不设置或者 false 表示不需要缓存
}
]
2,缓存组件
<!-- 基本 -->
<keep-alive>
<component :is="view"></component>
</keep-alive>
// include 和 exclude 属性允许组件有条件地缓存。二者都可以用逗号分隔字符串、正则表达式或一个数组来表示
<!-- 逗号分隔字符串 -->
<keep-alive include="a,b">
<component :is="view"></component>
</keep-alive>
<!-- 正则表达式 (使用 `v-bind`) -->
<keep-alive :include="/a|b/">
<component :is="view"></component>
</keep-alive>
<!-- 数组 (使用 `v-bind`) -->
<keep-alive :include="['a','b']">
<component :is="view"></component>
</keep-alive>
除了以上的优化方法外,还有常规的 图片的压缩合并、CDN 加速、压缩代码等方法,大家应该都很熟悉了,这里就不在一一阐述了。如果大家还有好的优化方案,欢迎大家留言交流~