Web性能優(yōu)化:從 2 秒到200毫秒
前不久發(fā)布了個人筆記軟件 Nebula Note 的Web預(yù)覽版(傳送門),整體開發(fā)體驗和使用效果都很滿意。但作為Web工程師的我習(xí)慣性的打開了瀏覽器開發(fā)者工具的Network面板,主要想觀察首次加載時間。2 秒+!顯然,這個加載速度無法接受。于是便開始了一輪深入優(yōu)化,目標(biāo)是:將首頁加載時間控制在 1 秒內(nèi),真正的實現(xiàn)秒開。
性能瓶頸分析
從瀏覽器開發(fā)者工具的Network面板上可以很明顯的觀察到是首屏資源體積過大所致。項目技術(shù)棧為:
- 前端框架:
React - 服務(wù)端框架:
NodeJs、Koa - 構(gòu)建工具:
Vite - UI 組件:自研的 Nebula UI,由于功能過于簡單,所以沒有用主流的UI庫。
排除自研代碼后,問題可能出在集成的第三方組件上。使用打包分析工具檢查產(chǎn)物體積,結(jié)果如下:
react-codemirror在線代碼編輯器:體積最大toast-uiMarkdown 編輯器:第二大- 自研邏輯:占比極小
使用source-map-explorer對構(gòu)架結(jié)果進(jìn)行分析,截圖如下:

基礎(chǔ)優(yōu)化:開啟 Brotli 壓縮
當(dāng)前服務(wù)部署在 99 元云服務(wù)器 上的 Kubernetes 環(huán)境中,所有服務(wù)通過自定義模板的 Deployment 文件部署(配置傳送門),IngressRoute 中默認(rèn)啟用了Gzip 壓縮。Gzip還是有點溫柔,考慮進(jìn)一步壓榨傳輸體積,于是啟用了Brotli壓縮。構(gòu)建結(jié)果對比測試效果如下:

Brotli的實力毋庸置疑,比Gzip多壓縮了近200KB。而且這次是在打包的時候就對資源進(jìn)行了壓縮,理論上應(yīng)該能有效縮減服務(wù)器的響應(yīng)時間。但即便如此頁面加載時間仍未突破 1 秒。
深度優(yōu)化:移除冗余語言包(AST靜態(tài)裁剪)
根據(jù)打包分析結(jié)果,react-codemirror 是最大“重量級選手”。主要原因是其默認(rèn)引入了大量編程語言的語法高亮支持,而目前 Nebula Note 實際僅使用少數(shù)幾種。因此,靜態(tài)分析源碼后,通過自定義 Vite 插件在構(gòu)建階段識別未使用的語言包,然后再利用 AST(抽象語法樹)移除無關(guān)代碼,最后打包體積減少1MB+。效果是相當(dāng)?shù)恼选?yōu)化后打包體積對比圖如下:

構(gòu)建分析結(jié)果:

此輪優(yōu)化后react-codemirror 從第一名降至第二,首屏加載時間也成功擠進(jìn) 1 秒以內(nèi)。最終成果如下:

更近一步:延遲加載非首屏組件
雖然“秒開”目標(biāo)已實現(xiàn),但從打包占比來看 react-codemirror 與 toast-ui 兩大組件仍占據(jù) 近 80% 體積,并且這兩個包在第一屏中是非必需的,或只需其一。于是采用 React 的 Suspense + lazy 機(jī)制,針對這兩個組件實現(xiàn)延遲加載:
import React, { Suspense, lazy } from 'react';
import SuspenseLoading from '@client/components/suspenseLoading';
import type { Props as IProps } from './codeMirror';
const Editor = lazy(() => import('./codeMirror'));
export type Props = IProps;
const CodeEditor = (props: IProps) => {
return (
<Suspense fallback={<SuspenseLoading />}>
<Editor {...props} />
</Suspense>
);
};
export default CodeEditor;

使用Suspense后,懶加載的模塊在構(gòu)建的時候會被拆成獨立的包,這對于首屏的加載非常的友好。通過對比可以看到不僅是JS文件從262KB降到了93KB,首次加載的CSS文件更是從83.5KB降到了2.1KB。
最后
有一個很奇怪的現(xiàn)象,CSS的TTFB很不穩(wěn)定,在約40ms和100ms間反復(fù)橫跳。其他資源,尤其是Http請求相關(guān)的資源表現(xiàn)很穩(wěn)定。有知道原因的朋友,還請在評論區(qū)分享一下。最后附上博客所述內(nèi)容資源,歡迎點贊支持~??。
Nebula Note預(yù)覽版:https://note.aser1989.cn/
Nebula Note源代碼: https://github.com/ASER1989/nebula-note

浙公網(wǎng)安備 33010602011771號