解释css和js是如何阻塞浏览器渲染DOM的,并提出一些优化的方案
1.CSS不会堵塞DOM解析(DOM Tree的生成)
2.CSS会堵塞页面的渲染
<!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <style>
            div {
                width: 100px;
                height: 100px;
                background: lightgreen;
            }
        </style>
        <link rel="stylesheet" href="/css/sleep3000-common.css">
    </head>
    <body>
        <div></div>
    </body>
 </html>
#1.sleep3000-common.css 会延迟3ms返回,样式就是设置div块为浅蓝色
#2.最终结果是浏览器会转圈圈三秒,之后呈现出一个浅蓝色的div,所以结果是CSS会堵塞页面的渲染。
3.JS会堵塞DOM解析
<!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <script src="/js/blok.js">
    </head>
    <body>
        <div></div>
    </body>
 </html>
#1.block.js代码如下
const arr = [];
for (let i = 0; i < 10000000; i++) {
  arr.push(i);
  arr.splice(i % 3, i % 7, i % 5);
}
const div = document.querySelector('div');
#2.最终结果浏览器转圈圈一会,这过程中不会有任何东西出现,之后打印出null。说明JS堵塞了DOM解析。
#3.如果JS文件体积太大,同时你确定没必要阻塞DOM解析的话,不妨按需要加上defer或者async属性,此时脚本下载的过程中是不会阻塞DOM解析的。
4.浏览器遇到 <script>且没有defer或async属性的标签时,会触发页面渲染。如果<script>标签前面有CSS资源,会等到CSS资源加载完毕之后再执行<script>脚本
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <link rel="stylesheet" href="/css/sleep3000-common.css">
     </head>
      <body>
            <div></div>
            <script src="/js/logDiv.js">
            <style>
                div {
                    background: lightgrey;
                }
            </style>
            <script src="/js/sleep5000-logDiv.js"></script>
            <link rel="stylesheet" href="/css/common.css">
            </body>
</html>
#答案是等待3秒浅蓝色打印div,等待5秒浅灰色打印div,最后浅蓝色。由此可见,每次碰到<script>标签时,浏览器都会渲染一次页面。这是基于同样的理由,浏览器不知道脚本的内容,因而碰到脚本时,只好先渲染页面,确保脚本能获取到最新的DOM元素信息,尽管脚本可能不需要这些信息。
5.优化方案:
<script>最好放底部,<link>最好放头部,如果头部同时有<script>与<link>的情况下,最好将<script>放在<link>上面
6.附:defer 与 async
如果我们不想<script>堵塞页面的解析,我们可以给<script>标签添加defer或者async属性。defer和async的区别主要如下:
1.执行时机不同:
    defer的脚本将在DOM解析完成后、触发 DOMContentLoaded 事件前执行
    async的脚本一旦加载完毕,就会执行(不论是在DOM解析阶段还是DOMContentLoaded之前之后,但是一定是在window.load之前执行)
2.执行顺序不同:
    defer能保证多个脚本按照书写顺序执行
    async不能保证多个脚本的执行顺序
 
                     
                    
                 
                    
                
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号