Практика оптимизации загрузки первого экрана Vue SPA

Nginx Vue.js
Практика оптимизации загрузки первого экрана Vue SPA

написать впереди

В этой статье описаны некоторые ямки и решения по оптимизации, с которыми автор столкнулся во время первого процесса оптимизации загрузки экрана в проекте Vue SPA!

мы начинаем сvue-cliинструмент, например, используйтеvue-routerСоздание SPA-приложений, выбор UI-фреймворкаelement-ui, выбор схемы ajaxaxios, и представитьvuex,использоватьvuex-router-syncбудетrouterсинхронизировать с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-router,element-ui,axios

// 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 и проверяем результат:

Видно, что без разработки каких-либо страниц и функций,vendor.jsТам 788кб. Если мы зависим от некоторых других библиотек, таких какechartsЖдать,vendor.jsможет достигать более 1 млн.

Используйте ресурсы CDN

мы будемvue,vue-router,vuex,element-uiотvendor.jsОн отделяется от него и импортируется с помощью ресурсов CDN. Рекомендуется использовать отечественные сервисы CDNBootCDN. За границей это плохо работает. . .

  • Сначала в файле шаблона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Имя модуля umdELEMENT

Снова упакуйте его и разверните в сервисе Nginx, вы можете увидеть:

vendor.jsУменьшено до 112кб, прирост 85,5%!

Посмотрите еще раз на ресурсы CDN:

Видно, что сумма 5 запросов составляет 216 КБ, что занимает 619 мс!

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 и посмотрите на результат:

Видно, что ресурсы на сервере 9кб после сжатия gzip, а степень сжатия 13,3%.

разработка и производство

То, что мы изменили выше,build/webpack.base.conf.js, чтобы мы не могли использовать его при локальной разработкеvue-devtoolsИнструменты отладки Chrome, чтобы облегчить отладку, нам нужно разделить конфигурацию разработки и производства.

  1. Первое местоbuild/webpack.base.conf.jsсерединаexternalsЭлемент конфигурации перемещен в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-router,vuex,element-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 вышел!

Суммировать

На этом наша предварительная оптимизация завершена. Моя реальная загрузка первого экрана проекта плюс некоторое стороннее обслуживание клиентов, сторонняя проверка и т. Д. Оптимизированы примерно до 4 с. Поскольку это демонстрационный проект, никаких других страниц и функций не разработано, и эффект не очень очевиден, вы можете сами наступить на яму. У каждого есть лучший план, мы можем учиться вместе!