浅显的说下浏览器的衬着历程

最初的模子:

  • 浏览器下载 html

  • 最先剖析 html

    • 碰见外链资本, 保存起来, 而且继承剖析

    • html 剖析终了

    • 最先下载外链

      • 下载终了

        • 最先处置惩罚

          • css 处置惩罚

          • js 处置惩罚

            • 处置惩罚终了, 最先衬着

            • 用户看到界面

这个模子的基本是: 浏览器是单线程的.

然则现实上: 浏览器不是单线程, 是多个线程.
浏览器有以下几个线程:
1 javascript引擎线程
2 界面衬着线程
3 浏览器事宜触发线程
4 http要求线程

也就是说: 下载和剖析是能够同步的, 碰见外链就最先下载.

变动以后的模子

  • 浏览器下载 html

  • 最先剖析 html

    • 碰见外链资本, 最先下载, 而且继承剖析

    • html 剖析终了

    • 下载终了

      • 最先处置惩罚

        • css 处置惩罚

        • js 处置惩罚

          • 处置惩罚终了, 最先衬着

          • 用户看到界面

这个模子的基本是:
资本下载和 html 剖析是同步的, 一切的资本下载终了, 才最先举行下一步:衬着.
现实情形是:
资本大抵能够分红
css
js
imgs
others

imgs以及 others 这类, 假如一个资本过大, 比如说一个媒体文件100M, 非要比及用户下载终了
才最先下一步, 这显然是不合理的.
而 css 和 js 是能够对页面发作修正和效果的, 所以必需要守候它们的介入才举行下一步操纵,
比如说 css,js 都没有下载剖析实行终了, 就最先下一步衬着, 终究衬着的效果是一个没有款式的
页面.

看浏览器是否是这么想的?
试验:
在demo 中加一个 p 标签, 在底部加一个 css 外链
假如 css 都没有加载终了, p 标签就显示出来了, 申明浏览器就没有等 css 文件
也就是说: html 剖析终了以后, 什么都不论, 就最先下一步衬着了.

demo:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>demo</title>
</head>
<body>
    <p>hello world</p>
    <link rel="stylesheet" href="https://www.google.com.hk/test.css">
</body>
</html>

效果:
css 没有加载之前, 页面空缺, 申明 html 剖析终了以后, 会比及css加载出来再最先衬着.

更一步的试验:
资本变成 js, 页面先衬着出来, js 还在加载.
资本变成 img, 页面会先衬着出来, img 还在加载.

结论:
**html 剖析终了以后, 会先比及 css 下载和剖析终了以后(经由历程 link 标签晓得是 css 文件)
再最先下一步, 并不会等一切的非 js 资本.**

所以模子变成:

  • 浏览器下载 html

  • 最先剖析 html

    • 碰见外链资本, 最先下载, 而且继承剖析

    • html 剖析终了

    • 比及css下载终了

      • 最先处置惩罚 css

        • 处置惩罚终了, 最先衬着

        • 用户看到界面

如今斟酌一种状况:
js 是有才能去转变 DOM, 那末假如都衬着终了了, js 这个时刻最先实行了,然后把页面从新干掉了.
这个时刻怎样办?


只能将修正应用到已衬着好的页面上.

斟酌一种极度状况, 页面内里有不计其数的节点, 比如说1万个节点, css 文件都 一两百k
辛辛苦苦浏览器把页面衬着出来了, 然后这个时刻, js 下载终了最先实行, 啪的一下把页面


document.write('中奖啦');

这类状况一定不能允许发作.

为了防止这类状况, 能够如许
先全局检测下是否是有 script 标签, 假如有的话, html 就等着 script 加载实行以后,
再最先衬着.

这类体式格局有一个不好: 也就是说, 纵然我们如今有了 html 和 css, 实在都能够把页面衬着出来了
然则照样要等 script 下载实行以后才敢举行衬着, 有点有所顾忌的觉得.
有时刻等半天, 能够 script 返回的就一句话:

console.log('逗你玩');

而且全局检测 script 标签, 这句话说的简朴, 现实上是要竖立在你已把 html 剖析终了了以后才晓得
究竟有无 script 标签.

所以现实的状况是:

浏览器不晓得页面内里有无 script 标签
不晓得script 内里会不会有 DOM 操纵, 是 '中奖啦' 照样 '逗你玩'

面临这类状况, 现实上只能赌, 或者说博弈.

浏览器拿到 html 和 css 以后照旧最先剖析衬着
为了减小万一中奖以后通盘都输的状况, 当碰见 script 以后

住手剖析, 用心下载 js 文件
    如许纵然中奖, 我也就衬着了前面了一点内容, 背面的还没有衬着, 输少点
    然则如许背面假如另有资本要加载。。。
    

所以更新战略:

浏览器碰见 script, 最先下载, 把背面的html 剖析掉, 一切的资本都最先下载
然后转头放心等这个 script, 看看究竟中奖不中奖.

所以模子变成:

  • 浏览器下载 html

  • 最先剖析 html

    • 碰见外链, 最先下载

      • 发明 script 外链, 继承html剖析

        • 将页面分红两部分, script 标签之前, 以后

          • 处于 script 之前的页面

            • css 下载终了

              • 衬着

              • 处于 script 以后的页面

                • script 下载终了, 实行

                  • css 下载终了

                    • 衬着

浏览器不是等一切的资本都下载终了才最先衬着
浏览器也不是比及一切的 js 都实行终了以后才会衬着

详细的衬着历程

当 html 剖析成 DOM tree, css 剖析成 CSSOM, 两者合并成
Render Tree, 就能够最先衬着了.

首先要先盘算这棵树上面的一切的节点的位置, 这一步叫做 layout
然后要给每一个节点上色, 这一步叫做 paint
layout 和 paint 统称为 render.

当页面的元素的位置修正以后, 就会涌现 relayout (重绘)
relayout 必定会形成 repaint.

附录: defer, async 之间的区分.

defer
之前说了, 浏览器碰见 js 以后会一直等着它实行, 背面的内容都不衬着了
然后常常就报错了, 我草猎取某个节点怎样没有, 想要猎取背面的节点然则节点还没有
衬着出来, 所以呢, 所以就有了 defer
相当于说, 我等你悉数衬着以后再实行吧, 要不然我总是失足, 烦人.
实行要在一切元素剖析完成以后,DOMContentLoaded 事宜触发之前完成。

async
另有一种状况, 就是说, 浏览器辛辛苦苦比及 js 下载实行终了发明哎吆我草这个玩意
对dom屁修改都没有, 我等她干吗啊, 我草草, 那就出来 async
这个东西就是说, 不需要等我, 也不需要体贴我的实行, 我不会滋扰你的, 你做本身的事变就好.
同时也处理了多个js之间的依靠, 加上这个就示意, 我是伶仃的, 我不依靠任何其他js也不给任何其他
js 依靠.

    原文作者:云水摇啊摇
    原文地址: https://segmentfault.com/a/1190000008277125
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞