zoukankan      html  css  js  c++  java
  • BOM 浏览器对象模型_渲染引擎_JavaScript 引擎_网页加载流程

    1. 浏览器核心的两个组成部分

    渲染引擎

    将网页代码渲染为用户视觉可以感知的平面文档

    • 分类:

     

    • Firefox        Gecko 引擎
    • Safari        WebKit 引擎
    • Chrome        Blink 引擎
    • IE        Trident 引擎
    • Edge        EdgeHTML 引擎

     

    • 渲染引擎处理网页,通常分成四个阶段

    1. 解析代码:HTML 代码解析为 DOM,CSS 代码解析为 CSSOM(CSS Object Model)。
    2. 对象合成:将 DOM 和 CSSOM 合成一棵渲染树(render tree)。
    3. 布局:计算出渲染树的布局(layout)。   
    4. 绘制:将 渲染树 绘制到屏幕

     

    往往第一步还没完成,第二步和第三步就已经开始了。

    所以,会看到这种情况:网页的 HTML 代码还没下载完,但浏览器已经显示出内容了

    • 渲染树转换为网页布局,称为“布局流”(flow)
    • 布局显示到页面的这个过程,称为“绘制”(paint)

    重流 和 重绘并不一定一起发生,

    重流必然导致重绘,重绘不一定需要重流。

    比如

    • 改变元素颜色,只会导致重绘,而不会导致重流;
    • 改变元素的布局,则会导致重绘和重流
    • 作为开发者,应该尽量设法降低重绘的次数和成本

    比如,重绘 table 布局 和 flex 布局,开销都会比较大

    尽量不要变动高层的 DOM 元素

    不要一项一项地改变样式,而是使用 CSS class 一次性改变样式

     

    JavaScript 引擎

    主要作用是,读取网页中的 JavaScript 代码,对其处理后运行

    • 解释型语言,也就是说,它不需要编译,由解释器实时运行

    缺点: 是每次运行都要调用解释器,系统开销较大,运行速度慢于编译型语言

    早期解决:

     进行一定程度的编译,生成类似字节码(bytecode)的中间代码,以提高运行速度

    逐行解释将字节码转为机器码,还是很低效的

     

    • 读取代码,进行词法分析(Lexical analysis),将代码分解成词元(token)。
    • 对词元进行语法分析(parsing),将代码整理成“语法树”(syntax tree)。
    • 使用“翻译器”(translator),将代码转为字节码(bytecode)。
    • 使用“字节码解释器”(bytecode interpreter),将字节码转为机器码。

     

    如今:

    采用“即时编译”(Just In Time compiler,缩写 JIT)

    即字节码只在运行时编译,用到哪一行就编译哪一行,并且把编译结果缓存(inline cache)。

    通常,一个程序被经常用到的,只是其中一小部分代码,有了缓存的编译结果,整个程序的运行速度就会显著提升

    • 字节码不能直接运行,而是运行在一个虚拟机(Virtual Machine)之上,一般也把虚拟机称为 JavaScript 引擎
    • 并非所有的 JavaScript 虚拟机运行时都有字节码

    有的 JavaScript 虚拟机基于源码,即只要有可能,就通过 JIT(just in time

    编译器直接把源码编译成机器码运行,省略字节码步骤。

    • 常见 JavaScript 虚拟机

     

    • [Chakra](http://en.wikipedia.org/wiki/Chakra_(JScript_engine))(Microsoft Internet Explorer)
    • Nitro/JavaScript Core (Safari)
    • Carakan (Opera)
    • SpiderMonkey (Firefox)
    • [V8](http://en.wikipedia.org/wiki/V8_(JavaScript_engine)) (Chrome, Chromium)

    2. 一般的网页加载流程

    • 浏览器一边下载 HTML 网页,一边开始解析。也就是说,不等到下载完,就开始解析。
    • 解析过程中,浏览器发现 <script> 元素,就暂停解析,把网页渲染的控制权转交给 JavaScript 引擎。

    原因是 JavaScript 代码可以修改 DOM,所以必须把控制权让给它,否则会导致复杂的线程竞赛的问题。

    如果外部脚本加载时间很长(一直无法完成下载),那么浏览器就会一直等待脚本下载完成,造成网页长时间失去响应,浏览器就会呈现“假死”状态,这被称为“阻塞效应”。

    • 如果 <script> 元素引用了外部脚本,就下载该脚本再执行,否则就直接执行代码。
    • JavaScript 引擎执行完毕,控制权交还渲染引擎,恢复往下解析 HTML 网页

    此外,对于来自同一个域名的资源,比如脚本文件、样式表文件、图片文件等,浏览器一般有限制,同时最多下载6~20个资源

    即最多同时打开的 TCP 连接有限制,这是为了防止对服务器造成太大压力

    如果是来自不同域名的资源,就没有这个限制。所以,通常把 静态文件 放在 不同的域名之下,以加快下载速度

    2. 解决“阻塞效应” ,而 defer、async 关键字的 <script>,都不应该使用 document.write
    <script src="a.js" defer></script>
    <script src="b.js" defer></script>

    defer 属性 的运行流程如下:

    浏览器开始解析 HTML 网页。
    解析过程中,发现带有 defer 属性的 <script> 元素。
    浏览器继续往下解析 HTML 网页,同时并行下载 <script> 元素加载的外部脚本。
    浏览器完成解析 HTML 网页,此时再回过头执行已经下载完成的脚本。

    优点:

    有了defer属性,浏览器下载脚本文件的时候,不会阻塞页面渲染。

    下载的脚本文件在 DOMContentLoaded 事件触发前执行(即刚刚读取完</html>标签),

    而且可以保证执行顺序就是它们在页面上出现的顺序

     

    <script src="a.js" async></script>
    <script src="b.js" async></script>

    使用另一个进程下载脚本,下载时不会阻塞渲染

     

    浏览器开始解析 HTML 网页。
    解析过程中,发现带有 async 属性的 script 标签。
    浏览器继续往下解析 HTML 网页,同时并行下载 <script> 标签中的外部脚本。
    脚本下载完成,浏览器暂停解析 HTML 网页,开始执行下载的脚本。
    脚本执行完毕,浏览器恢复解析 HTML 网页。

     

    一旦采用这个属性,就无法保证脚本的执行顺序。

    哪个脚本先下载结束,就先执行那个脚本

     

    --------小尾巴 ________一个人欣赏-最后一朵颜色的消逝-忠诚于我的是·一颗叫做野的心.决不受人奴役.怒火中生的那一刻·终将结束...
  • 相关阅读:
    字符串匹配算法 【微软面试100题 第三十三题】
    交换元素,使两数组之和的差最小 【微软面试100题 第三十二题】
    在从1到n的正数中1出现的次数 【微软面试100题 第三十题】
    栈的push、pop序列 【微软面试100题 第二十九题】
    整数的二进制表示中1的个数 【微软面试100题 第二十八题】
    跳台阶问题 【微软面试100题 第二十七题】
    左旋转字符串 【微软面试100题 第二十六题】
    字符串中找出最长的数字串 【微软面试100题 第二十五题】
    合并链表 【微软面试100题 第二十四题】
    计算圆形是否和正方形相交 【微软面试100题 第二十三题】
  • 原文地址:https://www.cnblogs.com/tianxiaxuange/p/10150326.html
Copyright © 2011-2022 走看看