浏览器渲染之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。

相关文章
相关标签/搜索