提升首屏頁面加載速度,解決vue-cli打包後單個文件過大的問題

本教程是針對vue-cli3以上的版本,其實原理都大同小異,這個demo爲vue-cli直接建立的項目,並在main.js中引入了echartelement-uilodashjavascript

首先看demo打包後生成的文件大小,這個demo裏面什麼業務都沒寫、僅僅引入了幾個包,chunk-vendors.js就達到了1.6M之多,若是是寫入了龐大的業務後沒作任何優化處理,那麼這個文件可能會達到10M之多,這發生在我真實的項目經歷中
html

藉助webpack-bundle-analyzer幫助分析

首先安裝webpack-bundle-analyzervue

yarn add webpack-bundle-analyzer -D

而後在項目根目錄建立vue.config.js,而後在文件中寫入如下代碼java

const WebpackBundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin

module.exports = {
    configureWebpack: {
        plugins: [new WebpackBundleAnalyzerPlugin()]
    }
}

而後執行yarn build 在瀏覽器會自動打開咱們的使用包分析文件,大體以下圖的樣子
node

咱們能夠看到生成的最大文件爲chunk-vendors.js,這個文件主要又由echartselement-uilodashzrender組成,其中echartselement-uilodash爲咱們項目開發時必要引入的文件,因此咱們若是把這寫文件分離出來那麼文件天然就會小了不少webpack

如何分離這些文件

咱們能夠藉助wepack配置項裏面的externals來達到目的,在vue.config.js裏面加入以下代碼web

module.exports = {

    // ... other code
    
    configureWebpack: {
    
    // ... other code
    
        externals: {
            "lodash": '_',
            "vue": 'Vue',
            "echarts": 'echarts',
            "element-ui": 'ELEMENT',
        },
        
        // ... other code
        
    }
    
    // ... other code
    
}

externals 配置選項提供了「從輸出的 bundle 中排除依賴」的方法。咱們能夠經過script標籤引入這些資源,具體關於externals的介紹請點擊這裏
而後咱們再對應的public -> index.html文件加入如下代碼,其中BASE_URL指的是public目錄,你須要從官網下載對應的資源放在對應的目錄下vue-cli

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <link rel="icon" href="<%= BASE_URL %>favicon.ico">
    <title>optimize_vue</title>
  </head>
  <body>
    <noscript>
      <strong>We're sorry but optimize_vue doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
    </noscript>
    <div id="app"></div>
    <!-- built files will be auto injected -->
    <script src="<%= BASE_URL %>js/pace.min.js"></script>
    <script src="<%= BASE_URL + (process.env.NODE_ENV === 'development' ? 'js/vue-2.6.0.js' : 'js/vue-2.6.0.min.js') %>"></script>
    <script src="<%= BASE_URL %>js/element-ui-2.11.1.js"></script>
    <script src="<%= BASE_URL %>js/lodash.min.js"></script>
    <script src="<%= BASE_URL %>js/echarts.min-4.4.0.js"></script>
  </body>
</html>

而後咱們再看一下效果, lodash、echarts、elementui已經成功從webpack bundle分離出去了,打包後的chunk-vendors.js也只有24kb的大小

element-ui

使用路由懶加載

路由懶加載會只加載當前頁面須要的資源,代碼以下json

const Foo = () => Promise.resolve({ /* 組件定義對象 */ })
// or
const Foo = () => import(/* webpackChunkName: "group-foo" */ './Foo.vue')
const Bar = () => import(/* webpackChunkName: "group-foo" */ './Bar.vue')
const Baz = () => import(/* webpackChunkName: "group-foo" */ './Baz.vue')

注意若是使用import方式的引入須要安裝@babel/plugin-syntax-dynamic-import,而後在babel.config.js中加入下面代碼便可

module.exports = {
    
  // ... other code
  
  "plugins": ["@babel/plugin-syntax-dynamic-import"]
  
  // ... other code
  
}

關於process.env.NODE_ENV

相信你們在開發的時候必定會有跟多個開發環境,好比development/feature/sandbox/production,由於這玩意我真是吃了大虧,剛開始沒看文檔, 直接在執行package.json的script命令的時候經過cross-env NODE_ENV=xxx 來修改環境變量,致使沒法使用vue-cli工具爲咱們提供的代碼優化功能

注意: process.env_NODE_ENV的值只能爲developmentproduction,不要修改成其餘值,否則可能會出現其餘問題,若是你真的想在不一樣的環境使用不一樣的接口地址或者、其餘的內容咱們能夠用vue-cli爲咱們提供的--mode達到目的,好比

"scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "build:sanbox": "vue-cli-service build --mode sanbox",
    "build:feature": "vue-cli-service build --mode feature",
    "lint": "vue-cli-service lint",
    "precommit": "yarn lint"
}

這裏vue-cli會讀取項目根目錄下的.env/.env./.env..local相關文件***指的是--mode的值,--mode會修改process.env.NODE_ENV的值,咱們須要再對應的env裏面把NODE_ENV改寫回來,好比一個.env.sanbox環境代碼以下

NODE_ENV=production
VUE_APP_ENV=sanbox

當咱們執行yarn build:sanbox的時候就會加載這個文件,咱們能夠經過process.env.VUE_APP_ENV來訪問對應設置的值,注意只有VIE_APP_前綴的環境變量纔會被webpack.DefinePlugin靜態嵌入到客戶端側的包中。

好比咱們須要不一樣的構建命令構建不一樣的的publicPath的時候咱們能夠這樣作

const map = {
    production: '/',
    feature: '/feature',
    sanbox: '/sanbox',
    development: '/development',
}
const env = process.env.VUE_APP_ENV
const publicPath =  map[env]
const PATH = require('path')
const WebpackBundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin

module.exports = {
    publicPath,
    configureWebpack: {
        externals: {
            "lodash": '_',
            "qiniu": 'qiniu',
            "vue": 'Vue',
            "echarts": 'echarts',
            "element-ui": 'ELEMENT',
        },
        resolve: {
            extensions: ['.js', '.vue', '.json', '.ts', '.tsx'],
            alias: {
                '$root': PATH.resolve(__dirname)
            }
        },
        plugins: [new WebpackBundleAnalyzerPlugin()]
    }
}

到這裏就全部功能大功告成了,能夠美滋滋的去喝一杯咖啡了。

相關文章
相關標籤/搜索