網(wǎng)站優(yōu)化是我們做網(wǎng)站最重要要的一部分,而且要做的東西多,非常重視細節(jié)及流程。
從網(wǎng)站設計最初開始,就需要提前進行規(guī)劃布局,沒有好的思路,優(yōu)化很難高效的開展。本文將以實際網(wǎng)站來做參考,手把手教你如何一步步做好網(wǎng)站優(yōu)化。
這不是一篇基礎網(wǎng)站優(yōu)化文章,繼續(xù)下文前,請確定已經(jīng)做了如下基本優(yōu)化:
1.圖片壓縮、合并
2.代碼精簡、混淆
3.減少 iframe 使用,及盡量不實用
4.避免圖片 src 為空
5.減少HTTP 請求數(shù)
6.避免重定向
7.樣式表放頁頭,腳本放底部
一、優(yōu)化的意義
我們可以從兩個角度來看這個問題:
1.用戶角度
網(wǎng)站優(yōu)化能夠讓頁面加載得更快,響應更加及時,極大提升用戶體驗。
2.服務商角度
優(yōu)化會減少頁面資源請求數(shù),減小請求資源所占帶寬大小,從而節(jié)省可觀的帶寬資源。
網(wǎng)站優(yōu)化的目標是:減少網(wǎng)站加載時間,提高響應速度。
那么網(wǎng)站加載速度和用戶體驗又有著怎樣的關系呢?我們來看下面這張圖:
Google 和亞馬遜的研究表明,Google頁面加載的時間從 0.4 秒提升到 0.9 秒導致丟失了 20% 流量和廣告收入,對于亞馬遜,頁面加載時間每增加 100ms 就意味著 1% 的銷售額損失。可見,頁面的加載速度對于用戶有著至關重要的影響。
二、分析網(wǎng)站性能瓶頸
1.打包文件大小
.
├──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
需要注意:生產(chǎn)環(huán)境不要開啟 SOURCEMAP
3. 靜態(tài)資源加載時間
TTFB 全稱 Time To First Byte:是指網(wǎng)絡請求被發(fā)起到從服務器接收到第一個字節(jié)的這段時間,它包含了 TCP 連接時間、發(fā)送 HTTP 請求時間和獲得響應消息第一個字節(jié)的時間。
頁面一接口情況:
頁面二接口情況:
用戶下載內(nèi)容所需要的時間,受限于服務器的資源、資源的大小以及用戶的網(wǎng)絡速度。因此,我們暫時不討論這方面的內(nèi)容。
5.分析工具
通過 webpack 打包,分析一下大文件構成。
6.YSlow 或者 PageSpeed
我們可以通過Google PageSpeed Insights API Extension 來對網(wǎng)站整體性能做一下評估,按照建議去做一些高效優(yōu)化。
加載時間概況:
影響網(wǎng)站加載因素:
緩存策略問題:
DOM 節(jié)點:
關鍵路徑:
主線程情況:
三、通過策略解決問題
1.favicon.ico 404 問題;?
2.去除調(diào)試工具代碼:eruda,線上環(huán)境是不需要的;?
3.圖片合并或者多個 svg;?
建議使用 webpack-spritesmith,簡單使用如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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 等文件。所以我們從這幾個文件入手,逐個優(yōu)化:
l moment.js:配置 moment 忽略本地化,可減少 70kb
1 | ignoreMomentLocale: true |
l dist.js:在給單頁應用做按需加載優(yōu)化時,一般采用以下原則:
l 把整個網(wǎng)站劃分成一個個小功能,再按照每個功能的相關程度把它們分成幾類。
l 把每一類合并為一個 Chunk,按需加載對應的 Chunk。
l 對于用戶首次打開你的網(wǎng)站時需要看到的畫面所對應的功能,不要對它們做按需加載,而是放到執(zhí)行入口所在的 Chunk 中,以降低用戶能感知的網(wǎng)頁加載時間。
l 對于個別依賴大量代碼的功能點,例如依賴 Chart.js 去畫圖表、依賴 flv.js 去播放視頻的功能點,可再對其進行按需加載。
l lottie.js:分離減少 60kb
1 2 3 | externals: { lottie : 'react-lottie', } |
l lodash.js
1 2 3 4 5 6 7 | externals: { lodash : { commonjs: 'lodash', amd: 'lodash', root: '_' // indicates global variable } } |
l 動態(tài)導入以及文件拆分
1 2 3 4 | dynamicImport: { webpackChunkName: true, loadingComponent: './components/Loading/jartto.js', } |
按照上面我們一步步處理后,重新打包分析一下文件構成:
這里為什么沒有繼續(xù)拆分 dist.js ,是因為目前階段沒有好的方案,需要對代碼做很多調(diào)整,所以暫且保留。相關信息可以在 Ant-Design Issuse Svg icons make bunlde size too large 中查看解決方案。
5.存放 CDN
loading.json,大小54kb ?
svg 替換 2 倍圖 ?
刪除項目冗余圖片 ?
6.優(yōu)化 TTFB
減少 DNS 查詢
使用 CDN
提早 Flush
添加周期頭
7.移除阻塞渲染的資源
l css 預加載 preload
<link rel="preload">
l 異步加載第三方資源:
<script async src="https://cdn.jartto.wang/fastclick.js"><
沒有 async 屬性,script 將立即獲?。ㄏ螺d)并執(zhí)行,期間阻塞了瀏覽器的后續(xù)處理。如果有 async 屬性,那么script 將被異步下載并執(zhí)行,同時瀏覽器繼續(xù)后續(xù)的處理。
8.確保文本在網(wǎng)頁字體加載期間保持可見狀態(tài)
利用 font-display 這項 CSS 功能,確保文本在網(wǎng)頁字體加載期間始終對用戶可見。
1 2 3 4 5 | @font-face { font-family: 'Arvo'; font-display: auto; src:local('Arvo'),url(https://fonts.jartto.wang/fonts/temp.woff2)format('woff2'); } |
9.采用高效的緩存策略提供靜態(tài)資源
延長緩存期限可加快重訪網(wǎng)頁的速度。
DNS TTL(Time-To-Live),簡單的說它表示一條域名解析記錄在 DNS 服務器上緩存時間.
當各地的 DNS 服務器接受到解析請求時,就會向域名指定的 DNS 服務器發(fā)出解析請求從而獲得解析記錄;
在獲得這個記錄之后,記錄會在 DNS 服務器中保存一段時間,這段時間內(nèi)如果再接到這個域名的解析請求,DNS 服務器將不再向 DNS 服務器發(fā)出請求,而是直接返回剛才獲得的記錄;
而這個記錄在 DNS 服務器上保留的時間,就是 TTL 值。
所以一般更新域名解析的步驟如下:
1. 先查看域名當前的 TTL 值。
2. 修改 TTL 值為可設定的最小值,建議為 60 秒。
3. 等待一天,保證各地的 DNS 服務器緩存都過期并更新了記錄。
4. 設置修改 DNS 解析到新的記錄,這個時候各地的 DNS 就能以最快的速度更新到新的記錄。
5. 確認各地的 DNS 已經(jīng)更新完成后,再 TTL 值設置成常用的值(如: TTL=86400)。
如下圖,TTL 值設置的最佳實踐,可供參考:
10.避免 DOM 規(guī)模過大
網(wǎng)頁包含的 DOM 節(jié)點最好少于 1500 個左右。理想狀況是,樹深度少于 32 個元素,且少于 60 個子/父元素。大型 DOM 可能會增加內(nèi)存使用量、導致樣式計算用時延長并產(chǎn)生高昂的布局重排費用。
11.最大限度地縮短關鍵請求深度
關鍵請求鏈 顯示了以高優(yōu)先級加載的資源。
我們可以通過:縮短鏈長、縮減資源的下載文件大小,或者推遲下載不必要的資源,從而提高網(wǎng)頁加載速度。
當 HTML 解析過程中遇到一個 script 標記時,它會暫停 DOM 構建,將控制權移交給 JavaScript 引擎,等JavaScript 引擎運行完畢,瀏覽器再從中斷的地方恢復 DOM 構建。
也就是說,執(zhí)行內(nèi)聯(lián)的 JavaScript 會阻塞頁面的首次渲染。
在關鍵渲染路徑中,我們通常要關注三個點:
1. 頁面首次渲染需要的關鍵資源數(shù)量
2. 關鍵資源的大小
3. 關鍵渲染路徑的往返次數(shù)(Roundtrip)
我們的策略也非常簡單,就是減少關鍵資源數(shù)量,降低資源大小,減少關鍵路徑的往返次數(shù)。
優(yōu)化關鍵渲染路徑的常規(guī)步驟如下:
a. 對關鍵路徑進行分析和特性描述:資源數(shù)、字節(jié)數(shù)、長度。
b. 最大限度減少關鍵資源的數(shù)量:刪除它們,延遲它們的下載,將它們標記為異步等。
c. 優(yōu)化關鍵字節(jié)數(shù)以縮短下載時間(往返次數(shù))。
d. 優(yōu)化其余關鍵資源的加載順序:您需要盡早下載所有關鍵資源,以縮短關鍵路徑長度。
更多詳情,請參考前端性能優(yōu)化—關鍵渲染路徑。
12.最大限度地減少主線程工作
考慮減少為解析、編譯和執(zhí)行 JS 而花費的時間。我們可以提供較小的 JS 負載來實現(xiàn)此目標。
13.最優(yōu)配置 nginx
a. gzip 配置
gzip on;
gzip_min_length 1k;
gzip_buffers 4 8k;
gzip_http_version 1.1;
gzip_comp_level 4;
gzip_types text/plain text/css application/json image/png image/x-icon application/javascript application/x-javascript text/javascript text/xml application/xml application/xml+rss text/cache-manifest application/octet-stream;
gzip_vary on;
b. nginx 開啟緩存
如果你對瀏覽器緩存還不太清楚,歡迎移步聊一聊瀏覽器緩存機制。
location ~.*\.(html|htm|js|css|gif|jpg|jpeg|png|bmp|swf|ico|json|otf)$ {
root /var/www/jartto_web/;
index index.html;
expires 1d;
}
Nginx 能非常有效地直接處理靜態(tài)內(nèi)容。在靜態(tài)文件和 Nginx 在同一主機的情況下,這種特性尤為有用。
四、效果如何?
優(yōu)化前:網(wǎng)站評分 27 ,首次內(nèi)容繪制 6.9 秒
1.網(wǎng)站評分
當然,優(yōu)化還可以做更多,我們盡量讓網(wǎng)站的評分接近 100 分,譬如:
1.網(wǎng)站評分
2.加載概況:
五、總結
我們整體把網(wǎng)站優(yōu)化下來,做了不少代碼改動,也達到了不錯的效果。但是有幾點還是需要注意:
1.盡可能減少白屏出現(xiàn)時間
骨架圖解決 webview 加載頁面過長的白屏過程。
2.關注整站性能,如 TTFB
服務端接口也需要同步優(yōu)化,而不要僅僅依賴前端單方面優(yōu)化。
3.按照使用情況加載優(yōu)先使用的資源
l css 預加載
l font 預加載
l js 預加載
l 圖片預加載
4.請高效利用 DNS 和 CDN
l 增加緩存時間
l DNS 預解析
網(wǎng)站優(yōu)化從來不是一蹴而就,需要不斷的去優(yōu)化細節(jié),不斷的摸索嘗試。從我的角度來看,網(wǎng)站優(yōu)化更像是在網(wǎng)站性能和加載速度之間找到一個平衡點。譬如,文中我們?yōu)榱藘?yōu)化文件打包大小,進行了大文件拆分。隨之而來的問題就是拆分后的文件可能還會對某些文件有關聯(lián),那么就影響到了關鍵渲染路徑。
所以,優(yōu)化不存在什么通天捷徑,需要不斷的去嘗試,去找到這個最佳優(yōu)化點,這才是根本。
希望這篇文章在您SEO的學習道路上能起到幫助,如需更多網(wǎng)站SEO解決方案請聯(lián)系風享互聯(lián)咨詢了解。