網站效能優化可以從下面總結點入手。
background-position
調整圖片顯示位置。這種方式適用面比較廣泛。data:URL
展示圖片,它可以在頁面中渲染圖片但無需額外的HTTP請求,請求格式:<img scr="data:image/jpg;base64, xxxxxxxxxxxxxxxx">
缺點是:此方案不適合mobile應用;IE7以下不支援;如果一張圖片在多個頁面被用到,無法利用瀏覽器快取。
為了解決無法快取問題,可以將data:image
應用到CSS樣式中,比如:
.imageA { background-image: url(data:image/jpg;base64, xxxxxxxxxxxxxxxx); }
req.responseText
function splitImages(imageString){ var imageData = imageString.split('\u0001'); var imageElement; for (var i =0, len = imageData.length; i<len; i++){ imageElement = document.createElement('img'); imageElement.src = 'data:image/jpeg;base64,' + imageData[i]; document.getElementById('container').appendChild(imageElement); } }
內容釋出網路(CDN)是一組分佈在多個不同地理位置的WEB伺服器,用於更加有效地向用戶釋出內容。
CDN用於釋出靜態內容,如圖片,指令碼,樣式表和Flash。
不使用CDN時:
儘量將CDN的域名設定的不同於請求方網站的域名。比如,網站為a.com
,CDN域名可以設定為acdn.com
。為什麼呢?
Cookie隔離:Cookie 是緊跟域名的,同一個域名下的所有請求,都會攜帶 Cookie。試想,海量請求圖片或JS/CSS檔案時,還要攜帶Cookie,也會成為不小的開銷。
並且,瀏覽器在同一個時刻向同一個域名請求檔案的並行下載數量是有限的(Chrome為6個並行),所以,可以利用多個域名主機存放不同的靜態資源,增大頁面載入時資源並行下載數量。
https://www.cnblogs.com/yizhiamumu/p/16687989.html
開啟HTTP Gzip壓縮。
request: Accept-Encoding: gzip, deflate
response:Content-Encoding:gzip
外部指令碼檔案和CSS檔案是並行下載的,把樣式表在頁面中的位置並不影響下載時間,但會影響頁面的呈現!瀏覽器必須要等樣式表載入完畢之後才渲染頁面。
因此,應該把樣式表放在head中,這樣它就能被最先下載使頁面逐步呈現。
一般,JS指令碼是被禁止並行下載的,因為JS指令碼可能使用document.write
來修改頁面內容,所以必須保證JS執行順序。
指令碼下載後,必須執行完,才可以繼續後面的解析。
但是,Chrome瀏覽器支援並行下載資原始檔,並保證按順序執行(參考《WebKit技術內幕-朱永盛》)。
CSS表示式是動態設定CSS屬性的一種強大(並且危險)的方式。CSS表示式求值頻率比人們期望的要高,它們不只在頁面呈現和大小變化時求知,甚至使用者滑鼠在頁面上拖拽都要求知。
如,將背景色設定為每小時變化一次:
background-color:expression((new Date()).getHours()%2?"#ccc":"#000");
觸發頻率太高!不建議使用。
純粹來講,內聯的JS和CSS可以產生比外部檔案檔案更快的響應速度。
但是現實中,外部連結的JS和CSS檔案會產生較快的頁面,是因為JS和CSS檔案有可能被快取。
DNS也是開銷。通常瀏覽器查詢一個給定主機名的IP地址要花費20~120毫秒。在DNS查詢完成之前,瀏覽器不能從主機名哪裡下載任何東西。
只要cline-server之間保持TCP連線開啟狀態,就無需DNS查詢。所以,我們可以通過使用Keep-Alive
和較少的域名來減少DNS查詢。
Keep-Alive
,HTTP1.1協定中推出的持久連線。特點為:只要任意一端沒有明確提出斷開連線,則保持TCP連線狀態。
含有Keep-Alive
首部的response範例:
HTTP/1.1 200 OK Connection: Keep-Alive Content-Encoding: gzip Content-Type: text/html; charset=utf-8 Date: Thu, 11 Aug 2016 15:23:13 GMT Keep-Alive: timeout=5, max=1000 Last-Modified: Mon, 25 Jul 2016 04:32:39 GMT Server: Apache
可以用各類構建或者編譯工具壓縮指令碼和樣式檔案,比如:gulp
,webpack
iframe是開銷最高的DOM元素,它的缺點遠大於優點。
<iframe id="iframe1" src=""></iframe> <script> document.getElementById('iframe1').src = "www.api.a.com"; </script>
table
內容渲染是將table
的DOM渲染樹全部生成完並一次繪製到頁面上,所以,在渲染長表格時很耗效能,應該儘量避免使用。
可以使用ul
或div
替代。
有多種方式支援JavaScript非同步載入。
script
標籤,並設定其src
值。如下:function createScript(url){ var scrElem = document.createElement('script'); srcElem.src = url; document.getElementsByTagName('head')[0].appendChild(scrElem); }
優點:支援跨域載入指令碼檔案;相容性最好、普適性最高的方案
缺點:指令碼無序執行;會阻塞onload事件
通過XMLHttpRequest
的方式下載指令碼檔案,然後使用eva
l或者動態新增<script>
標籤並設定其text
屬性來執行指令碼。
// 不考慮IE var xhrObj = new XMLHttpRequest(); xhrObj .onreadystatechange = function(){ if (xhrObj .readyState == 4) { // 方式一 eval(xhrObj.responseText); // 方式二 var scrElem = document.createElement('script'); srcElem.text= xhrObj.responseText; document.getElementsByTagName('head')[0].appendChild(scrElem); } } xhrObj .open('GET', 'a.js', true); xhrObj .send('');
優點:將指令碼下載和指令碼執行分離開,可以在適當的時候再執行指令碼;不會阻塞onload事件
缺點;通過XMLHttpRequest
獲取的指令碼檔案必須和主頁面是同一個域名下。也就是說,不支援跨域下載指令碼(除非做跨域處理)。因此不適合載入第三方檔案;指令碼無序執行。
兩者都支援非同步載入檔案,不同之處是,defer
會在全部資源下載完畢後才執行JS檔案;async
在指令碼檔案下載完就立刻執行,並且,async
模式載入的JS檔案無法依序執行,對於有順序依賴的指令碼來說,不應該採用這種方式。
defer相對友好一些,並可以保證JS檔案按照順序執行。
<script src="a.js" defer></script> <script src="a.js" async></script>
defer和async優點:支援跨域載入指令碼檔案。
defer優點:可以保證JS檔案按照順序執行。
defer和async缺點:IE10以上(包括IE10)才支援。
async缺點:JS檔案無法依序執行;會阻塞onload事件
通過圖片懶載入可以讓一些不可視的圖片不去載入,避免一次性載入過多的圖片導致請求阻塞(瀏覽器一般對同一域名下的並行請求的連線數有限制),這樣就可以提高網站的載入速度,提高使用者體驗。
第一步: 懶載入的img標籤的src設定縮圖或者不設定src,然後自定義一個屬性,值為真正的圖片或者原圖的地址(比如data-src)。
// https://a.com/logo.png 是圖片的真實地址,設定到data-src屬性上。 <img data-src="https://a.com/logo.png" class="lazy-image"/> // css部分 .lazy-image { background: url('loading.gif') no-repeat center; }
第二步:頁面載入完後,獲取所有需要懶載入的圖片的元素集合,判斷是否在可視區域,如果是在可視區域的話,設定元素的src屬性值為真正圖片的地址。
// 監聽捲動事件 document.addEventListener('scroll', inViewShow); // 顯示圖片 inViewShow() { let imageElements = Array.prototype.slice.call(document.querySelectorAll('.lazy-image')) let len = imageElements.length for(let i = 0; i < len; i++) { let imageElement = imageElements[i] const rect = imageElement.getBoundingClientRect() // 出現在視野的時候載入圖片 if(rect.top < document.documentElement.clientHeight) { imageElement.src = imageElement.dataset.src // 賦值到真正的src上 imageElements.splice(i, 1) len-- i-- } } }
利用瀏覽器新特性IntersectionObserver
(IntersectionObserver介面提供了一種非同步觀察目標元素與其祖先元素或頂級檔案視窗(viewport)交叉狀態的方法)。
// 渲染 public render() { const { src } = this.state // 一旦src變化,更新為img標籤,載入圖片 if (src) { return <img {...this.props} src={src} /> } // 佔點陣圖片 return ( <span ref={(ele) => (this.ele = ele)} /> ) } // 監控 public componentDidMount() { // 判斷瀏覽器是否支援IntersectionObserver函數 if (typeof IntersectionObserver === 'function') { const cb = (entries) => { if (entries.some((item) => item.intersectionRatio > 0)) { const { src } = this.props this.setState({ src }) this.ob.disconnect() // 取消監聽 } } this.ob = new IntersectionObserver(cb, { root: document.body, // 祖先元素 threshold: [0, 0.01], // 交叉值 }) this.ob.observe(this.ele) } else { const { src } = this.props this.setState({ src }) } }
使用三方庫處理圖片懶載入。
當link
標籤中的href
,或者ifram
,script
,img
標籤的src
屬性為空時,瀏覽器在渲染過程中仍然會將href
和src
中的空內容進行載入,直到失敗為止。這樣會阻塞頁面中其他資源的下載過程。
頁面重定向會延長頁面內容返回的等待時間,一次重定向大致需要600毫秒。
相比HTTP1.1,2.0版本有了更強大的能力,可以提升傳輸效能。
dns-prefetch
,preconnect
,prefetch
和prerender
dns-prefetch
:使瀏覽器主動去執行域名解析。
<link rel="dns-prefetch" href="https://fonts.google.com/" >
preconnect
:提前建立連線。比dns-prefetch
多走了兩步,除了完成dns解析之外,還完成了TCP握手(HTTPS下還完成TLS握手)。
<link rel="preconnect" href="https://fonts.google.com/" >
prefetch
:讓瀏覽器預載入一個資源(HTML,JS,CSS或者圖片等),可以讓使用者跳轉到其他頁面時,響應速度更快。
<link rel="prefetch" href="https://css-tricks.com/a.png">
prerender
:不僅會載入資源,還會解執行頁面,進行預渲染(太重,不建議使用)
<link rel="prefetch" href="https://css-tricks.com/a.html">