288

Vue SPA 首屏加载优化实践

 6 years ago
source link: https://juejin.im/post/5a291092518825293b50366d
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Vue SPA 首屏加载优化实践

2017年12月08日 02:32 ·  阅读 27087
Vue SPA 首屏加载优化实践

本文记录笔者在Vue SPA项目首屏加载优化过程中遇到的一些坑及优化方案!

我们以 vue-cli 工具为例,使用 vue-router 搭建SPA应用,UI框架选用 element-ui , ajax方案选用 axios, 并引入 vuex ,使用 vuex-router-syncrouter 同步到 store ,服务器使用本地Nginx服务。

vue-init webpack vue-spa-starter-kit
cd vue-spa-starter-kit
npm install
npm install vuex element-ui axios -S
npm run dev
复制代码

vue-cli会自动打开浏览器,可以看到效果。我们在入口文件中引入vue-routerelement-uiaxios

// src/main.js
import 'babel-polyfill'
import Vue from 'vue'
import App from './App'
import axios from 'axios'
import store from './store'
import router from './router'
import {sync} from 'vuex-router-sync'
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'

Vue.config.productionTip = false

Vue.use(ElementUI)
Vue.prototype.$http = axios

sync(store, router)

/* eslint-disable no-new */
new Vue({
  el: '#app',
  store,
  router,
  template: '<App/>',
  components: { App }
})
复制代码

接下来我们不做任何修改,使用默认的配置进行打包,Nginx采用默认配置,部署到Nginx,启动Nginx服务,查看效果:

160309a3eed1073e~tplv-t2oaga2asx-zoom-in-crop-mark:4536:0:0:0.awebp

可以看出,在没有开发任何页面及功能的情况下,vendor.js 有788kb。如果我们再依赖一些其他的库,比如 echarts 等,vendor.js 能到 1M 以上。

使用CDN资源

我们要将 vuevue-routervuexelement-uivendor.js 中分离出来,使用CDN资源引入。国内的CDN服务推荐使用 BootCDN。国外不是很好用。。。

  • 首先在模板文件index.html中添加以下内容:

    ...
    <head>
      <link rel="stylesheet" href="https://cdn.bootcss.com/element-ui/2.0.7/theme-chalk/index.css">
    </head>
    <body>
      <div id="app"></div>
      <script src="https://cdn.bootcss.com/vue/2.5.9/vue.min.js"></script>
      <script src="https://cdn.bootcss.com/vuex/3.0.1/vuex.min.js"></script>
      <script src="https://cdn.bootcss.com/vue-router/3.0.1/vue-router.min.js"></script>
      <script src="https://cdn.bootcss.com/element-ui/2.0.7/index.js"></script>
      <!-- built files will be auto injected -->
    </body>
    复制代码
  • 修改 build/webpack.base.conf.js。关于 externals 配置项请自行查阅相关资料。

    module.exports = {
      ...
      externals: {
        'vue': 'Vue',
        'vuex': 'Vuex',
        'vue-router': 'VueRouter',
        'element-ui': 'ELEMENT'
      }
      ...
    }
    复制代码
  • 修改 src/router/index.js

    // import Vue from 'vue'
    import VueRouter from 'vue-router'
    // 注释掉
    // Vue.use(VueRouter)
    ...
    复制代码
  • 修改 src/store/index.js

    ...
    // 注释掉
    // Vue.use(Vuex)
    ...
    复制代码
  • 修改 src/main.js

    import 'babel-polyfill'
    import Vue from 'vue'
    import App from './App'
    import axios from 'axios'
    import store from './store'
    import router from './router'
    import {sync} from 'vuex-router-sync'
    import ELEMENT from 'element-ui'
    // import 'element-ui/lib/theme-chalk/index.css'
    
    Vue.config.productionTip = false
    
    Vue.use(ELEMENT)
    Vue.prototype.$http = axios
    
    sync(store, router)
    
    /* eslint-disable no-new */
    new Vue({
      el: '#app',
      store,
      router,
      template: '<App/>',
      components: { App }
    })
    复制代码

    注意!这里 element-ui 变量名要使用 ELEMENT,因为element-ui的 umd 模块名是 ELEMENT

再次打包,部署到Nginx服务,可以看到:

vendor.js 减少到了 112kb,提升85.5%!

再看CDN资源:

可以看出,5个请求共216kb,耗时619ms!

Nginx 开启 gzip

vendor.js 我们优化完了,接下来我们优化服务器上的资源。先看看没有开启 gzip 的效果:

可以看到有 13.5kb

Nginx开启gzip,修改nginx配置文件 nginx.conf:

...

http {
    ...
    
    gzip               on;
    gzip_min_length    1k;
    gzip_buffers       4  16k;
    #gzip_http_version  1.1;
    gzip_comp_level    2; # 压缩级别
    # 要压缩的mine类型
    gzip_types         text/plain application/javascript application/x-javascript text/javascript text/css application/xml application/xml+rss image/jpeg image/gif image/png image/svg+xml;
    gzip_vary          off;
    gzip_proxied       expired no-cache no-store private auth;
    gzip_disable       "MSIE [1-6]\."; # IE6不支持gzip
    
    ...
}
复制代码

关于 nginx gzip,请自行查阅相关资料

重启nginx服务,再看效果:

16030ca36a137f1d~tplv-t2oaga2asx-zoom-in-crop-mark:4536:0:0:0.awebp

可以看到服务器上的资源经过gzip压缩之后有 9kb,压缩比 13.3%。

development 和 production

上文中我们修改的是 build/webpack.base.conf.js,这样一来,本地开发的时候我们就不能使用 vue-devtools Chrome调试工具了,为了方便调试,我们需要将development和production 配置分开。

  1. 首先将 build/webpack.base.conf.jsexternals 配置项挪到 build/webpack.prod.conf.js 中:
// build/webpack.prod.conf.js
module.exports = {
  ...
  externals: {
    'vue': 'Vue',
    'vuex': 'Vuex',
    'vue-router': 'VueRouter',
    'element-ui': 'ELEMENT'
  }
  ...
}
复制代码
  1. 拷贝 index.html 模板文件,并命名为 index.prod.html; 将原来的 index.html 重命名为 index.dev.html,并删除 CDN 资源:
<!-- index.dev.html -->
<head>
  ...
  <!-- <link rel="stylesheet" href="https://cdn.bootcss.com/element-ui/2.0.7/theme-chalk/index.css"> -->
</head>
<body>
  <div id="app"></div>
  <!-- <script src="https://cdn.bootcss.com/vue/2.5.9/vue.min.js"></script>
  <script src="https://cdn.bootcss.com/vuex/3.0.1/vuex.min.js"></script>
  <script src="https://cdn.bootcss.com/vue-router/3.0.1/vue-router.min.js"></script>
  <script src="https://cdn.bootcss.com/element-ui/2.0.7/index.js"></script> -->
  <!-- built files will be auto injected -->
</body>

<!-- index.prod.html -->
<head>
  <link rel="stylesheet" href="https://cdn.bootcss.com/element-ui/2.0.7/theme-chalk/index.css">
</head>
<body>
  <div id="app"></div>
  <script src="https://cdn.bootcss.com/vue/2.5.9/vue.min.js"></script>
  <script src="https://cdn.bootcss.com/vuex/3.0.1/vuex.min.js"></script>
  <script src="https://cdn.bootcss.com/vue-router/3.0.1/vue-router.min.js"></script>
  <script src="https://cdn.bootcss.com/element-ui/2.0.7/index.js"></script>
  <!-- built files will be auto injected -->
</body>
复制代码
  1. 修改 build/webpack.dev.conf.js:
plugins: [
  ...
  new HtmlWebpackPlugin({
    filename: 'index.html',
    template: 'index.dev.html',
    inject: true
  })
]
复制代码
  1. 修改 build/webpack.prod.conf.js:
plugins: [
  ...
  new HtmlWebpackPlugin({
    filename: 'index.html',
    template: 'index.prod.html',
    inject: true,
    ...
  })
]
复制代码
  1. 修改 vue-routervuexelement-ui 的引用:
// src/main.js
...
if (process.env.NODE_ENV === 'development') {
  require('element-ui/lib/theme-chalk/index.css')
}
...

// src/router/index.js
import Vue from 'vue'
import VueRouter from 'vue-router'

if (process.env.NODE_ENV === 'development') {
  Vue.use(VueRouter)
}
...

// src/store/index.js
import Vue from 'vue'
import Vuex from 'vuex'

if (process.env.NODE_ENV === 'development') {
  Vue.use(Vuex)
}
...
复制代码

这样我们就可以愉快的在开发环境使用 vue-devtools Chrome调试工具了!

至此,我们初步的优化就完成了。我实际的项目首屏加载加上一些第三方客服,第三方校验等优化到近4s 左右。由于是演示项目,并没有开发其他的页面和功能,效果不是很明显,大家可以自行踩坑。大家有更好的方案,可以共同学习!


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK