1. 程式人生 > >vue element-ui 優化打包 bundle js 大小

vue element-ui 優化打包 bundle js 大小

背景

最近開發的一個專案使用了 vue+ element-ui 的技術棧,當然,還有其他的一些工具庫,比如 axios

說一下我的開發步驟,基礎結構是通過 [email protected] 建立的,手動的加入了 axios vuex , vue-router 是腳手架自帶的。

code split

1. 路由懶載入

使用 vue-router 的時候,如果按照預設配置,所有的路由都會被打包到一個 bundle.js 檔案中去(bundle 檔名一般是 app.js)。

進入 router/index.js 檔案中,只需要將所有類似 import Home from '@/components/home';

替換為 const Home = () => import('@/components/home')

其餘部分不需要變。就能以最簡單的形式做到根據路由來劃分 webpack 打包的模組。這個時候 執行 npm run build 是就能看到多了很多小的 js 檔案, 並且app.js 檔案的體積也減小了。

附上程式碼示例:

import Vue from 'vue'
import Router from 'vue-router'
const AdminIndex = () => import('@/components/admin-index')
const Home = () => import('@/components/home')

Vue.use(Router)

export default new Router({
  routes: [
    {
      path: '/',
      name: 'admin-index',
      component: AdminIndex
    },
    {
      path: '/home',
      name: 'home',
      component: Home
    }
  ]
})

2. 元件懶載入

跟路由懶載入的形式一樣,也是使用 () => import('xxx') 的形式。
如果對於一個容器元件中,import 很多個元件進來,使用元件懶載入,能夠繼續減小首次載入的檔案大小。示例程式碼:

<template>
  <div>
    <HomeHeader />
    <SearchContainer  />
    <HomeFooter />
  </div>
</template>

<script>
import HomeHeader from "./home-header";
import HomeFooter from "./home-footer";
import SearchContainer from "./containers/search-container";
import LoadingComponent from "@/components/common/loading";

export default {
  name: "home",
  components: {
    HomeHeader,
    HomeFooter,
    SearchContainer,
    LoadingComponent
  }
};
</script>

優化之前:
在這裡插入圖片描述
在這裡插入圖片描述

元件懶載入優化之後:

<template>
  <div>
    <HomeHeader />
    <SearchContainer  />
    <HomeFooter />
  </div>
</template>

<script>
const HomeHeader = () => import("./home-header");
const HomeFooter = () => import("./home-footer");
const SearchContainer = () => import("./containers/search-container");
export default {
  name: "home",
  components: {
    HomeHeader,
    HomeFooter,
    SearchContainer
  }
};
</script>

在這裡插入圖片描述

從檔案的個數中,不知道有沒有看出什麼?

app.js 是屬於 專案的公共部分的程式碼而宣告一個 const HomeHeader = () => import("./home-header"); 類似的元件,就會建立一個 n.js 檔案,達到了繼續拆分比較大的js包的目的。

所以其實只要你願意,可以一部分元件使用 const HomeHeader = () => import("./home-header"); 另一部分元件使用 import HomeHeader from "./home-header";

不過總的來說,除非一個元件過於龐大了,在我開發過程中,才會想著用元件拆分的形式。每一個小元件都這樣拆分,最終得到很多很多個小的js檔案,反而是因為網路請求的原因,拖慢載入速度的。

3. webpack-bundle-analyzer

在做一個專案的一開始,其實我都沒有去考慮過效能優化、code split 的事情,只有當邏輯越來越多,開發的時候明顯感覺到頁面載入速度慢了,network裡看到 bundle.js 體積巨大了,才會想著去做優化的考慮。

emmm 所以到底應該怎麼拆?拆哪些部分?這個需要webpack-bundle-analyzer 來幫忙,code split 也要有理有據。

安裝和配置

如果你跟我一樣,使用的是 [email protected] 的話,webpack-bundle-analyzer 外掛是已經安裝了的,webpack 也配置好了的。

反正你就全域性搜尋一下 webpack-bundle-analyzer 就好了,看看 package.json 中有沒有依賴,webpack 配置中有沒有,一般只在webpack.prod.conf.js 中,因為開發環境下也不會去看的。

如果實在沒有,那就手動安裝和配置好了。

npm intall webpack-bundle-analyzer –save-dev

在build/webpack.prod.config.js中新增配置:

if (config.build.bundleAnalyzerReport) {
  const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
  webpackConfig.plugins.push(new BundleAnalyzerPlugin())
}

package.jsonscript 中新增:

“analyz”: “NODE_ENV=production npm_config_report=true npm run build”

如果你是window 使用者的話,應該是:

“analyz”: “set NODE_ENV=production npm_config_report=true npm run build”

執行: npm run analyz

等專案 build 完了之後,就會自動開啟一個頁面了,
在這裡插入圖片描述

4. element-ui 庫的優化

重點終於來了(不是標題黨。。。。)。從上面的圖中我們可以看到,vendor.xxx.js 實在是有點大,webpack build 完了之後,也細心的為我們標註出了 big:
在這裡插入圖片描述

解決辦法是對於 element-ui 這個 ui 庫從 vendor.xx.js 檔案中剝離出來,最簡單的辦法就是使用 公共的cdn了。這裡再做一層更徹底的剝離,將vue, vuex, vue-router,axios 等依賴檔案,全部使用cdn。
在這裡插入圖片描述
看好這些依賴的版本,直接去 百度搜索相關的 cdn 檔案。下面我直接貼我修改之後的程式碼:

index.html

...
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">

...
<body>
  <div id="app"></div>
  <!-- cdn 加速,減小 vendor.js 體積 -->
  <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17-beta.0/vue.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/vuex/3.0.1/vuex.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/vue-router/3.0.1/vue-router.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.18.0/axios.min.js"></script>
  <script src="https://unpkg.com/element-ui/lib/index.js"></script>
  <!-- built files will be auto injected -->
</body>

package.json

上面引入過 cdn 檔案的依賴, 全都可以去掉了。

main.js

刪除或者註釋跟element 相關的程式碼:

import ElementUI from 'element-ui';
...
import 'element-ui/lib/theme-chalk/index.css';
...
Vue.use(ElementUI);
...

webpack.base.conf.js

在 webpack 配置中新增外部擴充套件:

module.exports = {
...
      // 外部擴充套件,通過 cdn 引入,不會被webpack打包
	  externals: {
	    'vue': 'Vue',
	    'vue-router': 'VueRouter',
	    'vuex': 'Vuex',
	    'axios': 'axios'
	  }
  }

這個時候已經好了,清除一下專案 node_modules 中的刪除的不需要的依賴吧, uninstall 也行,直接刪除整個 node_modules 資料夾,重新 npm install 也行。

處理完 node_modules 之後, npm start 再次看一下我們優化之後的結果:

在這裡插入圖片描述

開發狀態下的 app.js 明顯已經變小了,build 之後的檔案也是。

這裡需要注意的一點是,依賴庫使用 cdn 檔案來載入話,網路請求的速度與 cdn 的速度有關,如果不放心別人的 cdn ,將上述的 cdn 檔案內容下載到本地放在 static 目錄下當做靜態檔案即可。

建議使用 CDN 引入依賴的使用者在連結地址上鎖定版本,以免將來升級時受到非相容性更新的影響。

vue 專案的 code split ,差不多就是這樣了。感謝閱讀, Happy Coding !