前言
因?yàn)檫@系統(tǒng)之前一直在不斷迭代,現(xiàn)在暫時(shí)告一段落了龙宏,我趕緊趁著開(kāi)年工作不多的空余時(shí)間棵逊,把這個(gè)系統(tǒng)優(yōu)化一下伤疙,不然我可能就被優(yōu)化了银酗。
優(yōu)化做啥
說(shuō)到優(yōu)化,網(wǎng)上一查一大堆教你的方法徒像,要說(shuō)的話黍特,人人都能說(shuō)兩句,但是做的話不一定人人都能做好锯蛀。那么我們?cè)撊绾芜\(yùn)用這些知識(shí)呢灭衷?
本系統(tǒng)基本情況:
- 構(gòu)建工具 vite4
- 框架 vue3
- UI組件庫(kù) tdesign
- 公司內(nèi)部業(yè)務(wù)組件庫(kù) sutpc-charts-utils
要優(yōu)化,我們首先要知道有沒(méi)有問(wèn)題旁涤,問(wèn)題自查的途徑有很多翔曲,我這里用了瀏覽器自帶的lighthouse,得到初步結(jié)果如下
不同的系統(tǒng)優(yōu)化關(guān)注點(diǎn)不一樣迫像,由于我這個(gè)系統(tǒng)是一個(gè)后臺(tái)系統(tǒng),我這里主要關(guān)注性能瞳遍,也就是圖中的Performance的得分51的那部分闻妓,再一看這幾個(gè)指標(biāo) 如 FCP\ TTI \ LCP,一看就知道不太ok了掠械,時(shí)間都4由缆、5秒了,再看看網(wǎng)絡(luò)資源加載方面:
根據(jù)經(jīng)驗(yàn)一看就會(huì)發(fā)現(xiàn)有的js\css存在體積過(guò)大猾蒂,而且都沒(méi)有g(shù)zip壓縮導(dǎo)致加載時(shí)間比較長(zhǎng)的問(wèn)題均唉,同時(shí),lighthouse也有對(duì)應(yīng)的診斷肚菠,以及對(duì)應(yīng)的改善建議
如下圖,點(diǎn)開(kāi)第一條建議蚊逢,果不其然限嫌,是讓你開(kāi)啟資源壓縮,壓縮方法有:gzip,deflate或者brotli时捌,我們用常用的gzip即可怒医,它一般壓縮率在70%左右。
然后再看看其他優(yōu)化建議奢讨,包括
- 減少未使用的JavaScript并延遲加載腳本稚叹,直到需要它們, 來(lái)減少網(wǎng)絡(luò)活動(dòng)消耗的字節(jié)數(shù)
- 資源正在阻止頁(yè)面的第一次繪制∧弥睿考慮內(nèi)聯(lián)交付關(guān)鍵JS/CSS扒袖,并推遲所有非關(guān)鍵JS/樣式
- 減少未使用的css
- 使用http2代替目前的http1.1
- 使用高效的緩存策略為靜態(tài)資產(chǎn)提供服務(wù)
- 避免昂貴的dom操作
還有一些其他小建議就不一 一列舉了
由于本系統(tǒng)的資源都在同一個(gè)域名(IP)下,且http協(xié)議是1.1版本, 所以會(huì)有最多6個(gè)TCP連接同時(shí)創(chuàng)建的限制亩码。其實(shí)最好的辦法還是上http2, 但是這又要先上https證書(shū)才行季率,考慮到這系統(tǒng)公司暫時(shí)不可能花錢(qián)搞這個(gè)證書(shū),所以http2的想法就算了描沟。
最后飒泻,根據(jù)現(xiàn)有問(wèn)題、優(yōu)化建議和實(shí)際情況吏廉,我打算做 代碼瘦身泞遗、打包時(shí)的代碼分割、gzip壓縮席覆、設(shè)置合適的緩存策略
具體操作:
1史辙、移除未使用的插件,檢查代碼發(fā)現(xiàn)有一些插件如vue3-lazy
vue3-clipboard
沒(méi)用到,刪掉
2聊倔、配置代碼分割
vite默認(rèn)node_modules的非公用依賴全給你打到一個(gè)vendor.js里面去晦毙,導(dǎo)致的問(wèn)題就是太大加載慢,所以需要分割耙蔑,方便并行加載结序。方法就是自定義打包策略,如下例子纵潦,把非源碼的依賴單獨(dú)提取出來(lái)徐鹤,再配合強(qiáng)緩存策略。
build: {
rollupOptions: {
output: {
manualChunks: {
'sutpc-charts-utils': ['sutpc-charts-utils'],
'vue-vendor': ['vue', 'vue-router', 'pinia'],
tdesign: ['tdesign-vue-next'],
}
}
}
},
看出來(lái)邀层,優(yōu)化前后主要變化是一個(gè)3366kb的chunk變成 兩個(gè), 分別是1037kb \ 2464kb , 在依賴不多的情況下返敬,優(yōu)化效果不大,至于其他的小chunk塊變化不大寥院。
3劲赠、配置gzip
讓運(yùn)維幫忙配置一下nginx,開(kāi)啟gzip
gzip on;
gzip_disable "msie6";
gzip_min_length 1024;
gzip_buffers 4 16k;
gzip_vary on;
gzip_comp_level 5;
gzip_static on;
gzip_types text/plain text/css application/json application/javascript
然后測(cè)試一下發(fā)現(xiàn)個(gè)問(wèn)題,如下圖
好家伙秸谢!資源加載更慢了凛澎!如下圖,隨便點(diǎn)開(kāi)某個(gè)請(qǐng)求一看原來(lái)是服務(wù)器響應(yīng)慢估蹄,可能是啥原因呢塑煎?
是服務(wù)端自己的問(wèn)題,仔細(xì)看了一下nginx配置找到了問(wèn)題 :gzip_comp_level 5
改一下nginx配置, 把 gzip_comp_level 5
改成 gzip_comp_level 2
臭蚁,因?yàn)閘evel越高越占用cpu資源最铁,現(xiàn)在改低應(yīng)該可以把服務(wù)響應(yīng)耗時(shí)短一點(diǎn)
gzip_comp_level 2;
看起來(lái) “請(qǐng)求-響應(yīng)” 時(shí)間確實(shí)從平均1.3s 降低到 700ms左右,約有4垮兑、50%的提升
優(yōu)化完了冷尉,重新從lighthouse測(cè)試看一下成果
從效果上來(lái)看,Performance從51 到 78分系枪,幾個(gè)相關(guān)指標(biāo)時(shí)間也進(jìn)入了2s左右雀哨,感覺(jué)效果還行。
能不能再快點(diǎn)私爷?
從上面的幾個(gè)關(guān)鍵資源加載情況來(lái)看雾棺,基本都要700ms左右,能不能再快點(diǎn)的当犯?其實(shí)是可以的垢村。因?yàn)樯厦娴膎ginx的gzip設(shè)置都是實(shí)時(shí)壓縮的割疾,就是說(shuō)每次請(qǐng)求資源嚎卫,服務(wù)器都要把該文件壓縮完再返回,這里是存在浪費(fèi)時(shí)間的,由于這些靜態(tài)資源每次打包生成之后就不會(huì)變化了拓诸,我們可以直接把它壓縮好侵佃,這樣子請(qǐng)求時(shí)直接把壓縮好的資源返回就行了,省去每次請(qǐng)求都去壓縮的時(shí)間開(kāi)銷奠支,網(wǎng)絡(luò)io就會(huì)更快馋辈!怎么做呢?裝個(gè)壓縮插件即可倍谜。
pnpm i vite-plugin-compression2 -D
vite.config.js配置
import { compression } from 'vite-plugin-compression2'
plugins: [
...其他插件
compression({
threshold: 1024,
include: [/\.css$/, /\.js$/]
})
],
上面配置對(duì)只對(duì)打包后大于1k的css迈螟、 js壓縮,發(fā)現(xiàn)會(huì)多了一份后綴名是.gz的文件尔崔,然后把dist目錄部署到服務(wù)上答毫,nginx響應(yīng)這些資源請(qǐng)求時(shí)會(huì)直接把對(duì)應(yīng).gz的文件返回。
重新部署查看網(wǎng)絡(luò)瀑布流季春,發(fā)現(xiàn)從請(qǐng)求耗時(shí)從700ms降低到100ms左右洗搂,提速明顯,但是lighthouse重新測(cè)試發(fā)現(xiàn) FCP \ LCP \ SI 指標(biāo)得分并沒(méi)有提升多少载弄,Performance總得分也還是70多耘拇,這就奇怪了,從官方的建議來(lái)看宇攻,現(xiàn)在應(yīng)該是GOOD階段范圍了
點(diǎn)擊LCP指標(biāo)下方的“查看原始追蹤記錄”按鈕惫叛,進(jìn)去查看:
從圖中可以看到LCP也就在1.2s左右的位置,哪里是lighthouse寫(xiě)的2.2s ? 不知道它是怎么算的逞刷,你知道嗎挣棕?歡迎留言討論。
4亲桥、 靜態(tài)資源設(shè)置強(qiáng)緩存洛心、協(xié)商緩存
在我另外一篇文章《徹底弄懂強(qiáng)緩存與協(xié)商緩存》說(shuō)過(guò)緩存的原理,這里直接用上結(jié)論:index.html設(shè)置協(xié)商緩存题篷,其他的設(shè)置強(qiáng)緩存词身。由于我這環(huán)境的nginx默認(rèn)是有協(xié)商緩存的,所以我只配置需要強(qiáng)緩存的資源番枚,如下法严,js|css|png|jpg 等資源強(qiáng)緩存30天,即2628000秒
location ~.*\.(js|css|png|jpg)$ {
add_header Cache-Control "max-age=2628000, private";
}
設(shè)置這些緩存只是對(duì)二次打開(kāi)頁(yè)面有用葫笼,對(duì)第一次打開(kāi)測(cè)試效果沒(méi)意義深啤。截止目前來(lái)看最大的問(wèn)題還是代碼問(wèn)題,如下最新的測(cè)試結(jié)果路星,查看優(yōu)化建議如下圖所示只剩下 3條建議
- 減少未使用的js\css
- 考慮內(nèi)聯(lián)腳本樣式
-
推遲所有非關(guān)鍵js\css
剩下建議.png
5溯街、增大代碼覆蓋率
其實(shí)要減少未使用的代碼,我們得先了解一個(gè)概念:代碼有個(gè)指標(biāo)是代碼覆蓋率;代碼覆蓋率 = 使用的部分 / 全部呈昔;代碼覆蓋率越大說(shuō)明你的代碼用到的刀刃上的越多挥等,而不是下載一大堆,只用一小部分功能堤尾。比如你引入了整個(gè)loadsh,只用到了深拷貝功能肝劲,其他沒(méi)用到的功能代碼也被打包部署,導(dǎo)致用戶請(qǐng)求資源時(shí)浪費(fèi)帶寬郭宝,浪費(fèi)時(shí)間辞槐,阻塞渲染。
view Treemap.png
代碼覆蓋率.png
根據(jù)上圖的代碼覆蓋率來(lái)看粘室,圖中底部的表格中Coverage列里面的柱子催蝗,其中紅色的部分表示是未使用的,所以我這里還是需要繼續(xù)代碼瘦身育特,把不用到的部分剔除丙号。而且大頭是前面兩個(gè)js,體積大缰冤,而未使用部分又占比大犬缨。根據(jù)上文列舉的剩下的3條優(yōu)化建議,內(nèi)聯(lián)腳本樣式不太現(xiàn)實(shí)棉浸,所以按照建議去
- 減少未使用的js\css
- 推遲所有非關(guān)鍵js\css
我的具體做法就是 把在main.ts全量引入sutpc-charts-utils這個(gè)組件庫(kù)的代碼刪掉怀薛,改成在局部頁(yè)面去按需引入具體的組件、配合defineAsyncComponent
異步組件實(shí)現(xiàn)按需加載迷郑,也就實(shí)現(xiàn)了“減少未使用的js\css枝恋、推遲所有非關(guān)鍵js\css”。
局部頁(yè)面異步方式按需引入MatrixEditor組件的例子
const MatrixEditor = defineAsyncComponent(() => import('sutpc-charts-utils/dist/matrix-editor').then(({MatrixEditor}) => MatrixEditor))
import 'sutpc-charts-utils/dist/matrix-editor/style.css';
export default defineComponent({
render(){
return <div>
<MatrixEditor />
</div>
}
})
再次打包嗡害,發(fā)現(xiàn)原來(lái)最大的chunk: sutpc-charts-utils-[hash].js沒(méi)了, 多了幾個(gè)幾百k的js焚碌,因?yàn)檫@些獨(dú)立組件本來(lái)就比較大。至于tdesign-[hash].js暫時(shí)不變霸妹,沒(méi)改按需引入十电。
最后再部署測(cè)試一次 , Performance 90+分,F(xiàn)CP \ SI \ LCP \ TTI 幾乎進(jìn)入秒級(jí)叹螟!
總結(jié)
本次優(yōu)化主要是通過(guò)移除未使用的代碼鹃骂、代碼分割、gzip壓縮設(shè)置罢绽、按需引入等手段畏线,降低了首屏資源請(qǐng)求時(shí)的“請(qǐng)求-響應(yīng)”時(shí)間,從而達(dá)到資源加載優(yōu)化的目的良价。