前端的性能優化能夠從網絡層面和渲染層面兩個維度來實現優化,網絡層面主要指的是HTTP請求與響應過程,渲染層面指的是瀏覽器端或者說是客戶端(包括瀏覽器和代理服務器等)。javascript
webpack的性能優化主要從兩個方面着手,縮短構建時間和減少打包結果體積,優化方案有配置loader讓它忽略掉指定文件夾的打包,將轉譯結果緩存、使用插件來優化(使用DllPlugin將第三方庫單獨打包到一個文件中;使用Happypack將loader由單進程轉爲多進程;使用webpack-bundle-analyzer可視化文件結構,找出致使體積過大的緣由;使用DllPlugin拆分資源;使用Tree-Shaking 和UglifJsPlugin刪除冗餘代碼;使用require.ensure按需加載)。html
圖片的優化就是在作權衡,由於咱們作的就是選擇質量好的體積又小的圖片格式,或者是壓縮圖片的體積又要保證圖片的質量。圖片優化咱們須要瞭解不一樣圖片格式的優缺點,它們適用的不一樣業務場景,不談業務場景的選型就是流氓。通常來講,JPG適用於呈現色彩豐富的圖片,好比大的背景圖、輪播圖或者Banner圖;PNG適合用來呈現小的Logo,顏色簡單且對比強烈的圖片;SVG是一種更好的選擇方式,它的體積更小,並且能夠無限放大而不失真,可是它的渲染成本較高;Base64是做爲雪碧圖的補充而存在的,它不是圖片格式,而是一種編碼方式,咱們能夠直接將編碼結果寫入 HTML 或者寫入 CSS,從而減小 HTTP 請求的次數,主要用來呈現小圖,小的logo;WebP是最年輕的一種圖片格式,支持有損壓縮和無損壓縮,集多種圖片的格式的優勢於一身,可是的缺點就是兼容性很差,若是要使用WebP,就要作兼容性處理。前端
關於圖片的優化有一些建議:vue
HTTP壓縮就是以縮小體積爲目的 ,對HTTP內容進行從新編碼的過程。Gzip 壓縮背後的原理,是在一個文本文件中找出一些重複出現的字符串、臨時替換它們,從而使整個文件變小。根據這個原理,文件中代碼的重複率越高,那麼壓縮的效率就越高,使用 Gzip 的收益也就越大。咱們知道服務端的Gzip壓縮是消耗CPU的,因此咱們須要給服務器分壓,咱們能夠利用webpack中的gzip壓縮來爲服務端的gzip分壓。java
緩存能夠減少網絡IO消耗,提升訪問速度,通常咱們講的瀏覽器能夠簡單理解爲HTTP緩存,可是瀏覽器的緩存包括四個方面,首先是內存(Memory Cache),而後是Service Worker Cache,再是磁盤(Disk Cache,也就是HTTP Cache),最後是Push Cache。react
本地存儲主要是Cookie,Web Storage(Local Storage和Session Storage)和IndexDB。Cookie能夠用來存儲用戶愛好和購買記錄,用戶瀏覽過的網站,曾經點擊過的廣告等信息;Session Storage 更適合用來存儲生命週期和它同步的會話級別的信息。這些信息只適用於當前會話,當你開啓新的會話時,它也須要相應的更新或釋放,好比微博的 Session Storage 就主要是存儲你本次會話的瀏覽足跡;Local Storage 的特色之一是持久,有時咱們更傾向於用它來存儲一些內容穩定的資源。好比圖片內容豐富的電商網站會用它來存儲 Base64 格式的圖片字符串;IndexDB 是一個運行在瀏覽器上的非關係型數據庫,IndexDB 能夠看作是 LocalStorage 的一個升級,當數據的複雜度和規模上升到了 LocalStorage 沒法解決的程度,咱們毫無疑問能夠請出 IndexDB 來幫忙。webpack
CDN的核心點有兩個,緩存和回源,CDN每每用來存放靜態資源,它像一個倉庫,而根服務器本質上是業務服務器,它的任務是生成動態頁面或返回非純靜態頁面,這兩種過程都是須要計算的。CSD的效用最大化涉及到服務器自己的性能優化,CDN節點的選址等,另外在CDN的域名選取時要與業務服務器的域名不同,這樣小的一個細節也能很大的提升性能。git
服務端渲染的模式下,當用戶第一次請求頁面時,由服務器把須要的組件或頁面渲染成 HTML 字符串,而後把它返回給客戶端。客戶端拿到手的,是能夠直接渲染而後呈現給用戶的 HTML 內容,不須要爲了生成 DOM 內容本身再去跑一遍 JS 代碼。使用服務端渲染的網站,能夠說是「所見即所得」,頁面上呈現的內容,咱們在 html 源文件裏也能找到。不少網站是爲了讓搜索引擎搜到網站內容才採起服務端渲染的,性能卻是其次,而服務端渲染自己解決了一個很是關鍵的性能問題——首屏加載速度過慢。在react,vue中服務端渲染的實踐中,主要在於兩點:一是renderToString()方法,而是把轉化結果塞進模板裏。SSR優化的再好仍是比較消耗CPU的,咱們何不要讓服務器去作這件事,一個公司服務器是有限的,公司更願意讓用戶的瀏覽器去跑,因此大部分網站都沒有用服務端渲染,另外首屏渲染體驗和SEO的優化方案有不少,通常咱們都不會取用服務端渲染。github
DOM的訪問和修改所帶來的開銷都是很大的,並且對DOM的修改會引起它的外觀(樣式)的改變時,就會觸發迴流或重繪,實際上是DOM的修改觸發了渲染樹(render tree)的變化,而後致使迴流或重繪。DOM的優化主要就是減小對DOM的訪問(少交過路費)和減小對DOM的修改(避免過分渲染,避免過分迴流或重繪),咱們常常作的就是讓JS給DOM分壓,用DOM Fragment來緩存批量化的DOM操做。web
實現異步更新
Vue 和 React 都實現了異步更新策略。雖然實現的方式不盡相同,但都達到了減小 DOM 操做、避免過分渲染的目的。當咱們使用 Vue 或 React 提供的接口去更新數據時,這個更新並不會當即生效,而是會被推入到一個隊列裏。待到適當的時機,隊列中的更新任務會被批量觸發,這就是異步更新。異步更新的特性在於它只看結果,所以渲染引擎不須要爲過程買單。
避免可能會引起迴流與重繪的DOM操做
咱們能夠監聽滾動事件,懶加載實現是根據若是可視區域高度大於元素頂部距可視區域頂部的高度,說明元素露出,這時給元素寫入真實的src,展現圖片
<script>
// 獲取全部的圖片標籤
const imgs = document.getElementsByTagName('img')
// 獲取可視區域的高度
const viewHeight = window.innerHeight || document.documentElement.clientHeight
// num用於統計當前顯示到了哪一張圖片,避免每次都從第一張圖片開始檢查是否露出
let num = 0
function lazyload(){
for(let i=num; i<imgs.length; i++) {
// 用可視區域高度減去元素頂部距離可視區域頂部的高度
let distance = viewHeight - imgs[i].getBoundingClientRect().top
// 若是可視區域高度大於等於元素頂部距離可視區域頂部的高度,說明元素露出
if(distance >= 0 ){
// 給元素寫入真實的src,展現圖片
imgs[i].src = imgs[i].getAttribute('data-src')
// 前i張圖片已經加載完畢,下次從第i+1張開始檢查是否露出
num = i + 1
}
}
}
// 監聽Scroll事件
window.addEventListener('scroll', lazyload, false);
</script>
複製代碼
**scroll 事件,resize 事件、鼠標事件(好比 mousemove、mouseover 等)、鍵盤事件(keyup、keydown 等)**都存在被頻繁觸發的風險。頻繁觸發回調致使的大量計算會引起頁面的抖動甚至卡頓。爲了規避這種狀況,咱們須要一些手段來控制事件被觸發的頻率。就是在這樣的背景下,throttle(事件節流)和 debounce(事件防抖)出現了。它們經過對事件對應的回調函數進行包裹、以自由變量的形式緩存時間信息,最後用 setTimeout 來控制事件的觸發頻率。
儘量使用外部腳本和樣式文本 使用分離的樣式表和腳本可使其被瀏覽器緩存,本站的其餘頁面可以重用該文件。
將樣式表放在頂部 把樣式表放在文檔底部會致使瀏覽器阻止頁面逐步呈現,這會致使用戶看不到頁面上內容的,在瀏覽器等待文檔底部的樣式表的時候,會延遲顯示任何可視化組件。在IE中會致使白屏現象。將樣式表放在文檔的頂部則能很好地解決白屏現象,使頁面逐步呈現。
腳本儘量移到底部
腳本放在頂部帶來的問題:
1) 使用腳本時,對於位於腳本如下的內容,逐步呈現將被阻塞 2) 在下載腳本時會阻塞並行下載 放在底部可能會出現JS錯誤問題,當腳本沒加載進來,用戶就觸發腳本事件。因此要綜合考慮狀況。
Script延遲加載 defer屬性(IE & FF3.1+)、setTimeout
避免CSS表達式對於 IE ,其支持 CSS 表達式,以下:
width:expression(document.body.clientWidth < 600 ? 「600px」 : 「auto」);
複製代碼
其餘瀏覽器會忽略該屬性,可是 IE 認識。這個寫法的性能低下之處,在於其更新頻率遠遠超出你的預估。它不僅僅會在頁面大小改變的時候求值,用戶滾動頁面,鼠標移動這都會進行求值。因此須要避免使用CSS表達式,必要的時候使用JavaScript處理。
優勢:能夠和主頁面並行加載 缺點: iframe會阻塞onload事件 解決:onload事件後設置iframe的src,或者JS建立iframe節點 和主頁面使用同一個鏈接池 避免src爲空—爲空默認爲主頁面地址
DOM層級越深會增長 CSS rule Tree 和 Dom Tree 匹配構造的性能
table會影響頁面呈現的速度,只有table裏的內容所有加載完纔會顯示
由於在同一域名下,只要有一個請求,cookie都會被傳來傳去,無論此次請求是否用到,因此須要減少cookie的大小
相關書籍與資料:
《高性能網站建設指南》