zoukankan      html  css  js  c++  java
  • 浏览器渲染——html页面外联script会阻塞页面渲染吗?

    注:测试浏览器为chrome浏览器

    我们先来看第一段代码:

    <!DOCTYPE html>
    <html>
        <head>
            <meta charset="utf-8" />
            <meta name="viewport" content="width=device-width, initial-scale=1">
            <title>测试</title>
        </head>
        <body>
            <h1>Hello</h1>
            <script type="text/javascript">
                let i = 1000000000
                while(i>0){
                    i-- 
                }
            </script>
            <h1>world</h1>
        </body>
    </html>

     我们知道js会阻塞DOM解析和渲染,所以页面肯定会在内联script里的代码执行完成之后,再渲染出来

    答案确实是这样

    分析:一开始渲染进程的HTML 解析器开始解析DOM,当解析到内联script 脚本标签时,HTML 解析器会暂停解析DOM,此时JavaScript 引擎介入,并执行内联script 标签中的这段脚本,脚本执行完成之后,HTML 解析器恢复解析过程,继续解析DOM,然后进行后续的渲染,最终将页面上同时渲染出 Hello World

    接下来,我们看第二段代码:

    index.js:

    var i = 1000000000
    while(i>0){
        i--
    }

    index.html:

    <!DOCTYPE html>
    <html>
        <head>
            <meta charset="utf-8" />
            <meta name="viewport" content="width=device-width, initial-scale=1">
            <title>测试</title>
        </head>
        <body>
            <h1>Hello</h1>
            <script type="text/javascript" src="index.js"></script>
            <h1>world</h1>
        </body>
    </html>

    那这段html代码的运行结果是不是和上面一样呢?

    刚开始我以为是,后来发现并不是这样的,谷歌浏览器做了一些优化,所以执行结果会有一些变化

    分析:当渲染引擎收到字节流之后,会开启一个预解析线程,用来分析 HTML 文件中包含的 JavaScript、CSS 等相关文件,解析到相关文件之后,预解析线程会提前下载这些文件。因为这段html代码里有外联script脚本,所以会丢到预解析线程去下载这个外联js文件,此时HTML 解析器开始解析DOM,当遇到外联script标签时,停止DOM解析,浏览器会渲染一次页面(当前的Hello会被渲染到页面上),然后执行下载完成的js文件,接着继续解析DOM,然后进行后续的渲染,最终将页面上就会渲染出 Hello World

    注意:这里是先渲染出Hello ,然后过一会儿(这个期间在执行js),再渲染出World

    答案:第一段代码和第二段代码的执行最终结果一样,但是渲染顺序不一样。第一段代码先间隔一段时间(执行js),然后Hello World会同时被渲染出来;第二段代码会先渲染出Hello,然后间隔一段时间(执行js),再渲染出World

    总结:

      虽然js都会阻塞DOM解析,但是浏览器对于内联script和外联script的渲染过程还是有一点点不同。内联js会阻塞DOM解析和渲染,直到js执行完成后,页面才会被渲染出来。外联js也会阻塞DOM解析和渲染,但是如果在外联script标签之前已经有DOM元素生成,则浏览器会优先渲染一次。我想这是因为浏览器不知道脚本的内容,因而碰到脚本时,只好先渲染页面,确保脚本能获取到最新的DOM元素信息,尽管脚本可能不需要这些信息。

    ——个人理解,如有出错,请指正——  

  • 相关阅读:
    Java 打印HelloKitty
    Android四大组件:BroadcastReceiver 介绍
    详解 Handler 消息处理机制(附自整理超全 Q&A)
    垃圾回收机制 —— 整理介绍
    四种引用类型 —— 软引用与弱引用的应用
    线程池 —— 使用介绍
    倒计时器 CountDownTimer
    屏幕旋转时 Activity 的生命周期 —— 测试与结论
    arcengine Objects in this class cannot be updated outside an edit session(不能在编辑会话之外更新此类对象)解决办法
    基于rtmp+nginx 、vlc实现FFmpeg推流与wpf端拉流
  • 原文地址:https://www.cnblogs.com/FHC1994/p/13162696.html
Copyright © 2011-2022 走看看