網站優化實戰
網站優化是前端開發的重中之重,但是優化細節卻十分繁雜。沒有好的思路,優化很難高效的開展。本文將以實際網站來做參考,手把手教你如何一步步做好網站優化。
這不是一篇 基礎網站優化
文章,再繼續下文前前,請確定已經做了:
1.圖片壓縮、合併
2.程式碼精簡、混淆
3.減少 iframe 使用
4.避免圖片 src 為空
5.減少 HTTP 請求數
6.避免重定向
7.樣式表放頁頭,指令碼放底部
…
一、優化的意義
我們可以從兩個角度來看這個問題:
1.使用者角度
網站優化能夠讓頁面載入得更快,響應更加及時,極大提升使用者體驗。
2.服務商角度
優化會減少頁面資源請求數,減小請求資源所佔頻寬大小,從而節省可觀的頻寬資源。
網站優化的目標是:減少網站載入時間,提高響應速度。
那麼網站載入速度和使用者體驗又有著怎樣的關係呢?我們來看下面這張圖:

二、分析網站效能瓶頸
1.打包檔案大小

2.打包檔案目錄

. ├── favicon.ico ├── index.html ├── manifest.json ├── static │├── DIN-Medium.1bbe3460.otf │├── DIN-Regular.799221d7.otf │└── logo.c57d38d0.png ├── umi.css ├── umi.css.map ├── umi.js └── umi.js.map
需要注意:生產環境不要開啟 SOURCEMAP
3.靜態資源載入時間

4.waterfall

TTFB
全稱 Time To First Byte
:是指網路請求被髮起到從伺服器接收到第一個位元組的這段時間,它包含了 TCP
連線時間、傳送 HTTP
請求時間和獲得響應訊息第一個位元組的時間。
Content Download:即下載內容所需要的時間。
頁面一介面情況:

頁面二介面情況:

使用者下載內容所需要的時間,受限於伺服器的資源、資源的大小以及使用者的網路速度。因此,我們暫時不討論這方面的內容。
5.分析工具
通過 webpack
打包,分析一下大檔案構成。

6. YSlow
或者 PageSpeed
我們可以通過 Google PageSpeed Insights API Extension 來對網站整體效能做一下評估,按照建議去做一些高效優化。
載入時間概況:

影響網站載入因素:

快取策略問題:

DOM
節點:

關鍵路徑:

主執行緒情況:

三、通過策略解決問題
1. favicon.ico
404 問題;√
2.去除除錯工具程式碼: eruda
,線上環境是不需要的;√
3.圖片合併或者多個 svg
;√
建議使用 webpack-spritesmith
,簡單使用如下:
plugins: [ new SpritesmithPlugin({ src: { cwd: path.resolve(__dirname, 'src/ico'), glob: '*.png' }, target: { image: path.resolve(__dirname, 'src/spritesmith-generated/jartto.png'), css: path.resolve(__dirname, 'src/spritesmith-generated/jartto.styl') }, apiOptions: { cssImageRef: "~jartto.png" } }) ]
4.大檔案拆分 √

從上圖分析得出,大檔案主要包含: dist.js
, lottie.js
, lodash.js
, loading.json
等檔案。所以我們從這幾個檔案入手,逐個優化:
-
moment.js
:配置moment
忽略本地化,可減少70kb
ignoreMomentLocale: true
-
dist.js
:在給單頁應用做按需載入優化時,一般採用以下原則:
- 把整個網站劃分成一個個小功能,再按照每個功能的相關程度把它們分成幾類。
- 把每一類合併為一個
Chunk
,按需載入對應的Chunk
。 - 對於使用者首次開啟你的網站時需要看到的畫面所對應的功能,不要對它們做按需載入,而是放到執行入口所在的
Chunk
中,以降低使用者能感知的網頁載入時間。 - 對於個別依賴大量程式碼的功能點,例如依賴
Chart.js
去畫圖表、依賴flv.js
去播放視訊的功能點,可再對其進行按需載入。
-
lottie.js
:分離減少60kb
externals: { lottie : 'react-lottie', }
-
lodash.js
externals: { lodash : { commonjs: 'lodash', amd: 'lodash', root: '_' // indicates global variable } }
-
動態匯入以及檔案拆分
dynamicImport: { webpackChunkName: true, loadingComponent: './components/Loading/jartto.js', }
按照上面我們一步步處理後,重新打包分析一下檔案構成:

這裡為什麼沒有繼續拆分 dist.js
,是因為目前階段沒有好的方案,需要對程式碼做很多調整,所以暫且保留。相關資訊可以在 Ant-Design Issuse
Svg icons make bunlde size too large 中檢視解決方案。
5.存放 CDN
loading.json svg
6.優化 TTFB
DNS CDN Flush
7.移除阻塞渲染的資源
-
css
預載入preload
<link rel="preload">
-
非同步載入第三方資源:
<script async src="https://cdn.jartto.wang/fastclick.js"></script>
沒有 async
屬性, script
將立即獲取(下載)並執行,期間阻塞了瀏覽器的後續處理。如果有 async
屬性,那麼 script
將被非同步下載並執行,同時瀏覽器繼續後續的處理。
8.確保文字在網頁字型載入期間保持可見狀態
利用 font-display
這項 CSS
功能,確保文字在網頁字型載入期間始終對使用者可見。
@font-face { font-family: 'Arvo'; font-display: auto; src:local('Arvo'),url(https://fonts.jartto.wang/fonts/temp.woff2)format('woff2'); }
9.採用高效的快取策略提供靜態資源
延長快取期限可加快重訪網頁的速度。
DNS TTL(Time-To-Live)
,簡單的說它表示一條域名解析記錄在 DNS
伺服器上快取時間.
當各地的 DNS
伺服器接受到解析請求時,就會向域名指定的 DNS
伺服器發出解析請求從而獲得解析記錄;
在獲得這個記錄之後,記錄會在 DNS
伺服器中儲存一段時間,這段時間內如果再接到這個域名的解析請求, DNS
伺服器將不再向 DNS
伺服器發出請求,而是直接返回剛才獲得的記錄;
而這個記錄在 DNS
伺服器上保留的時間,就是 TTL
值。
所以一般更新域名解析的步驟如下:
- 先檢視域名當前的
TTL
值。 - 修改
TTL
值為可設定的最小值,建議為 60 秒。 - 等待一天,保證各地的
DNS
伺服器快取都過期並更新了記錄。 - 設定修改
DNS
解析到新的記錄,這個時候各地的DNS
就能以最快的速度更新到新的記錄。 - 確認各地的
DNS
已經更新完成後,再TTL
值設定成常用的值(如:TTL=86400
)。
後文我們會詳細介紹 DNS
相關內容,歡迎各位童鞋關注。
10.避免 DOM
規模過大
網頁包含的 DOM
節點最好少於 1500
個左右。理想狀況是,樹深度少於 32
個元素,且少於 60
個子/父元素。大型 DOM
可能會增加記憶體使用量、導致樣式計算用時延長併產生高昂的佈局重排費用。
11.最大限度地縮短關鍵請求深度
關鍵請求鏈顯示了以高優先順序載入的資源。考慮縮短鏈長、縮減資源的下載檔案大小,或者推遲下載不必要的資源,從而提高網頁載入速度。
12.最大限度地減少主執行緒工作
考慮減少為解析、編譯和執行 JS
而花費的時間。我們可以提供較小的 JS
負載來實現此目標。
四、效果如何?
優化前
1.網站評分

2.載入概況:

優化後
2.載入概況:

五、總結
我們從頭優化下來,做了不少程式碼改動,也達到了不錯的效果。但是有幾點還是需要注意:
1.儘可能減少白屏出現時間
骨架圖解決 webview
載入頁面過長的白屏過程。
2.關注整站效能,如 TTFB
服務端介面也需要同步優化,而不要僅僅依賴前端單方面優化。
3.按照使用情況載入優先使用的資源
- css 預載入
- font 預載入
- js 預載入
- 圖片懶載入
4.請高效利用 DNS
和 CDN
- 增加快取時間
- DNS 預解析
網站優化從來不是一蹴而就,需要不斷的去優化細節,不斷的摸索嘗試。