Vue項目減肥之旅(前端項目體積精簡的幾種方法)

一個項目的文件大小分析圖
P.S. 本文同時適用於:使用webpack打包的項目。

俗話說得好,引用依賴一時爽,一直引用一直爽。javascript

在開發項目的過程當中,咱們每每須要引用到大量的第三方模塊(node modules)。確實,經過引用第三方模塊,能大大的簡化開發的過程,提升工程質量。但不免的,也帶來了「體積」這個問題。筆者曾經開發過一個簡單的網站項目,功能簡單,業務邏輯也只是純粹的查看信息。但在通過了混淆壓縮後,依然達到了1M多。是的,這個項目毫無疑問是不及格的。由於即使在現今隨隨便便百兆網絡的時代下,因爲服務器、通路等多重因素的影響下,整個項目的加載每每須要數秒鐘。在網絡上有人是這麼描述這幾秒鐘的:css

若是網頁加載時間超過4秒,約有四分之一的人會放棄打開該網頁。
若是網頁加載時間超過10秒,50%的移動用戶會放棄該網頁,約五分之三的人不會再返回該網站。html

因此,咱們在可容許的範圍內,除了在物理層面上加強咱們的訪問速度外,還應該從項目的根源入手,儘量的減小訪問須要的時間。
在本文中,筆者總結了以前項目中一些精簡項目的方法,但願能對各位看官有所幫助。vue

1、分析你的項目

通常狀況下,webpack是vue項目的不二之選。那麼,如何分析使用webpack打包後的包文件呢?在這裏就要介紹本文的核心主角包分析工具——webpack-bundle-analyzerjava

webpack-bundle-analyzer界面

衆所周知的,webpack是一個將網頁元素打包的工具。在一個JS文件中,不只包含了javascript的代碼,還包含了如「html」、「css」等等元素。若是純粹的經過直接分析包中的內容,或者經過分析webpack配置(甚至在Vue Cli 三、Angular Cli 3,根本就不存在webpack配置文件),是很是不現實的事情。而webpack-bundle-analyzer則能夠爲咱們提供圖形化的包分析。 node

webpack-bundle-analyzer界面

在webpack-bundle-analyzer中,咱們能夠看到各個模塊所佔項目的比例,以及模塊在StatParsedGzipped狀態下的大小。嗯,是的,這樣咱們就能找出使項目臃腫的元兇了!webpack

2、引入\開啓項目的分析功能

  • 使用Vue Cli 3的項目
    對於使用Vue cli 3管理的項目而言,它已經內置了包分析的功能。只須要在編譯時,加入參數--report便可生成分析報告。
  • 使用Vue Cli 2或其餘Webpack項目 首先,你須要安裝webpack-bundle-analyzer
# NPM 
npm install --save-dev webpack-bundle-analyzer
# Yarn 
yarn add -D webpack-bundle-analyzer
複製代碼

而後,添加到項目的配置文件中:git

const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
 
module.exports = {
  plugins: [
    new BundleAnalyzerPlugin()
  ]
}
複製代碼

編譯完畢後,即會生成分析報告。github

  • 題外話:Angular 項目
    與Vue Cli 3相似的,在ng cli中一樣包含了包分析的功能。在編譯時,加入參數--stats-json將會生成一個json文件。
    你能夠經過 ````webpack-bundle-analyzer``` 或者 webpack.github.io/analyse 分析包結構

3、精簡依賴

既然咱們如今已經知道了「元兇」是誰了,那咱們如今應該去處理它了。對於,不一樣的第三方模塊咱們有不一樣的方法去解決它:web

1. 常規方法:按需引入(最小化引入)

通常最經常使用的import形式是這樣的:

import crypto from 'crypto-js'
...
crypto.HmacSHA1()
...
複製代碼

這種方法將會引入整個crypto(第三方模塊)。然而,咱們每每僅須要其中的一兩個方法。這是一個很是不划算的行爲,同時也是項目中最多見的臃腫的緣由。經過局部引入須要的方法,咱們即可以很大程度的減小項目的臃腫程度:

import HmacSHA1 from 'crypto-js/hmac-sha1'
...
HmacSHA1()
...
複製代碼

至於如何找到局部引入的文件,由於不一樣模塊的項目結構不盡一致,因此沒有一個標準的答案。不過,最多見的方法,就是查看第三方模塊的入口文件或者查閱官方的文檔,每每能夠找到最小化引入的方法。

2. 折中的方法:異步加載

影響首屏加載速度的,是那些隨着html文件「同步」下載的js文件。有很多第三方模塊是不會在首屏加載時用到的,並且他們沒法經過「最小化引入」有效減小它們的大小。此時,便應該考慮將一些無需隨着首屏加載的內容,經過異步的形式,在它們須要的時候加載。
熟悉Vue的各位大佬們大概都早已熟知Vue異步組件的寫法

...
components: {
    asyncComponent: () => import('./asyncComponent.vue')
    // function(){
    // return import('./asyncComponent.vue')
    // }
}
...
複製代碼

但對於新手而言,他們可能會誤認爲這是Vue中提供的異步組件加載的方式。但實際上,這是webpack進行異步模塊加載的方法。import能夠運用在各個方面,如:加載Echarts

const Echarts = () => import('echarts')
...
 Echarts().then(echarts => {
     echarts.xxx()
 })
...
複製代碼

此方法也能夠在Angular 8中使用

3. 一些UI庫的按需引入

不少流行的UI庫是沒法直接按需引入須要的組件的(其實不少都是能夠的,但小部分組件會出現問題)。如:Element、ant-design-vue、iView 、Mint UI等等。但他們每每很是的「龐大」,多數可達2~3M。對於網頁應用而言,這確定是沒法接受的。不過萬幸的是,它們均可以經過babel-plugin-component進行按需引入(或者直接按需引入)。具體的方法能夠參閱它們各自的官方文檔。須要注意的是,因爲css文件是全局引入的,須要注意樣式被污染的問題。

4. 一些特殊的模塊的精簡方案

對於一些特殊的模塊而言,他們可能沒法使用「按需引入」的方法進行瘦身。就好比「moment.js」,在引入其本體的同時,它會附帶所有的多語言支持的模塊。但這些每每是咱們不須要的。

webpack ContextReplacementPlugin

ContextReplacementPlugin 能夠經過正則表達式或其餘過濾條件忽略引入的第三方模塊的某些文件,從而達到瘦身的需求。

在webpack的官方文檔中,正是以moment.js做爲實例的。

new webpack.ContextReplacementPlugin(
  /moment[\/\\]locale$/,
  /de|fr|hu/
)
複製代碼

既然這是一個大胖子。爲何不去換一個瘦子呢?

在全部的方法都沒法知足功能需求>文件體積的時候,爲什麼不嘗試換一個模塊試試呢?
在npm中充斥着大量的功能類似的module,好比:querystring,我所知的就有qs\query-string\querystringify...它們大多功能類似,但因爲實現的方法、考量的形式不一樣等等方面,致使了它們之間存在很多的差別。所以,爲了減小沒必要要的文件體積,咱們能夠嘗試選擇與之類似的或者功能沒有如此強大的但剛好符合咱們需求的模塊。就如「moment.js」在多數的狀況下,能夠被「dayjs」所替代。然後者則宣稱它只佔用2kb的空間。

固然,在選擇第三方模塊的時候,也須要考量這個模塊是否足夠的成熟。

5. 終極方案:本身實現吧

第三方模塊能幫助咱們解決不少問題。但並非全部的「複雜」功能都須要經過引入第三方模塊來解決。
舉個簡單的栗子:
若是你只須要獲取URL中的參數,你不須要引入Vue Router或者XXX Router。你只須要qs.parse(location.search)便可.甚至連qs庫都無需引入:

Object.fromEntries(
  location.search
    .slice(1)
    .split('&')
    .map(v => v.split('='))
)
複製代碼
相關文章
相關標籤/搜索