Vue包大小優(yōu)化的實(shí)現(xiàn)(從1.72M到94K)
一、背景
最近做了一個(gè)網(wǎng)站,uidea,是用來(lái)輔助獨(dú)立開(kāi)發(fā)者做一些 UI 設(shè)計(jì)的,當(dāng)時(shí)只管開(kāi)發(fā),等部署完以后,發(fā)現(xiàn)訪問(wèn)速度堪憂
畢竟是個(gè)小水管服務(wù)器,相比提高帶寬,還是先看看代碼上能不能優(yōu)化一下,性價(jià)比更高
這個(gè)是優(yōu)化前的包大小,這家伙都上 1.72 M 了,小水管加載時(shí)間直接往 3s 以上走了,臣妾扛不住啊

二、目標(biāo)
這必須得優(yōu)化一下,優(yōu)化前得大致定一下目標(biāo),目標(biāo)又需要指標(biāo)來(lái)衡量,所以定了兩個(gè)指標(biāo):
- 頁(yè)面加載時(shí)間不多說(shuō),至少得 1s 以內(nèi),越快越好
- 包大小控制在 200k 以內(nèi)
為什么定這兩個(gè)目標(biāo)呢?首先頁(yè)面加載時(shí)間是最終要解決的問(wèn)題,那頁(yè)面加載時(shí)間初步來(lái)看,影響因素有兩個(gè),網(wǎng)絡(luò)和包大小,網(wǎng)絡(luò)暫時(shí)缺錢沒(méi)法升級(jí),所以主要優(yōu)化就集中在包大小上
首先要定義什么是包大小,我這里主要指入口包大小,對(duì)應(yīng) Vue 就是 app.js 和 app.css,入口加載完頁(yè)面至少可以展示了
那包大小要優(yōu)化到什么程度呢?
一方面 vue-cli-service 建議不超過(guò) 244K,另一方面就是找對(duì)標(biāo),看看類似的網(wǎng)站包大小多少,那我們也有個(gè)參照,我選擇的是 materialpalette,看了下他的包大小大概在 150k 左右,我的功能更復(fù)雜一些,所以取了兩者中間的 200K 作為目標(biāo)
這里為什么要講目標(biāo)呢?因?yàn)槟繕?biāo)其實(shí)是很重要的,老話也說(shuō)有的放矢,沒(méi)有目標(biāo),那執(zhí)行的過(guò)程中很容易半途而廢,或者只前進(jìn)半步就終止了
拿談戀愛(ài)來(lái)說(shuō),如果你的目標(biāo)是找個(gè)女朋友,那大概率找不到,但是如果你的目標(biāo)是追到某個(gè)確定的女生(比如張三)做女朋友,那成功的概率就大大增加了,因?yàn)槟憧梢匀メ槍?duì)這個(gè)女生去做針對(duì)性的準(zhǔn)備
三、方案
目標(biāo)定了,然后就是定方案
雖然咱第一次做 Web 的優(yōu)化,但是之前有過(guò)安卓包大小優(yōu)化的經(jīng)驗(yàn)呀,道理總是相通的,所以第一時(shí)間想了下面幾個(gè)策略
- 代碼混淆
- 資源放到 cdn,因?yàn)殚_(kāi)發(fā)的時(shí)候圖省事,資源放在 assets 下面,直接 require 引入了,這也是一個(gè)大頭
- 無(wú)用庫(kù)刪除,功能相近的庫(kù)合并,只用到少部分功能的庫(kù),看看能否自己實(shí)現(xiàn)
- gzip 壓縮
- 第三方庫(kù)也放到 cdn
1 - 3 三個(gè)優(yōu)化方案是首先想到的,然后網(wǎng)上搜了下 Vue 對(duì)應(yīng)的優(yōu)化策略,又增加了后面兩個(gè)
還有一些其他方案,比如路由懶加載,但是因?yàn)檫@個(gè)網(wǎng)站主要內(nèi)容都集中在首頁(yè),所以這個(gè)就沒(méi)考慮了(好東西雖多,但因地制宜最好)
所以一共定了 5 個(gè)優(yōu)化策略,下面就開(kāi)干
四、執(zhí)行
1. 代碼混淆
代碼混淆就不多說(shuō)了,一方面節(jié)省包大小,一方面還能增加一些反編譯的難度,直接網(wǎng)上搜了 Vue 混淆配置(畢竟要站在巨人肩膀上),試了下確實(shí)好使,配置如下
const CompressionWebpackPlugin = require('compression-webpack-plugin');
module.exports = {
configureWebpack: (config) => {
// 引入uglifyjs-webpack-plugin
let UglifyPlugin = require('uglifyjs-webpack-plugin');
if (process.env.NODE_ENV == 'production') {
// 壓縮混淆
config.mode = 'production'
// 將每個(gè)依賴包打包成單獨(dú)的js文件
let optimization = {
minimizer: [new UglifyPlugin({
uglifyOptions: {
warnings: false,
compress: {
drop_console: true,
drop_debugger: false,
pure_funcs: ['console.log']
}
}
})]
}
Object.assign(config, {
optimization
})
} else {
// 為開(kāi)發(fā)環(huán)境修改配置
config.mode = 'development'
}
}
}
}
2. 資源放到 cdn
這一步也容易做,資源全部都放到阿里云 oss 上,幾分鐘搞定
3. 無(wú)用庫(kù)刪除
這一步花了不少時(shí)間,因?yàn)殚_(kāi)發(fā)的時(shí)候圖省事,很多庫(kù)直接 github 上一搜,yarn add 引入就完事了,現(xiàn)在需要細(xì)細(xì)的再拆分一下
在打包命令后面加 --report 看一下打包的狀態(tài)
yarn build --report

首先是去掉 ElementUi(gzip 壓縮后大約 158k),開(kāi)發(fā)的時(shí)候 ElementUi 和 Vuetify 混用了,其實(shí)只留一個(gè) Vuetify 就夠了,然后對(duì)界面做一些小小的改造就完成了
然后是 lodash,只用到了其中幾個(gè)方法,但是他的整個(gè)體積不小,gzip 壓縮后大概 25k,于是找了 lodash 源碼,打算把用到的幾個(gè)方法抽出來(lái),但是 lodash 代碼嵌套、引用太深了,不太抽,干脆直接干掉這個(gè)庫(kù),找了幾個(gè)更純粹的實(shí)現(xiàn)做了替換,主要時(shí)間花在了讀 lodash 源碼上
再然后就是 vuescroll,在實(shí)現(xiàn)滾動(dòng)條樣式自定義的時(shí)候,偷懶直接用了這個(gè)庫(kù),發(fā)現(xiàn)這個(gè)庫(kù)體積還是不小的,gzip 壓縮后將近 20k,直接干掉,自己寫(xiě)一下樣式吧(這件事告訴我們,現(xiàn)在偷的懶,以后會(huì)以別的方式還回來(lái)的 0_0)
這樣就干掉了幾個(gè)大頭庫(kù)
4. gzip 壓縮
這個(gè)是網(wǎng)上找的解決方案,直接在 vue.config.js 里加點(diǎn)配置,然后 nginx 里也需要做一下對(duì)應(yīng)的配置
// vue.config.js
module.exports = {
configureWebpack: (config) => {
if (process.env.NODE_ENV == 'production') {
// ...
// gzip
config.plugins.push(new CompressionWebpackPlugin({
algorithm: 'gzip',
test: /\.js$|\.html$|\.json$|\.css/,
threshold: 10240,
minRatio: 0.8
}))
}
// ...
}
}
// nginx 直接開(kāi)啟下面的配置
gzip_static on;
這樣打包以后,會(huì)生成 .gz 文件,nginx 會(huì)自動(dòng)使用 .gz 文件
5. 第三方庫(kù)放到 cdn
這里主要是處理 Vuetify 這個(gè)庫(kù),畢竟 gzip 以后也有將近 50k 的大小,放到 cdn 上會(huì)快一些
首先是打包配置中去掉 Vuetify
module.exports = {
// ...
configureWebpack: (config) => {
if (process.env.NODE_ENV == 'production') {
// 第三方庫(kù)不打包,使用 cdn
config.externals = {
vuetify: 'Vuetify'
}
} else {
// 為開(kāi)發(fā)環(huán)境修改配置
config.mode = 'development'
config.externals = {
vuetify: 'Vuetify'
}
}
}
}
然后在 index.html 里手動(dòng)加載 vuetify css 和 js
<link rel="external nofollow" rel="stylesheet"> <script src="https://cdn.staticfile.org/vuetify/2.4.4/vuetify.min.js"></script>
這里其實(shí)有一些更好的方式,可以通過(guò) webpack 參數(shù)傳給 index.html,通過(guò) ejs 引入,現(xiàn)在比較簡(jiǎn)單,這里就沒(méi)做了
五、效果
通過(guò)上面幾個(gè)策略,最終包大小從 1.72 M 優(yōu)化到 94k

六、后續(xù)
總體看來(lái),優(yōu)化效果是明顯的,但是還有后續(xù)可以做的事情:
- 更精細(xì)化優(yōu)化,應(yīng)該可以結(jié)合 webpack 做更深的定制化
- 對(duì)上面說(shuō)到的 cdn 上的第三方庫(kù)做整合,畢竟直接放在 index.html 里太散,并不是很好的項(xiàng)目結(jié)構(gòu),也不利于后面開(kāi)發(fā)
- 對(duì)后續(xù)的代碼開(kāi)發(fā)做規(guī)范,比如三方庫(kù)引用的規(guī)范、資源的引入規(guī)范等等,可以做的事情還是很多的
- 每次部署前的性能測(cè)試,主要看看頁(yè)面加載速度是否達(dá)標(biāo)
可以做的事情還很多,有時(shí)候做一件事,達(dá)成目標(biāo)并沒(méi)有結(jié)束,維持目標(biāo)也是需要考慮的
到此這篇關(guān)于Vue包大小優(yōu)化的實(shí)現(xiàn)(從1.72M到94K)的文章就介紹到這了,更多相關(guān)Vue包大小優(yōu)化內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue3中pinia的使用及持久化的實(shí)現(xiàn)
Pinia是一個(gè)基于Vue3的狀態(tài)管理庫(kù),本文主要介紹了vue3中pinia的使用及持久化的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2025-04-04
Vue導(dǎo)出頁(yè)面為PDF格式的實(shí)現(xiàn)思路
這篇文章主要介紹了Vue導(dǎo)出頁(yè)面為PDF格式的實(shí)現(xiàn)思路,其實(shí)思路也很簡(jiǎn)單,就是將頁(yè)面轉(zhuǎn)換成圖片格式.然后通過(guò)圖片的base64碼.生成PDF..感興趣的朋友跟隨腳本之家小編一起看看吧2018-07-07
Vue項(xiàng)目報(bào)錯(cuò):Uncaught SyntaxError: Unexpected token <
這篇文章主要介紹了Vue項(xiàng)目報(bào)錯(cuò):Uncaught SyntaxError: Unexpected token <,在引入第三方依賴的 JS 文件時(shí),遇到的一個(gè)問(wèn)題,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-11-11
使用Vue.js實(shí)現(xiàn)一個(gè)循環(huán)倒計(jì)時(shí)功能
在Web應(yīng)用中,倒計(jì)時(shí)功能常用于各種場(chǎng)景,如活動(dòng)倒計(jì)時(shí)、定時(shí)任務(wù)提醒等,Vue.js作為一款輕量級(jí)的前端框架,提供了豐富的工具和API來(lái)實(shí)現(xiàn)這些功能,本文將詳細(xì)介紹如何使用Vue.js實(shí)現(xiàn)一個(gè)循環(huán)倒計(jì)時(shí)功能,需要的朋友可以參考下2024-09-09
vue使用splice()刪除數(shù)組中的一個(gè)數(shù)據(jù) 彈出窗口提示問(wèn)題
這篇文章主要介紹了vue使用splice()刪除數(shù)組中的一個(gè)數(shù)據(jù) 彈出窗口提示問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-07-07
vue計(jì)算屬性想要傳入?yún)?shù)如何解決
這篇文章主要介紹了vue計(jì)算屬性想要傳入?yún)?shù)如何解決問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-01-01

