瀏覽器渲染之link標籤和script標籤對頁面的影響

1、引子

最近看了本書,叫《web 高效編程與優化實踐》,看的過程當中激發了我對 Chrome Devtools 的興趣,剛好看到了關於性能優化和網頁渲染的那部分,又想起了以前看過各大論壇你們對於瀏覽器渲染的理解,因此打算本身再看看這部分的知識點,解決一些疑問。css

本文的試驗都是基於 Chrome 瀏覽器,版本:75.0.3770.100(正式版本)(64 位)html

2、前置知識

先上連接:前端

這幾篇部分是在這個過程當中看到的感受比較細緻且靠譜的文章,雖然文章的寫做時間都不算早,可是原理基本不會有太大變化,你們若是看完個人文章以爲不過癮的話,能夠看看這些文章。html5

先簡單歸納一下瀏覽器渲染的步驟:node

  1. 瀏覽器接收到 html 文檔
  2. 解析 html 文檔生成 dom 對象模型,是一個樹形結構。
  3. 發起請求,獲取 html 中的外部資源,好比圖片,css文件,js文件等。
  4. 獲取css文件後,生成 css 對象模型,也是一個樹形結構。
  5. 有了 dom 對象模型樹和 css 對象模型樹,瀏覽器會生成渲染樹(render tree)。
  6. 有了渲染樹,瀏覽器會執行一個叫作佈局的操做(layout),用於計算頁面上各個元素的幾何位置。
  7. 最終,瀏覽器會把「佈局」好的頁面元素繪製(paint)成咱們最終看到的網頁。

以上步驟說的比較簡略,並且沒有帶上 reflow 和 repaint,主要是幫你們梳理一下這個過程,便於後面的閱讀。web

3、正文

終於說到文章正題,想必標題你們也看到了,是想研究一下 link 標籤和 script 標籤對頁面渲染的影響,既然是影響,確定是不理想的狀況。至於對頁面渲染的影響,這裏主要討論的是對頁面首次繪製時的影響。chrome

下面讓咱們先整理一下不理想的狀況,而後一個一個來試驗下:express

  • link 標籤正常位置加載時間過長
  • link 標籤非正常位置加載時間過長
  • script 標籤正常位置加載時間過長
  • script 標籤非正常位置加載時間過長

這就是本文試驗的一些狀況,正常位置固然是咱們平時總說的 link 標籤要放在首部 head 中,script 標籤放在 body 底部,加載時間過長經過服務器端延時 5000 毫秒來處理。編程

本次爲了快速開發,用到了一些快速搭建的工具,先推薦給你們:瀏覽器

  • Parcel:一個小型前端打包工具,很方便就能起個服務,以前用過一次,感受很好用。
  • express:由於要模擬網絡很差的狀況,雖然谷歌瀏覽器裏也能夠設置網絡速度,可是我如本身控制來的直觀,因此仍是本身簡答搞個 server 靠譜些,express 就很少介紹了。
  • nodemon:用了這個來監測 server 端的文件修改,其實寫好後也沒啥改動,就是修改一下不一樣文件返回時的延遲時間。

行了,就用到這些東西,廢話很少說,咱們開始吧。

先來看看咱們用到的文件:

html:

<!DOCTYPE html>
<html lang="zh-cmn-Hans">

<head>
    <meta charset="utf-8">
    <meta http-equiv="x-ua-compatible" content="IE=edge, chrome=1">
    <title>debounce</title>
    <style> img { width: 500px; } .block { width: 300px; height: 200px; border: 1px solid #000; } </style>
    <link href="http://127.0.0.1:3000/public/css/common.css" rel="stylesheet">
</head>

<body>
    <div class="block">
        <h2 class="title">我是一段沒有感情的測試文案</h2>
    </div>
    <div class="pic">
        <img src="https://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=4215863670,261223381&fm=26&gp=0.jpg">
    </div>
    <script src="http://127.0.0.1:3000/public/js/test.js"></script>
</body>
</html>
複製代碼

common.css:

.block {
	width: 500px;
	background-color: red;
	border: none;
}
複製代碼

test.js:

document.querySelector('.title').innerHTML = '我被修改了';
複製代碼

app.js:

const express = require('express')
const app = express()
const fs = require('fs')
const path = require('path');

app.use('*',function(req, res){
    if (req.params[0] === '/public/css/common.css') {
        // setTimeout(() => {
            res.setHeader('content-type', 'text/css');
            res.send(fs.readFileSync(path.join(__dirname, req.params[0])));
        // }, 5000)
    } else if(req.params[0] === '/public/js/test.js') {
        // setTimeout(() => {
            res.send(fs.readFileSync(path.join(__dirname, req.params[0])));
        // }, 5000)
    } else {
        res.send('success');
    }
})

app.listen(3000, () => console.log('working'))
複製代碼

這個頁面打開之後是這個樣子的:

狀況一:js在頁面頂部延遲加載

讓咱們先把 js 標籤放到 head 的底部,也就是 link 標籤下面(這裏爲了避免把每次改完標籤位置的html都帖出來,我每次說的位置都是以初始位置爲基準),並把服務器端延時的代碼加上來看看效果:

能夠看到頁面由於 js 腳本的延遲加載,致使頁面白屏長達數秒,這確定不是咱們平時開發中想要的,還有由於腳本位置過前致使操做的 dom 元素也沒法找到。

再讓咱們看看控制檯中這個頁面具體經歷了什麼:

經過 performance 咱們能夠看到頁面的在 5s 後纔開始首次繪製,timeline 上也很容易看出前面頁面一直處於白屏階段。

狀況二:js在頁面底部延遲加載

如今讓咱們把 js 放到初始的位置,一樣加上延遲,再看下效果:

此次咱們能夠看到雖然 js 文件延遲加載了,可是 js 文件以前的元素很快就渲染出來了,再看下控制檯:

此次就很快了,頁面沒有由於 js 的加載阻塞前面元素的渲染,js 文件加載後由於修改了 dom 元素又繪製了一次。因此說把 js 文件放在頁面底部這個作法仍是比較合理的,可是也須要分狀況討論,好比有些頁面較長,圖片較多,可能首屏只展示了部分 dom,這時若是把全部的 js 都放在頁面底部,反而可能會影響 js 腳本對 dom 操做的實時性。

狀況三:css在頁面頂部延遲加載

看完了 script 標籤,如今讓咱們看下 link 標籤的表現,首先把 script 標籤的延遲去掉,讓 link 標籤待在它原來的位置,在服務端加上延遲試一下:

很差意思,這裏沒有動圖。。。

此次的狀況動圖能夠參考動圖一,由於第一次正經寫文章,因此 gif 圖是先錄屏,而後截視頻,再上傳視頻作 gif。有點麻煩,就懶得再搞一個了,小夥伴有好的軟件或者方法歡迎評論區推薦。 至於網頁的 performance 和第一種狀況也是基本無差,我們直接進入到下一種狀況吧。

狀況四:css在頁面底部延遲加載

此次咱們把 link 標籤放到 body 的底部,其實前三種的狀況和我想象中的基本沒差,我試這個就是想看看最後一種狀況,來直接看圖吧:

誒,貌似和我預想的不太同樣,咱們先來看下控制檯確認下:

咱們能夠看到瀏覽器此次並無像 script 腳本延遲時同樣,等到 css 加載完纔開始繪製,而是很早就把 dom 畫出來了,等 css 加載完後,又再次繪製了一遍。後來我多試了幾回,若是把css文件放到dom中間位置,發現css文件的延遲一樣會阻塞後面元素的渲染,這個是我以前沒有想到的。

4、結語

其實,若是網速足夠快,在資源的加載這一塊,咱們根本無需考慮優化,由於腳本自己不會大的離譜,因此在網速超快的狀況下,固然是想放哪裏放哪裏。可能在5年、10年之後的開發者回過頭來我這篇文章,沒準會對我如今考慮的這些問題不屑一顧,hhh。

相關文章
相關標籤/搜索