400% 的飛躍-web 頁(yè)面加載速度優(yōu)化實(shí)戰(zhàn)
前言
一個(gè)網(wǎng)站的加載速度有多重要? 反正我相信之前來(lái)博主網(wǎng)站的人至少有 50% 在加載完成前關(guān)閉了本站。 為啥捏? 看圖
首頁(yè)完整加載時(shí)間 8.18s,看來(lái)能進(jìn)來(lái)看博主網(wǎng)站的人都是真愛呀,哈哈。 正常來(lái)講一個(gè)網(wǎng)頁(yè) 4s 加載不完就會(huì)流失很大一部分用戶,而博主的網(wǎng)站加載時(shí)間竟然達(dá)到了 8s 還是在電腦端,如果在移動(dòng)端,加載時(shí)間會(huì)更久,體驗(yàn)會(huì)更差。 這樣的話網(wǎng)站做得再難看批判者進(jìn)不來(lái)不是白搭嘛,于是針對(duì) web 頁(yè)面加載速度的優(yōu)化迫在眉睫。
基于博主以前優(yōu)化過(guò)其他網(wǎng)站,于是博主準(zhǔn)備把這次的優(yōu)化過(guò)程記錄下來(lái)分享給大家借鑒。
1. 頁(yè)面分析
先來(lái)看優(yōu)化前的頁(yè)面:
加載時(shí)間 8.18s ,一共 33 個(gè) 請(qǐng)求,加載 1.38MB 。 可以看到對(duì)于網(wǎng)速較慢的瀏覽者光加載資源就需要 5s 以上,再加上 33 個(gè)請(qǐng)求切換開銷,簡(jiǎn)直不能愉快的玩耍。 所以接下來(lái)的優(yōu)化手段就要從加載流量和請(qǐng)求數(shù)量入手:
2. 優(yōu)化圖片
圖片在網(wǎng)絡(luò)流量中占有很大的比重,因此優(yōu)化圖片對(duì)于減少流量有著至關(guān)重要的作用。
合并小圖片:
很多頁(yè)面有很多小圖標(biāo),一個(gè)一個(gè)加載就相當(dāng)于一個(gè)一個(gè)請(qǐng)求,將這些小圖片合并成一個(gè)大圖片,用css 控制顯示范圍,這樣就只需要一個(gè)請(qǐng)求即可加載完所有小圖片,瞬間就會(huì)減少很多網(wǎng)絡(luò)請(qǐng)求。
優(yōu)化圖片格式:
很多圖片沒有經(jīng)過(guò)優(yōu)化直接上傳到網(wǎng)頁(yè)中會(huì)占用很多額外的流量,比如一張屏幕大小的截圖,用截圖工具直接截圖后的大小大概有 1MB ,此時(shí)直接上傳到網(wǎng)頁(yè)中就直接占用了 1MB 流量,但其實(shí)我們完全可以只犧牲它 40% 的質(zhì)量換取縮小 10 倍的大小,網(wǎng)上有很多轉(zhuǎn)化 web 圖片的網(wǎng)站,當(dāng)然如果你有 photoshop 的話完全可以自己導(dǎo)出:
將圖片在 ps 中打開,然后點(diǎn)擊菜單欄 “文件” 菜單,選擇 “儲(chǔ)存為 web 所用格式”,出現(xiàn)如下對(duì)話框:
一般情況下 jpg 圖片選擇品質(zhì)中即可,png 格式圖片選擇 png8 即可,但注意有透明背景的 png 圖片要選擇 png24 ,否則透明背景中會(huì)出現(xiàn)白邊,gif 圖片選擇 gif64 無(wú)仿色即可。
一般經(jīng)過(guò)優(yōu)化的圖片大小至少會(huì)有 3倍 之差,圖片原大小越大優(yōu)化的結(jié)果會(huì)越好。
博主的網(wǎng)站最顯眼的圖片就是頁(yè)眉上那個(gè)幽鬼的圖片啦,所以就先拿它開刀,經(jīng)過(guò)以上步驟優(yōu)化:
瞬間減小 4 倍,實(shí)際效果可以看看,代表著博主門面的圖片經(jīng)過(guò)優(yōu)化后和優(yōu)化前顯示效果并沒有明顯區(qū)別,而文件大小卻相差了 4 倍。
3. 使用免費(fèi) cdn 加載第三方資源
所有網(wǎng)站都會(huì)用到第三方資源,對(duì)于第三方資源,如果選擇讓自己的服務(wù)器提供,那么對(duì)于小型站點(diǎn),本就不大的帶寬相當(dāng)一部分還要被公共資源占用,無(wú)形之中壓縮了服務(wù)器帶寬,如果把這部分資源讓第三方 cdn 提供,那么對(duì)于網(wǎng)站加載速度會(huì)有不小的提升。
博主選用的是 bootstrap 中文站提供的 cdn 靜態(tài)庫(kù),博主看過(guò)不少國(guó)內(nèi) cdn 靜態(tài)庫(kù),可以說(shuō) bootstrap 家的還是很良心的,更新及時(shí),資源現(xiàn)在也很豐富,基本博主用的三方資源都能在上面找到,于是接下來(lái)就是搜索靜態(tài)資源 + 替換靜態(tài)資源:
- <script src="/s/js/jquery.min.js"></script>
改為
- <script src="//cdn.bootcss.com/jquery/3.1.1/jquery.min.js"></script>
這里不要寫協(xié)議頭,讓網(wǎng)頁(yè)自動(dòng)判斷使用 http 還是 https ( 關(guān)于 https 網(wǎng)站的部署可以看博主之前的文章: 給你的網(wǎng)站穿上外衣- HTTPS 免費(fèi)部署指南 )
4. 使用 cdn 儲(chǔ)存靜態(tài)資源
一般網(wǎng)站 90% 的流量都用于靜態(tài)資源的加載,除了用免費(fèi) cdn 加載第三方資源,還可以自己申請(qǐng)?jiān)瓶臻g儲(chǔ)存自己的靜態(tài)資源,進(jìn)一步減小服務(wù)器的開銷,讓服務(wù)器只專注于提供數(shù)據(jù)或者網(wǎng)頁(yè)渲染服務(wù)。 比如博主使用的是 X牛 ,將自己的圖片什么都存在 x牛上,每個(gè)月都有免費(fèi)流量,對(duì)于個(gè)人網(wǎng)站來(lái)說(shuō)應(yīng)該夠用。
5. 合并壓縮 js css
除去引用公共庫(kù),網(wǎng)頁(yè)中還有許多自己寫的 js 與 css,如果我們直接把開發(fā)環(huán)境的文件拿來(lái)用無(wú)疑很浪費(fèi)流量,因此在編寫好網(wǎng)頁(yè)測(cè)試完畢后,我們應(yīng)該將 css 和 js 壓縮合并成一個(gè)或者幾個(gè)文件,這樣既減少了請(qǐng)求次數(shù)又減少了流量消耗,一箭雙雕。 當(dāng)然還有 html 壓縮,不過(guò) ms 現(xiàn)階段還有一些坑,就先不用了。 說(shuō)到合并壓縮,***時(shí)間播追就想到了 webpack ,前端工程化神器,簡(jiǎn)單配置一下就可以完全搞定任務(wù):
博主網(wǎng)站自己的 js 工程文件放在 /webroot/static/src/js/ 中,假如我們要將壓縮合并后的文件放在 /webroot/static/dist/js/中:
在 /webroot/ 下新建文件夾 webpack, 進(jìn)入文件夾,新建文件 package.json:
- {
- "name": "RaPo3",
- "version": "1.0.0",
- "description": "",
- "main": "index.js",
- "scripts": {
- "test": "echo \"Error: no test specified\" && exit 1"
- },
- "author": "rapospectre",
- "license": "ISC",
- "devDependencies": {
- "css-loader": "^0.24.0",
- "style-loader": "^0.13.1",
- "webpack": "^1.13.2",
- "webpack-dev-server": "^1.15.1"
- }
- }
保存后執(zhí)行:
- npm install
- //或
- cnpm install
- //如果你有的話
然后新建 webpack 配置文件 webpack.config.js:
- var webpack = require('webpack');
- module.exports = {
- entry: {
- base: ['../static/js/src/http.js', '../static/js/stickUp.min.js', '../static/js/src/base.js'],
- index: ['../static/js/src/index.js'],
- detail: ['../static/js/editormd.js', '../static/js/src/article.js'],
- know: ['../static/js/editormd.js', '../static/js/src/know.js'],
- list: ['../static/js/src/list.js']
- },
- output: {
- path: '../static/js/dist/',
- filename: '[name].js'
- },
- plugins: [
- new webpack.optimize.UglifyJsPlugin({
- output: {
- comments: false
- },
- compress: {
- warnings: true
- }
- }),
- ]
- }
這里要注意的是如果你的 js 文件間的引用是傳統(tǒng)的 html 引入后引用那么在這里合并時(shí)記得把你被引用的方法對(duì)象等等設(shè)置為全局,比如 b.js 要引用 a.js 中的函數(shù) c,合并前要在 a.js 中加上( 當(dāng)然如果你一直用 es6/node 寫 js 就不用看這里了 ):
- window.c = c;
- 或
- this.c = c;
不然 c 就會(huì)被當(dāng)作局部函數(shù)封裝起來(lái)。
改完后運(yùn)行 webpack 提示成功后看到 dist 目錄里已經(jīng)輸出了合并壓縮好的文件,之前 12kb 的文件經(jīng)過(guò)壓縮合并后只有 6kb 大小,然后我們將其替換到網(wǎng)頁(yè)中即可。
6. 代碼優(yōu)化
頁(yè)面代碼的優(yōu)化對(duì)于頁(yè)面加載速度也有不小的影響,最廣為人知的:
HTML頭部的JavaScript和寫在HTML標(biāo)簽中的Style會(huì)阻塞頁(yè)面的渲染,因此CSS放在頁(yè)面頭部并使用Link方式引入,JavaScript的引入放在頁(yè)面尾
其次還有:
- 按需加載,把統(tǒng)計(jì)、分享等 js 在頁(yè)面 onload 后再進(jìn)行加載,可以提高訪問(wèn)速度;
- 優(yōu)化 cookie ,減少 cookie 體積;
- 避免 <img> 的 src 為空;
- 盡量避免設(shè)置圖片大小,多次重設(shè)圖片大小會(huì)引發(fā)圖片的多次重繪,影響性能;
- 合理使用display屬性:
- a.display:inline后不應(yīng)該再使用width、height、margin、padding以及float
- b.display:inline-block后不應(yīng)該再使用float
- c.display:block后不應(yīng)該再使用vertical-align
- d.display:table-*后不應(yīng)該再使用margin或者float
- 不濫用Float 和 web 字體;
- 盡量使用CSS3動(dòng)畫;
- 使用 ajax 異步加載部分請(qǐng)求;
7. HTTP2 與 gzip
HTTP2 是以 SPDY 為基礎(chǔ)開發(fā)的。 SPDY 系列協(xié)議由谷歌開發(fā),于 2009 年公開。它的設(shè)計(jì)目標(biāo)就是降低 50% 的頁(yè)面加載時(shí)間,所以 HTTP2 在很大程度也是為了優(yōu)化頁(yè)面加載時(shí)間,同時(shí) HTTP2 支持多路復(fù)用,簡(jiǎn)單說(shuō)就是所有的請(qǐng)求都通過(guò)一個(gè) TCP 連接并發(fā)完成。 而 gzip 大家都不陌生,就是一種壓縮網(wǎng)頁(yè)的技術(shù),當(dāng)然壓縮網(wǎng)頁(yè)進(jìn)行傳輸?shù)拇鷥r(jià)就是給服務(wù)器增加一些壓縮的負(fù)擔(dān),當(dāng)然這種犧牲是值得的。
如何開啟 HTTP2 與 gzip? 博主的網(wǎng)站基于 nginx + uWSGI 進(jìn)行服務(wù),因此只要在 nginx 開啟 HTTP2 與 gzip 就好:
開啟 HTTP2
nginx 1.9.5 之后才支持 HTTP2 ,而且需要配置編譯參數(shù),關(guān)于 nginx 開啟 HTTP2 請(qǐng)直接移步博主之前的文章: nginx 配置 http2
開啟 gzip
直接打開 nginx 配置文件, 比如博主的在 /etc/nginx/nginx.conf, 然后加上:
- server{
- gzip on;
- gzip_comp_level 6;
- gzip_proxied any;
- gzip_types text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript application/x-font-woff;
- }
然后重啟 nginx 即可
***,讓我們清除緩存,再次打開網(wǎng)站:
總加載流量 527kb ,頁(yè)面完成加載時(shí)間 1.84s,對(duì)比之前加載時(shí)間 8.18s ,1.38MB 流量,整體時(shí)間提升了 4 倍多!用手機(jī)端訪問(wèn)測(cè)試,簡(jiǎn)直快的飛起,不信你也來(lái)[訪問(wèn)]1試試呀~
***,附上本文網(wǎng)站的源碼以及目錄結(jié)構(gòu),可以通過(guò) commit 記錄更加直觀的看到優(yōu)化的過(guò)程: