Vue打包優化之code spliting-02

前言
以前用 vuecli作了個博客,是一個單頁面項目,大概有十個路由。css

直接 npm run build打包出來,有一個 1M的巨大 js文件。html

clipboard.pngvue

先掛載到服務器上試試
好傢伙 這加載時間 彷彿過了半個世紀webpack

clipboard.pngweb

首屏頁面整整加載了 9s 光加載那個大文件就花了 8s
這必須得作個優化了,沒有用戶能忍受 9s的白屏而不關閉頁面的vue-cli

過程當中,我還順便把項目從 vuecli 2.x遷移到了 vuecli 3,因此接下來還會介紹一些它們在優化上的異同express

分析
vuecli 2.x自帶了分析工具
只要運行 npm run build --reportnpm

若是是 vuecli 3的話,先安裝插件element-ui

cnpm intall webpack
-
bundle
-
analyzer

save
-
dev瀏覽器

而後在 vue.config.js中對 webpack進行配置

chainWebpack
:

(
config
)

=>

{

/ 添加分析工具/

if

(
process
.
env
.

NODE_ENV

'production'
)

{

if

(
process
.
env
.
npm_config_report
)

{

config

.
plugin
(
'webpack-bundle-analyzer'
)

.
use
(
require
(
'webpack-bundle-analyzer'
).
BundleAnalyzerPlugin
)

.
end
();

config

.
plugins
.
delete
(
'prefetch'
)

}

}

}

再運行 npm run build --report

會在瀏覽器打開一個項目打包的狀況圖,便於直觀地比較各個 bundle文件的大小

clipboard.png

能夠看到 項目中全部的依賴,全部的路由,都被打包進了同一個文件中

另外,在瀏覽器中,也能夠經過 converge來查看代碼的使用情況

clipboard.png
紅色的是下載了但未使用的部分

路由懶加載
當打包構建應用時,JavaScript包會變得很是大,影響頁面加載。
若是咱們能把不一樣路由對應的組件分割成不一樣的代碼塊,而後當路由被訪問的時候才加載對應組件,這樣就更加高效了。

在一開始就下載完全部路由對應的組件文件,這明顯是不合適的,這就像下載一個 app了,因此咱們就須要使用路由懶加載

clipboard.png

在 router.js文件中,原來的靜態引用方式

import

ShowBlogs

from

'@/components/ShowBlogs'

routes
:[
path
:

'Blogs'
,
name
:

'ShowBlogs'
,
component
:

ShowBlogs

]

改成

routes
:[
path
:

'Blogs'
,
name
:

'ShowBlogs'
,
component
:

()

=>

import
(
'./components/ShowBlogs.vue'
)

以函數的形式動態引入,這樣就能夠把各自的路由文件分別打包,只有在解析給定的路由時,纔會下載路由組件

clipboard.png

首屏須要加載的文件變成了橙色的部分,被小弟們分流出去了 300k

若是是在 vuecli 3中,咱們還須要多作一步工做

由於 vuecli 3默認開啓 prefetch(預先加載模塊),提早獲取用戶將來可能會訪問的內容

在首屏會把這十幾個路由文件,都一口氣下載了

因此咱們要關閉這個功能,在 vue.config.js中設置

參考官網的作法:

clipboard.png

設置完畢後,首屏就只會加載當前頁面路由的組件了

element-ui按需加載
clipboard.png

首屏須要加載的依賴包,其中 element-ui整整佔了 568k
本來的引進方式引進了整個包:

import

ElementUI

from

'element-ui'

Vue
.
use
(
ElementUI
)

但實際上我用到的組件只有按鈕,分頁,表格,輸入與警告
因此咱們要按需引用:

import

{

Button
,

Input
,

Pagination
,

Table
,

TableColumn
,

MessageBox

}

from

'element-ui'
;

Vue
.
use
(
Button
)

Vue
.
use
(
Input
)

Vue
.
use
(
Pagination
)

Vue
.
prototype
.
$alert
=

MessageBox
.
alert

注意 MessageBox註冊方法的區別,而且咱們雖然用到了 alert,但並不須要引入 Alert組件

在 .babelrc文件中添加( vue-cli 3要先安裝 babel-plugin-component):

plugins
:

[

[

"component"
,

{

"libraryName"
:

"element-ui"
,

"styleLibraryName"
:

"theme-chalk"

}

]

]

clipboard.png
element-ui小了不少,不過看到那個顯眼的 table.js後想到, table組件只有後臺管理頁面用到了,不須要全局註冊,因此咱們刪除 main.js中 Table和 TablColumn的引用,並在後臺組件中局部註冊

import

{

Table
,

TableColumn

}

from

"element-ui"
;

components
:

{

"el-table"
:

Table
,

"el-table-column"
:

TableColumn

},

clipboard.png
table就被拆分到了路由文件中

組件重複打包
能夠看到上圖,有兩個路由文件都引用了 codemirror.js形成重複下載
咱們能夠在 webpack的 config文件中,修改 CommonsChunkPlugin的配置

minChunks
:

3

把3改成2,就會把使用2次及以上的包抽離出來,放進公共依賴文件,不過因爲首頁也有複用的組件,因此首頁也會下載這個公共依賴文件

clipboard.png

首頁下載了黃色和灰色部分
拆了半天,又回到原點

固然,咱們能夠繼續折騰 CommonsChunkPlugin的配置來解決這個問題
但在新版 webpack中, CommonsChunkPlugin被自由度更高,更高級的 SplitChunksPlugin代替

這也是爲何我要把項目遷移到 vuecli 3(使用 webpack4)
默認就作了優化,首頁只會下載灰色的部分( 235K)

gzip
拆完包以後,咱們再用 gzip作一下壓縮
安裝 compression-webpack-plugin

cnmp i compression
-
webpack
-
plugin
-
D

在 vue.congig.js中引入並修改 webpack配置

const

CompressionPlugin

=

require
(
'compression-webpack-plugin'
)

configureWebpack
:

(
config
)

=>

{

if

(
process
.
env
.

NODE_ENV

'production'
)

{

// 爲生產環境修改配置...

config

.
mode
=

'production'

return

{

plugins

:

[
new

CompressionPlugin
({

test

:

/.js$|\.html$|.css/
,

//匹配文件名

threshold

:

10240
,

//對超過10k的數據進行壓縮

deleteOriginalAssets

:

false

//是否刪除原文件

})]

}

}

clipboard.png
能夠看到 200k以上的文件被壓縮到了 100k之內

在服務器咱們也要作相應的配置
若是發送請求的瀏覽器支持 gzip,就發送給它 gzip格式的文件
個人服務器是用 express框架搭建的
只要安裝一下 compression就能使用

const
compression
=

require
(
'compression'
)

app
.
use
(
compression
())

注意,後面這一句,要放在全部其餘中間件註冊以前

最終效果
clipboard.png
首屏加載資源198k,加載時間1s,相比原來速度提高了90%

後記:css是否要拆分
vuecli 3和 vuecli2.x還有一個區別是
vuecli 3會默認開啓一個 css分離插件 ExtractTextPlugin

每個模塊的 css文件都會分離出來,整整13個 css文件,而咱們的首頁就請求了4個,花費了很多的資源請求時間。

咱們能夠在 vue.config.js中關閉它:

css

:

{

// 是否使用css分離插件 ExtractTextPlugin

extract

:

false
,

// 開啓 CSS source maps?

sourceMap

:

false
,

// css預設器配置項

loaderOptions

:

{},

// 啓用 CSS modules for all css / pre-processor files.

modules

:

false

},

clipboard.png

clipboard.png

打包出來的文件中,直接就沒有了 css文件夾。

取而代之的是整合起來的一個 js文件,負責在一開始就注入全部的樣式。

首屏加載文件數減小,但體積變大,最終測下來速度沒有太大差別。

因此,是否要css拆分就見仁見智,具體項目具體分析吧。

總結性能優化是一個很是使人愉悅的過程,同時也是個深坑,有着太多東西,本篇文章開了個頭,但願能對你們有所幫助

相關文章
相關標籤/搜索