這篇文章主要介紹了js和css文件位置對(duì)頁(yè)面性能的影響有哪些,具有一定借鑒價(jià)值,需要的朋友可以參考下。希望大家閱讀完這篇文章后大有收獲。下面讓小編帶著大家一起了解一下。
公司專(zhuān)注于為企業(yè)提供網(wǎng)站制作、成都網(wǎng)站制作、微信公眾號(hào)開(kāi)發(fā)、商城網(wǎng)站制作,微信小程序定制開(kāi)發(fā),軟件按需開(kāi)發(fā)網(wǎng)站等一站式互聯(lián)網(wǎng)企業(yè)服務(wù)。憑借多年豐富的經(jīng)驗(yàn),我們會(huì)仔細(xì)了解各客戶的需求而做出多方面的分析、設(shè)計(jì)、整合,為客戶設(shè)計(jì)出具風(fēng)格及創(chuàng)意性的商業(yè)解決方案,創(chuàng)新互聯(lián)更提供一系列網(wǎng)站制作和網(wǎng)站推廣的服務(wù)。
CSS和JS文件的位置會(huì)影響頁(yè)面效率。js腳本應(yīng)放在底部,如果放在首部,當(dāng)下載執(zhí)行js時(shí),會(huì)影響渲染行程繪制頁(yè)面;而CSS應(yīng)放在頂部,如果放在底部,頁(yè)面可以逐步呈現(xiàn),但在CSS下載并解析完畢后,已經(jīng)呈現(xiàn)的文字和圖片就要需要根據(jù)新的樣式重繪。
js腳本文件的位置
js腳本應(yīng)該放在底部,原因在于js線程與GUI渲染線程是互斥的關(guān)系,如果js放在首部,當(dāng)下載執(zhí)行js的時(shí)候,會(huì)影響渲染行程繪制頁(yè)面,js的作用主要是處理交互,而交互必須得先讓頁(yè)面呈現(xiàn)才能進(jìn)行,所以為了保證用戶體驗(yàn),盡量讓頁(yè)面先繪制出來(lái)。
CSS文件的位置
CSS 是頁(yè)面渲染的關(guān)鍵因素之一,(當(dāng)頁(yè)面存在外鏈 CSS 時(shí),)瀏覽器會(huì)等待全部的 CSS 下載及解析完成后再渲染頁(yè)面。關(guān)鍵路徑上的任何延遲都會(huì)影響首屏?xí)r間,因而我們需要盡快地將 CSS 傳輸?shù)接脩舻脑O(shè)備,否則,(在頁(yè)面渲染之前,)用戶只能看到一個(gè)空白的屏幕。
CSS文件放在頂部一方面是因?yàn)榉胖庙樞驔Q定了下載的優(yōu)先級(jí),更關(guān)鍵的是瀏覽器的渲染機(jī)制。
css在加載過(guò)程中不會(huì)影響到DOM樹(shù)的生成,但是會(huì)影響到Render樹(shù)的生成,進(jìn)而影響到layout,所以一般來(lái)說(shuō),style的link標(biāo)簽需要盡量放在head里面,因?yàn)樵诮馕鯠OM樹(shù)的時(shí)候是自上而下的,而css樣式又是通過(guò)異步加載的,這樣的話,解析DOM樹(shù)下的body節(jié)點(diǎn)和加載css樣式能盡可能的并行,加快Render樹(shù)的生成的速度。
將CSS放在底部,頁(yè)面可以逐步呈現(xiàn),但在CSS下載并解析完畢后,已經(jīng)呈現(xiàn)的文字和圖片就要需要根據(jù)新的樣式重繪,這是一種不好的用戶體驗(yàn)。
js、css等腳本位置對(duì)性能的影響
用一句話概括就是: JS 全阻塞,CSS 半阻塞。(詞是我發(fā)明的,方便記憶而已)
JS 會(huì)阻塞后續(xù) DOM 解析以及其它資源(如 CSS,JS 或圖片資源)的加載。
CSS 不會(huì)阻塞后續(xù) DOM 結(jié)構(gòu)的解析,不會(huì)阻塞其它資源(如圖片)的加載,但是會(huì)阻塞 JS 文件的加載。
現(xiàn)代瀏覽器很聰明,會(huì)進(jìn)行 prefetch 優(yōu)化,瀏覽器在獲得 html 文檔之后會(huì)對(duì)頁(yè)面上引用的資源進(jìn)行提前下載。(注意僅僅只是提前下載)
下面開(kāi)始我就一邊測(cè)試,一邊解釋上述測(cè)試的結(jié)果:
測(cè)試的瀏覽器是 Chrome,版本號(hào)為 55.0.2883.95 (64-bit)
先用 Nodejs 搭建一個(gè)簡(jiǎn)單 http 服務(wù)器:
//test.jsconst http = require('http');const fs = require('fs');const hostname = '127.0.0.1';const port = 9000;http.createServer((req, res) => { if(req.url === "/") { fs.readFile("index.html", "utf-8", function(err, data) { res.writeHead(200, { 'Content-Type': 'text/html' }); res.write(data); res.end(); }) }else if(req.url === "/yellow.js") { //延遲 5s fs.readFile("yellow.js", "utf-8", function(err, data) { res.writeHead(200, { 'Content-Type': 'text/plain' }); setTimeout(function () { res.write(data); res.end(); }, 5000); }) }else if(req.url === "/blue.js") { //延遲 10s fs.readFile("blue.js", "utf-8", function(err, data) { res.writeHead(200, { 'Content-Type': 'text/plain' }); setTimeout(function () { res.write(data); res.end(); }, 10000); }) }else if(req.url === "/red.css") { //延遲 15s fs.readFile("red.css", "utf-8", function(err, data) { res.writeHead(200, { 'Content-Type': 'text/css' }); setTimeout(function () { res.write(data); res.end(); }, 15000); }) }else if(req.url === "/green.css") { //延遲 20s fs.readFile("green.css", "utf-8", function(err, data) { res.writeHead(200, { 'Content-Type': 'text/css' }); setTimeout(function () { res.write(data); res.end(); }, 20000); }) }}).listen(port, hostname, () => { console.log('Server running at ' + hostname);});
首頁(yè)的代碼結(jié)構(gòu):
//index.html <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http-equiv="cache-control" content="no-cache,no-store, must-revalidate" /> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>測(cè)試瀏覽器渲染</title> </head> <body> <p>First Line</p> <script src="/yellow.js"></script> <p>Second Line</p> <link rel="stylesheet" href="/red.css"> <p>Third Line</p> <script src="/blue.js"></script> <p>Fourth Line</p> <link rel="stylesheet" href="/green.css"> <img src="http://www.liuhaihua.cn/wp-content/uploads/2016/02/uuUFNjm.png"> <p>Fifth Line</p> </body> </html>
以及其它 CSS 和 JS 文件:
//yellow.js document.body.style.cssText = "background: yellow !important"; //blue.js document.body.style.cssText = "background: blue !important";
//red.css body { background:red !important; } //green.css body { background: green !important; }
說(shuō)明下:yellow.js 和 blue.js 下載時(shí)間分別為 5s 和 10s,red.css 和 green.css 下載時(shí)間分別為 15s 和 20s。
之后將所有文件放到同個(gè)目錄下,在控制臺(tái)輸入 node test.js,打開(kāi)瀏覽器訪問(wèn) 127.0.0.1:9000 就可以訪問(wèn)。
先來(lái)看第三點(diǎn)結(jié)論:現(xiàn)代瀏覽器很聰明,會(huì)進(jìn)行 prefetch 優(yōu)化,瀏覽器在獲得 html 文檔之后會(huì)對(duì)頁(yè)面上引用的資源進(jìn)行提前下載。(注意僅僅只是提前下載)
很好理解,從圖中可以看出:CSS、JS、圖片在瀏覽器在拿到 html 文檔之后會(huì)將頁(yè)面上引用資源幾乎同時(shí)下載,但具體什么時(shí)候執(zhí)行要看 html 的結(jié)構(gòu),注意我這里使用的是 Chrome 瀏覽器,其它瀏覽器可能會(huì)有差別。
還有就是一個(gè)奇怪的現(xiàn)象,Chrome 瀏覽器有時(shí)會(huì)對(duì) img 進(jìn)行 prefetch,有時(shí)則不會(huì)。
接著是第一點(diǎn)規(guī)則:
JS 會(huì)阻塞后續(xù) DOM 解析以及其它資源(如 CSS,JS 或圖片資源)的加載。
從上圖可以看出,當(dāng)瀏覽器解析到 yellow.js 這行時(shí)候會(huì)等待 yellow.js 加載,阻塞后續(xù) DOM 結(jié)構(gòu)的解析(包括 DOM 結(jié)構(gòu),其他所有資源(CSS, JS, 圖片))。
這個(gè)很好理解:
JS 運(yùn)行在瀏覽器中,是單線程的,每個(gè) window 一個(gè) JS 線程,所以當(dāng)然會(huì)阻塞后續(xù) DOM 樹(shù)的解析咯。
JS 有可能會(huì)修改 DOM 結(jié)構(gòu),給 DOM 添加樣式等等,所以這就意味著在當(dāng)前 JS 加載執(zhí)行完成前,后續(xù)資源的加載可能是沒(méi)有意義的。
其次第二點(diǎn):
CSS 不會(huì)阻塞后續(xù) DOM 結(jié)構(gòu)的解析,不會(huì)阻塞其它資源(如圖片)的加載,但是會(huì)阻塞 JS 文件的加載。
這個(gè)就相對(duì)比較復(fù)雜點(diǎn),讓我先上測(cè)試結(jié)果的圖:
從圖中可以得出以下總結(jié):
在加載完 yellow.js 后,當(dāng)在下載 red.css 時(shí)候并不會(huì)阻塞 DOM 解析,并且由于第一點(diǎn)規(guī)則,當(dāng)解析到 blue.js 這行的時(shí)候,同樣會(huì)阻塞后續(xù) DOM 解析。
由于我們?cè)O(shè)置的 red.css 下載時(shí)間為 15s 而 blue.js 為 10s,而從前面第三條規(guī)則的圖中也可以看到,blue.js 在 10s 左右下載完而 red.css 在 15s 左右下載完畢。
最后在 15s 時(shí)候頁(yè)面變?yōu)榱怂{(lán)色,這說(shuō)明了 CSS 阻塞了 JS 的加載,后續(xù)的 JS 文件雖然提前下載完畢了,但還是要等前面 CSS 文件加載完后才能執(zhí)行。
后續(xù)當(dāng) blue.js 加載完之后可以看到,green.css 的下載并不會(huì)影響到后續(xù) img 的加載,所以說(shuō)明 CSS 文件下載并不會(huì)影響后續(xù)圖片等其它資源以及 DOM 的加載。
這個(gè)也好理解:JS 代碼在執(zhí)行前,瀏覽器必須保證在 JS 之前的所有 CSS 樣式都解析完成,不然不就亂套了,前面的 CSS 樣式可能會(huì)覆蓋 JS 文件中定義的元素樣式,這是 CSS 阻塞后續(xù) JS 執(zhí)行的根本原因。
最后這里說(shuō)明下為什么最后 body 的背景色沒(méi)有變成綠色:因?yàn)?js 定義的樣式在內(nèi)聯(lián)樣式,優(yōu)先級(jí)高于在 CSS 文件中定義的樣式,所以不是 green.css 沒(méi)有加載,而是沒(méi)有生效。看下圖就知道了:(green 和 red 樣式都被劃掉了)
所以知道了上述的結(jié)論之后,我們?cè)陂_(kāi)發(fā)的時(shí)候應(yīng)該盡可能地:
將樣式或 CSS 文件定義在 head 中,并且在處理此類(lèi)請(qǐng)求的時(shí)候應(yīng)該盡快能夠響應(yīng)(cdn 什么的),如果像上面請(qǐng)求一個(gè) CSS 文件都要 10s 的話,那你這頁(yè)面估計(jì)沒(méi)多少人有耐心等下去。
將 JS 腳本文件放在 body 底部,讓 DOM 結(jié)構(gòu)能優(yōu)先渲染出來(lái),避免 DOM 被阻塞。
當(dāng)編寫(xiě)比較耗時(shí)的 JS 代碼時(shí)候盡可能使用異步的方式進(jìn)行加載,比如 setTimeout, ajax 等等,同樣也是為了避免頁(yè)面渲染耗時(shí)過(guò)長(zhǎng),影響用戶體驗(yàn)。
上面介紹了 JS 會(huì)阻塞后續(xù) DOM 解析以及其它資源(如 CSS,JS 或圖片資源)的加載,這是在沒(méi)有考慮到 defer, async 的情況下。
當(dāng)瀏覽器碰到 script 腳本的時(shí)候:(不考慮瀏覽器的 prefetch)
<script async src="script.js"></script>
有 async,加載和渲染后續(xù)文檔元素的過(guò)程將和 script.js 的加載與執(zhí)行并行進(jìn)行(下載異步,執(zhí)行同步)。<script defer src="script.js"></script>
有 defer,加載后續(xù)文檔元素的過(guò)程將和 script.js 的加載并行進(jìn)行(異步),但是 script.js 的執(zhí)行要在所有元素解析完成之后,DOMContentLoaded 事件觸發(fā)之前完成。從使用的角度來(lái)看,首先把腳本丟到 body 底部是比較好的優(yōu)化選擇,此法可保證非腳本的其他一切元素能夠以最快的速度得到加載和解析。
上述的三點(diǎn)用圖可表示為:
藍(lán)色線代表網(wǎng)絡(luò)讀取,紅色線代表執(zhí)行時(shí)間,這倆都是針對(duì)腳本的;綠色線代表 HTML 解析。
總結(jié):
由于現(xiàn)代瀏覽器都存在 prefetch,所以 defer, async 可能并沒(méi)有太多的用途,可以作為了解擴(kuò)展知識(shí),僅僅將腳本文件放到 body 底部就可以起到很不錯(cuò)的優(yōu)化效果。
defer 和 async 都是異步加載腳本文件。
慎用 async,因?yàn)樗耆豢紤]依賴關(guān)系,只要下載完后就加載,不考慮此時(shí)頁(yè)面樣式先后的加載順序,不過(guò)它對(duì)于那些可以不依賴任何腳本或不被任何腳本依賴的腳本來(lái)說(shuō)卻是非常合適的,最典型的例子:Google Analytics。
耗時(shí)較長(zhǎng)的腳本代碼可以使用 defer 來(lái)推遲執(zhí)行。
感謝你能夠認(rèn)真閱讀完這篇文章,希望小編分享js和css文件位置對(duì)頁(yè)面性能的影響有哪些內(nèi)容對(duì)大家有幫助,同時(shí)也希望大家多多支持創(chuàng)新互聯(lián),關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,遇到問(wèn)題就找創(chuàng)新互聯(lián),詳細(xì)的解決方法等著你來(lái)學(xué)習(xí)!
名稱(chēng)欄目:js和css文件位置對(duì)頁(yè)面性能的影響有哪些
分享網(wǎng)址:http://chinadenli.net/article38/gshjpp.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供靜態(tài)網(wǎng)站、云服務(wù)器、營(yíng)銷(xiāo)型網(wǎng)站建設(shè)、面包屑導(dǎo)航、企業(yè)網(wǎng)站制作、微信公眾號(hào)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)