首屏優(yōu)化方案
1、JavaScript外聯(lián)文件引用放在html文檔底部;CSS外聯(lián)文件引用在html文檔頭部,位于head內(nèi);對首屏頁面用到的 css內(nèi)容,可以style 的形式寫在首頁
2、首屏不需要展示的較大尺寸圖片,請使用lazyload;
3、避免404錯誤:盡量減少外聯(lián)js;
4、減少cookies的大?。罕M量減少cookies的體積對減少用戶獲得響應(yīng)的時間十分重要;
5、減少DOM Elements的數(shù)量;
6、Webpack開啟gzip壓縮
7、服務(wù)端渲染SSR
8、Skeleton Screen (骨架屏)
9、路由懶加載
10、圖片懶加載(vue-lazyload)
11、Promise優(yōu)化
12、減少http請求
13、精靈圖可以大大地減少CSS背景圖片的HTTP請求次數(shù);
14、壓縮圖片
15、CDN優(yōu)化
16、少用location.reload()
17、正確使用display的屬性
18、采用按需加載
19、壓縮圖片優(yōu)化
20、合理使用緩存
21、預(yù)加載
幾種常見web頁面渲染方式對比
FP: ”首次繪制“(First Paint)不包括默認(rèn)背景繪制(例如瀏覽器默認(rèn)的白色背景),但是包含非默認(rèn)的背景繪制,與iframe。
FCP:”首次內(nèi)容繪制“(First Contentful Paint)包含文本,圖片(包含背景圖),非白色canvas與SVG。
iframe:父級瀏覽上下文不應(yīng)該知道子瀏覽上下文的繪制事件,反之亦然。這就意味著如果一個瀏覽上下文只包含一個iframe,那么將只有“首次繪制”,但沒有“首次內(nèi)容繪制”。
1.CSR(客戶端渲染)
1.最近幾年流行的SPA,web app都是CSR模式,頁面只有一個空div
2.優(yōu)點:
(1)不依賴數(shù)據(jù)
(2)FP時間最塊;就是留了一個div掛載組件嘛
(3)客戶端用戶體驗好
(4)內(nèi)存數(shù)據(jù)共享
3.缺點:
(1)SEO不友好
(2)FCP(首次有內(nèi)容的渲染)、FMP( 首次有意義的繪制)慢;要各種發(fā)請求;
2.預(yù)渲染
使用puppeteer或者 rize.js 提前渲染一遍,另存起來;這種方式太傻了,就不詳細(xì)介紹了;具體可以看他們的官方文檔;
3.SSR和同構(gòu)(服務(wù)端渲染)
1.服務(wù)端渲染,服務(wù)器把內(nèi)容全都拼好直接輸出,服務(wù)端用一套模板引擎
2.服務(wù)器和客戶端使用一套代碼就是同構(gòu)
3.優(yōu)點:
(1)SEO友好
(2)首屏性能高,F(xiàn)MP比CSR和預(yù)渲染都要快
4.缺點:
(1)客戶端數(shù)據(jù)共享成本高
(2)模板維護(hù)成本高
4.最優(yōu)的渲染方式
1.SSR和CSR共存的模式,發(fā)揮兩者的優(yōu)勢
(1)刷新頁面是SSR渲染,nodejs配合bigpipe
(2)站內(nèi)點擊是CSR,不用vue router、react router等等,直接用原生的a鏈接
Skeleton Screen (骨架屏)
簡單來說,骨架屏就是在頁面內(nèi)容未加載完成的時候,先使用一些圖形進(jìn)行占位,待內(nèi)容加載完成之后再把它替換掉。體驗的效果就是,在頁面完全渲染完成之前,用戶會看到一個樣式簡單,描繪了當(dāng)前頁面的大致框架,能夠感知到頁面正在逐步加載,最終骨架屏中各個占位部分被完全替換。
Vue-Router路由懶加載(利用Webpack的代碼切割)
把不同路由對應(yīng)的組件分割為不同的代碼塊,當(dāng)路由被訪問的時候,再加載對應(yīng)的組件,對中大型項目來說,會顯得很高效,對開發(fā)者而言,也方便維護(hù)。不過這里要對生產(chǎn)環(huán)境和開發(fā)環(huán)境做區(qū)分,因為如果項目很大的話,每次更改代碼觸發(fā)的熱更新時間都會很長,所以只在生產(chǎn)環(huán)境中使用路由懶加載。
// 生產(chǎn)環(huán)境 _import_production.js
module.exports = file => () => import('@/pages/' + file + '.vue');
// 開發(fā)環(huán)境 _import_development.js
module.exports = file => require('@/pages/' + file + '.vue').default; // vue-loader at least v13.0.0+
// router.js中引用
const _import = require('./_import_' + process.env.NODE_ENV);
{
path: 'course',
component: _import('course/index'),
name: 'course'
}
復(fù)制代碼
圖片懶加載(vue-lazyload)
在圖片沒有進(jìn)入可視區(qū)域時先不給img的src賦值,優(yōu)先加載可視區(qū)域的內(nèi)容,其他部分等進(jìn)入了可視區(qū)域再加載,從而提高性能
// 安裝
npm install vue-lazyload --save-dev
// 使用 main.js
import Vue from 'vue'
import App from './App.vue'
import VueLazyload from 'vue-lazyload'
Vue.use(VueLazyload)
Vue.use(VueLazyload, {
preLoad: 1.8,
error: require('@/assets/lazy/error.png'),
loading: require('@/assets/lazy/loading.png'),
attempt: 1,
listenEvents: ['scroll']
});
new Vue({
el: 'body',
components: {
App
}
});
// 在使用圖片的地方加上v-lazy即可
<img v-lazy="img.src" >
復(fù)制代碼
更多使用方式可參考vue-lazyload 這里呈現(xiàn)的效果就是,請求完成數(shù)據(jù),再去請求阿里云存放的圖片,這個階段中,圖片資源加載過程中,顯示loading的狀態(tài),加載完畢,顯示圖片,如果圖片加載失敗,顯示失敗的圖片。
Promise
課程首頁的請求數(shù)為8,請求都為異步請求,而我們的瀏覽器對同一域下的請求數(shù)量是有限制的,超過限制數(shù)目的請求會被阻塞,以谷歌瀏覽器的6個并發(fā)請求量為例,課程首頁的數(shù)據(jù)請求和圖片請求加起來成百上千個,上面,我們對圖片請求已經(jīng)做了處理,使用懶加載的方式,另外,放在和數(shù)據(jù)請求不同的域下,我們需要考慮的就是數(shù)據(jù)請求,采用了promise的方式,如下:
return new Promise((resolve,reject) => {
})
采用這種方式的另一個原因是,如果所有異步請求同時觸發(fā)的話,瀏覽器會為他們分配執(zhí)行的優(yōu)先級,而采用這種方式,請求的順序會按照我們調(diào)用的順序執(zhí)行。而瀏覽器分配的話,可能頁面底部的請求會先執(zhí)行。在請求較少的情況下,這種差異是體現(xiàn)的不明顯。
提到promise,我覺得最大的好處就是如它設(shè)計的初衷那樣,解決了層層回調(diào)的問題(難以維護(hù),且不優(yōu)雅)--鏈?zhǔn)秸{(diào)用,還有Promise.all()的用法,對于組合數(shù)據(jù)很方便。
減少http請求
網(wǎng)頁中的的圖片、form、flash等等元素都會發(fā)出HTTP請求,盡可能的減少頁面中非必要的元素,可以減少HTTP請求的次數(shù)。
CSS Sprites ——精靈(雪碧)圖
圖片是增加HTTP請求的最大可能者;把全站的圖標(biāo)都放在一個圖像文件中,然后用CSS的background-image和background-position屬性定位來顯示其中的一小部分。
壓縮圖片
圖片是最占流量的資源,因此盡量避免使用它,使用時選擇最合適的格式(實現(xiàn)需求的前提下,以大小判斷),合適的大小,然后使用智圖壓縮,同時在代碼中用Srcset來按需顯示。
PS:過度壓縮圖片大小影響圖片顯示效果
a) 使用智圖( http://zhitu.tencent.com/ )
b) 使用其它方式代替圖片(1. 使用CSS3 2. 使用SVG 3. 使用IconFont)
c) 使用Srcset
d) 選擇合適的圖片(1. webP優(yōu)于JPG 2. PNG8優(yōu)于GIF)
e) 選擇合適的大?。?. 首次加載不大于1014KB 2. 不寬于640(基于手機(jī)屏幕一般寬度))
CDN內(nèi)容分發(fā)網(wǎng)絡(luò)
CDN優(yōu)化原理
用戶在通過瀏覽器訪問未使用CDN加速的網(wǎng)站的大致過程如下:

- 用戶在瀏覽器中輸入要訪問的域名。
- 瀏覽器向DNS服務(wù)器請求對該域名的解析。
- DNS服務(wù)器返回該域名的IP地址給瀏覽器。
- 瀏覽器使用該IP地址向服務(wù)器請求內(nèi)容。
- 服務(wù)器將用戶請求的內(nèi)容返回給瀏覽器。
如果使用了CDN,則其過程會變成以下這樣

- 用戶在瀏覽器中輸入要訪問的域名。
- 瀏覽器向DNS服務(wù)器請求對域名進(jìn)行解析。由于CDN對域名解析進(jìn)行了調(diào)整,DNS服務(wù)器會最終將域名的解析權(quán)交給CNAME指向的CDN專用DNS服務(wù)器。
- CDN的DNS服務(wù)器將CDN的負(fù)載均衡設(shè)備IP地址返回給用戶。
- 用戶向CDN的負(fù)載均衡設(shè)備發(fā)起內(nèi)容URL訪問請求。
- CDN負(fù)載均衡設(shè)備會為用戶選擇一臺合適的緩存服務(wù)器提供服務(wù)。
選擇的依據(jù)包括:
根據(jù)用戶IP地址,判斷哪一臺服務(wù)器距離用戶最近;
根據(jù)用戶所請求的URL中攜帶的內(nèi)容名稱,判斷哪一臺服務(wù)器上有用戶所需內(nèi)容;
查詢各個服務(wù)器的負(fù)載情況,判斷哪一臺服務(wù)器的負(fù)載較小。
基于以上這些依據(jù)的綜合分析之后,負(fù)載均衡設(shè)置會把緩存服務(wù)器的IP地址返回給用戶。 - 用戶向緩存服務(wù)器發(fā)出請求。
- 緩存服務(wù)器響應(yīng)用戶請求,將用戶所需內(nèi)容傳送到用戶。
如果這臺緩存服務(wù)器上并沒有用戶想要的內(nèi)容,而負(fù)載均衡設(shè)備依然將它分配給了用戶,那么這臺服務(wù)器就要向它的上一級緩存服務(wù)器請求內(nèi)容,直至追溯到網(wǎng)站的源服務(wù)器將內(nèi)容拉取到本地。
CDN優(yōu)化總結(jié)
在網(wǎng)站和用戶之間引入CDN之后,用戶不會有任何與原來不同的感覺。
使用CDN服務(wù)的網(wǎng)站,只需將其域名的解析權(quán)交給CDN的負(fù)載均衡設(shè)備,CDN負(fù)載均衡設(shè)備將為用戶選擇一臺合適的緩存服務(wù)器,用戶通過訪問這臺緩存服務(wù)器來獲取自己所需的數(shù)據(jù)。
由于緩存服務(wù)器部署在網(wǎng)絡(luò)運(yùn)營商的機(jī)房,而這些運(yùn)營商又是用戶的網(wǎng)絡(luò)服務(wù)提供商,因此用戶可以以最短的路徑,最快的速度對網(wǎng)站進(jìn)行訪問。因此,CDN可以加速用戶訪問速度,減少源站中心負(fù)載壓力。
少用location.reload()
使用location.reload() 會刷新頁面,刷新頁面時頁面所有資源(css,js,img等)會重新請求服務(wù)器;建議使用location.href=“當(dāng)前頁url” 代替location.reload() ,使用location.href 瀏覽器會讀取本地緩存資源。
正確使用display的屬性
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
按需加載
將不影響首屏的資源和當(dāng)前屏幕資源不用的資源放到用戶需要時才加載,可以大大提升重要資源的顯示速度和降低總體流量。
PS:按需加載會導(dǎo)致大量重繪,影響渲染性能
a) LazyLoad
b) 滾屏加載
c) 通過Media Query加載
合理使用緩存
使用緩存可以減少向服務(wù)器的請求數(shù),節(jié)省加載時間,所以所有靜態(tài)資源都要在服務(wù)器端設(shè)置緩存,并且盡量使用長Cache(長Cache資源的更新可使用時間戳
預(yù)加載
以下是幾個通過瀏覽器特性來很容易提高資源加載速度的方法:
1:DNS prefetching
DNS解析的速度可用通過下面的標(biāo)簽來進(jìn)行預(yù)解析
<link rel=”dns-prefetch” href=”//weibo.com”>
2:Preconnect
和DNS預(yù)解析差不多,Preconnect還會做TCP握手和TLS Negotiation:
<link rel=”preconnect” href=”http://css-tricks.com”>。
3:Prefetching
如果我們猜測用戶接下來將要訪問哪個具體的資源,那就可以用prefetching來預(yù)加載確定的資源了
<link rel=”prefetch” href=”image.png”>
4:Prerendering pages
預(yù)先渲染頁面,這是更牛的預(yù)加載方式了,他的作用就類似打開一個隱藏的tab差不多
<link rel=”prerender” href=”http://css-tricks.com”>
5:新特性:Preloading
和prefetching不同的是,preloading會讓瀏覽器無論如何都下載指定的資源
<link rel=”preload” href=”image.png”>
6:H5音樂預(yù)加載
<audio src=”music.mp3″ autoplay=”autoplay” loop preload=”auto” id=”sendid2″></audio>
參考資料:
最近做首屏優(yōu)化學(xué)到的知識點
關(guān)于首屏優(yōu)化
首屏加載優(yōu)化有哪些方案?
網(wǎng)站首屏優(yōu)化總結(jié)
web前端性能優(yōu)化之CDN