Vue webpack 压缩打包上线 首屏加载时间过长 优化方案

Vue 上线优化方案

#1 为什么要引入外部CDN

最近博客上线,但是在首次加载的时候,需要消耗很多时间,大概在50秒左右,就是说第一页登录页面,就需要用户等待50秒(服务器是最低配置也是一个原因),看了一下network,发现有两个文件加载的时间特别长,一个是vendor.js,一个是app.js,打包的时候,这两个文件也提示文件过大

20191203213946-image.png

最终,结合网上的前辈们的解答,首屏加载时间过长重要有以下几点:

  1. 图片,登录页面(打开网站的第一个页面)静态图片过多也会在首屏中加载出来,消耗时间
  2. Vue代码里面Router没有使用懒加载
  3. 使用npm安装第三方库

#2 如何优化?

根据以上三点,具体优化步骤如下 :

#2.1 登录页面(打开网站的第一个页面)图片

主要的处理方式就是减小图片的大小 我这里直接把登录页面的背景图片全部去掉,这样子直接可以省很多时间

#2.2 Router懒加载

webpack默认将所有js源代码打包成一个js文件,导致JS包会变得非常大,影响页面首次加载速度 按需加载能把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件的js文件

  • 没有优化前的路由:
代码语言:javascript
复制
// 优化前的路由
import Home form "@/views/home/home"
import Listblog form "@/views/listblog/listblog"
import Createblog form "@/views/createblog/createblog"
import Login form "@/views/login/login"
import Test form "@/views/test/test"

export default new VueRouter({
routes: [
{
path: '/',
name: 'Home',
component:Home
redirect:"/dashboard",
children:[
{
path: "/listblog",
component: Listblog,
},
{
path: "/createblog",
component: Createblog
},
]
},
{
path: '/login',
name: 'Login',
component: Login
},
{
path: '/test',
name: 'Test',
component: Test
},
]
})

  • 优化后的路由:
代码语言:javascript
复制
// 优化后的路由

export default new VueRouter({
routes: [
{
path: '/',
name: 'Home',
component:(resolve) => require(["@/views/home/home"], resolve)
redirect:"/dashboard",
children:[
{
path: "/listblog",
component: (resolve) => require(["@/views/listblog/listblog"], resolve),
},
{
path: "/createblog",
component: (resolve) => require(["@/views/createblog/createblog"], resolve)
},
]
},
{
path: '/login',
name: 'Login',
component: (resolve) => require(["@/views/login/login"], resolve)
},
{
path: '/test',
name: 'Test',
component: (resolve) => require(["@/views/test/test"], resolve)
},
]
})

优化前和优化后的路由对比,优化后,使用箭头函数,将组件导入,而不是在文件开头,将所有的组件一次全部倒入,一次全部倒入会导致加载时间长,对用户体验不友好

#2.3 引入外部CDN

CDN是构建在网络之上的内容分发网络,依靠部署在各地的边缘服务器,通过中心平台的负载均衡、内容分发、调度等功能模块,使用户就近获取所需内容,降低网络拥塞,提高用户访问响应速度和命中率。

引入外部CDN,就是说,不需要npm下载对应的库,从而减小vendor.js的体积,但是又不会影响库的正常使用,因为这些库放到CDN上之后,下载速度非常快,而且是并行的下载,下面就说说如何引入外部CDN

我的项目这几个库需要外部引入CDN

代码语言:javascript
复制
vue
vuex
axios
vue-router
view-design
element-ui
echarts
countup

引入外部CDN大致需要三部:

  • 配置文件webpack.base.conf.js
  • 去掉原来npm引入库的那些代码
  • 在index.html引入CDN链接
  1. 配置webpack.base.conf.js

bulid/webpack.base.conf.js

加上 externals

代码语言:javascript
复制
...
module.exports = {
    ...
    module: {
        ...
    },
    externals:{
        "vue": 'Vue',
        "vuex":"Vuex",
        "axios":"axios",
        "vue-router":"VueRouter",
        "view-design":"ViewUI",
        'element-ui': 'ELEMENT',
        'echarts': 'echarts',
        'countup': 'countup',
    },
    ...
}
  1. 去掉npm引入的那些代码(Vue不能去掉)

src/main.js

代码语言:javascript
复制
...
import Vue from 'vue' // 这个不变
// import ViewUI from 'view-design'; // 使用CDN后注释掉
// import 'view-design/dist/styles/iview.css'; // 使用CDN后注释掉
// import 'element-ui/lib/theme-chalk/index.css'
// import element from './other_ui/element/index'
// Vue.use(ViewUI);
// Vue.use(element);

store/index.js

去掉Vuex的npm导入方式

代码语言:javascript
复制
// import Vue from 'vue'
// import Vuex from 'vuex' // 使用CDN后注释掉
// Vue.use(Vuex); // 使用CDN后注释掉

axios/index.js

去掉axios的npm导入方式

代码语言:javascript
复制
// import axios from 'axios'

router/index.js

去掉vue-router的npm导入方式

代码语言:javascript
复制
// import Vue from 'vue'
// import VueRouter from 'vue-router'
// Vue.use(VueRouter);

相应的countup和echarts在使用的时候也不需要import,直接注释掉

代码语言:javascript
复制
// import echarts from 'echarts'
// import countup from 'countup'
  1. index.html引入CDN
代码语言:javascript
复制
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.2"></script>
<script src="https://unpkg.com/vuex@3.1.1"></script>
<script src="https://cdn.bootcss.com/vue-router/3.0.1/vue-router.min.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<link rel="stylesheet" href="https://unpkg.com/element-ui@2.12.0/lib/theme-chalk/index.css">
<script src="https://unpkg.com/element-ui@2.12.0/lib/index.js"></script>
<link rel="stylesheet" type="text/css" href="http://unpkg.com/view-design@4.0.0/dist/styles/iview.css">
<script type="text/javascript" src="http://unpkg.com/view-design@4.0.0/dist/iview.min.js"></script>
<script src="https://cdn.bootcss.com/echarts/4.0.4/echarts.min.js"></script>
<script src="https://cdn.bootcss.com/countup.js/1.8.2/countUp.min.js"></script>

为了避免升级版本的问题,请在引入CDN的时候加上版本号,没有版本号,默认是最新的库,不同的库,不同的CDN,引入版本号的方式不一样,需要具体到对应的网站上查看如何锁定版本

#2.4 启用 Gzip 压缩

vue 默认不启用 Gzip 压缩,但我们知道,压缩后的文件体积会大大减少,这适用于线上部署。 如何启用也很简单: 首先,在 config 中将 build.productionGzip 设置为 true 然后,确认 webpack.prod.conf.js 中有如下代码(默认是有的,没有的手动添加):

代码语言:javascript
复制
if (config.build.productionGzip) {
  const CompressionWebpackPlugin = require('compression-webpack-plugin')

webpackConfig.plugins.push(
new CompressionWebpackPlugin({
asset: '[path].gz[query]',
algorithm: 'gzip',
test: new RegExp(
'\.(' +
config.build.productionGzipExtensions.join('|') +
')$'
),
threshold: 10240,
minRatio: 0.8
})
)
}

下面只要使用 npm install --save-dev compression-webpack-plugin 安装 webpack 插件

代码语言:javascript
复制
npm install --save-dev compression-webpack-plugin@1.1.12

这样,你在 build 项目时,webpack 会帮你压缩文件。
如果没有的话,你只要把上面代码复制到 webpack 配置文件的 plugins 下即可。
如何方面查看build之后的文件大小呢?我们可以使用另外一个 webpack 插件:webpack-bundle-analyzer ,如何使用呢?默认 Vue 会导入这个插件,我们只需要调用即可:在 package.json 文件中增加以下命令:
“analyzer”: “NODE_ENV=production npm_config_report=true npm run build”,

20191203233055-image.png

运行 npm run analyzer ,等待一会,就可以看到整个项目的打包情况了。

20191203233146-image.png

nginx配置一句话即可

代码语言:javascript
复制
nginx.conf文件
http{
...
gzip_static on; #静态压缩
...
}
20191203233426-image.png

#3 验证

#3.1 打包

20191203221548-image.png

虽然这两个文件的体积已经减少了不少,但是webpack还是提示文件big,还有待优化呀!!!