CSS と JS が DOM の解析とレンダリングをどのようにブロックするかについて話しましょう

青灯夜游
リリース: 2021-05-27 09:58:16
転載
2740 人が閲覧しました

この記事では、CSS と JS が DOM の解析とレンダリングをブロックする原理を紹介します。一定の参考値があるので、困っている友達が参考になれば幸いです。

CSS と JS が DOM の解析とレンダリングをどのようにブロックするかについて話しましょう

#こんにちは~ 読者の皆様、こんにちは。誰もが聞いたことがあると思いますが、CSS を先頭に、JS を最後に配置すると、ページのパフォーマンスが向上します。しかし、なぜでしょうか?検討しましたか?ずっと前から知ってたけど、なぜかわからなかった、もちろん試験のために暗記するのはいいけど、実際に応用するとめちゃくちゃになってしまう。そこで、洗い(王)、心(陽)、皮(ブ)、顔(ラオ)を洗い、最近の結果をまとめます。

この記事は主に初心者向けです。結論を直接確認したい場合は、一番下までスクロールしてください~


ファイルの読み取りに関連しているため、それは確かです。サーバーが必要な場合は、すべてのファイルを github に置き、star を付けてください。そうすれば満足します。

node説明する必要があるのはこの関数だけです:

function sleep(time) {
  return new Promise(function(res) {
    setTimeout(() => {
      res()
    }, time);
  })
}
ログイン後にコピー

うーん!実際、遅れています。 CSS または JS ファイル名に sleep3000 などのプレフィックスが付いている場合は、ファイルが 3000 ミリ秒の遅延後に返されることを意味します。

以下で使用する HTML ファイルは次のようになります:

    <!DOCTYPE html>
    <html>
    <head>
     <meta charset="UTF-8">
     <title>Title</title>
     <style>
     div {
     width: 100px;
     height: 100px;
     background: lightgreen;
     }
     </style>
    </head>
    <body>
     <div></div>
    </body>
    </html>
ログイン後にコピー

それに別の JSCSS## を挿入します。

プレフィックスの有無に関係なく、使用される

common.css の内容は次のとおりです:

div {
  background: lightblue;
}
ログイン後にコピー

わかりました。特に言うことはありません。始めましょう。テキスト!

CSS

CSS については、先頭のパフォーマンスに <link> タグが配置されていることを誰もが知っている必要があります。少し高くなりますが、<script><link> が同時に先頭にある場合、<script> が先頭にあることを知っている人は少なくなります。 が一番上にある可能性があります。どうしてこれなの? CSSDOM に与える影響を見てみましょう。

CSSDOM

注意!ここで話しているのは DOM の解析です。証明例は次のとおりです。最初に <script defer src="/js/logDiv.js"></script># を挿入します。ヘッダーの ## 、JS ファイルの内容は次のとおりです:

const div = document.querySelector(&#39;div&#39;);
console.log(div);
ログイン後にコピー

defer 属性 誰もがよく知っていると思いますが、MDNこれの説明は、ドキュメントの解析が完了した後、DOMContentLoaded イベントがトリガーされる前に、ブラウザー スクリプトが実行されることを通知するためです。このプロパティを設定すると、DOM が解析された直後に div が確実に出力されます。

次に、

HTML ファイルの任意の位置に挿入します。ブラウザを開くと、DOM ノード div が最初に出力され、約 3 秒後に水色の div がレンダリングされることがわかります。これは、CSSDOM の解析をブロックしないことを証明しています。CSS のダウンロードには 3 秒かかりますが、ブラウザはこのプロセス中に愚かに待機しません。CSSダウンロード後、DOM が解析されます。

ここで簡単に説明すると、ブラウザは

DOM を解析して DOM Tree を生成し、CSS を結合して CSS Tree# を生成します。 ## 、最後に render Tree を形成し、ページをレンダリングします。このプロセスでは CSSDOM Tree に影響を与えないことがわかります。そのため、DOM の解析をブロックする必要はありません。ただし、DOM TreeCSS Treerender Tree に結合されるため、CSS はページのレンダリングをブロックしますか?

CSS ページ レンダリングのブロック実際、この例では、

CSS

がブロックしない場合にこの点を説明しました。ページがレンダリングをブロックすると、ブラウザは CSS ファイルがダウンロードされる前に薄緑色の div を表示し、その後水色に変わります。ブラウザのこの戦略は実際には非常に賢明です。この戦略がなければ、ページは最初は元の外観を表示し、CSS がダウンロードされた後、その外観が突然変わることを想像してください。ユーザーエクスペリエンスは非常に悪く、レンダリングにはコストがかかります。 したがって、パフォーマンスとユーザー エクスペリエンスを考慮して、ブラウザーはレンダリングの数を減らそうとするため、

CSS

は当然ページのレンダリングをブロックします。 ただし、状況は常に奇妙です。この例を見てください。

HTML

ヘッダー構造は次のとおりです: <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:js;toolbar:false;">&lt;header&gt; &lt;link rel=&quot;stylesheet&quot; href=&quot;/css/sleep3000-common.css&quot;&gt; &lt;script src=&quot;/js/logDiv.js&quot;&gt;&lt;/script&gt; &lt;/header&gt;</pre><div class="contentsignin">ログイン後にコピー</div></div>しかし、これがどのような結果を生み出すか考えてください。

答案是浏览器会转圈圈三秒,但此过程中不会打印任何东西,之后呈现出一个浅蓝色的div,再打印出null。结果好像是CSS不单阻塞了页面渲染,还阻塞了DOM 的解析啊!稍等,在你打算掀桌子疯狂吐槽我之前,请先思考一下是什么阻塞了DOM 的解析,刚才已经证明了CSS是不会阻塞的,那么阻塞了页面解析其实是JS!但明明JS的代码如此简单,肯定不会阻塞这么久,那就是JS在等待CSS的下载,这是为什么呢?

仔细思考一下,其实这样做是有道理的,如果脚本的内容是获取元素的样式,宽高等CSS控制的属性,浏览器是需要计算的,也就是依赖于CSS。浏览器也无法感知脚本内容到底是什么,为避免样式获取,因而只好等前面所有的样式下载完后,再执行JS。因而造成了之前例子的情况。

所以,看官大人明白为何<script><link>同时在头部的话,<script>在上可能会更好了么?之所以是可能,是因为如果<link>的内容下载更快的话,是没影响的,但反过来的话,JS就要等待了,然而这些等待的时间是完全不必要的。

JS

JS,也就是<script>标签,估计大家都很熟悉了,不就是阻塞DOM解析和渲染么。然而,其中其实还是有一点细节可以考究一下的,我们一起来好好看看。

JS 阻塞 DOM 解析

首先我们需要一个新的JS文件名为blok.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(&#39;div&#39;);
console.log(div);
ログイン後にコピー

其实那个数组操作时没意义的,只是为了让这个JS文件多花执行时间而已。之后把这个文件插入头部,浏览器跑一下。

结果估计大家也能想象得到,浏览器转圈圈一会,这过程中不会有任何东西出现。之后打印出null,再出现一个浅绿色的div。现象就足以说明JS 阻塞 DOM 解析了。其实原因也很好理解,浏览器并不知道脚本的内容是什么,如果先行解析下面的DOM,万一脚本内全删了后面的DOM,浏览器就白干活了。更别谈丧心病狂的document.write。浏览器无法预估里面的内容,那就干脆全部停住,等脚本执行完再干活就好了。

对此的优化其实也很显而易见,具体分为两类。如果JS文件体积太大,同时你确定没必要阻塞DOM解析的话,不妨按需要加上defer或者async属性,此时脚本下载的过程中是不会阻塞DOM解析的。

而如果是文件执行时间太长,不妨分拆一下代码,不用立即执行的代码,可以使用一下以前的黑科技:setTimeout()。当然,现代的浏览器很聪明,它会“偷看”之后的DOM内容,碰到如<link><script><img>等标签时,它会帮助我们先行下载里面的资源,不会傻等到解析到那里时才下载。

浏览器遇到 <script> 标签时,会触发页面渲染

这个细节可能不少看官大人并不清楚,其实这才是解释上面为何JS执行会等待CSS下载的原因。先上例子,HTMLbody的结构如下:

<body>
	<div></div>
	<script src="/js/sleep3000-logDiv.js"></script>
	<style>
		div {
			background: lightgrey;
		}
	</style>
	<script src="/js/sleep5000-logDiv.js"></script>
	<link rel="stylesheet" href="/css/common.css">
</body>
ログイン後にコピー

这个例子也是很极端的例子,但不妨碍它透露给我们很多重要的信息。想象一下,页面会怎样呢?

答案是先浅绿色,再浅灰色,最后浅蓝色。由此可见,每次碰到<script>标签时,浏览器都会渲染一次页面。这是基于同样的理由,浏览器不知道脚本的内容,因而碰到脚本时,只好先渲染页面,确保脚本能获取到最新的DOM元素信息,尽管脚本可能不需要这些信息。

小结

综上所述,我们得出这样的结论:

  • CSSDOM の解析をブロックしませんが、DOM のレンダリングをブロックします。
  • JS DOM の解析をブロックしますが、ブラウザは DOM を「覗き見」し、関連リソースを事前にダウンロードします。
  • ブラウザが <script> を持ち、defer または async 属性を持たないタグを検出すると、ページのレンダリングがトリガーされます。前の CSSリソースがロードされていない場合、ブラウザはリソースがロードされるのを待ってからスクリプトを実行します。

これで、<script> を一番下に配置するのが最適であり、<link> を配置するのが最適である理由がわかりました。 <script><link> がある場合、# に <script> を入れるのが最善です。 ##<link>上ですか?

これを読んでくれてありがとう。この記事があなたのお役に立てば幸いです。異なる意見やより良い意見がある場合は、お気軽に教えてください。ありがとうございます~

元のアドレス: https://juejin.cn/post/6844903497599549453

プログラミング関連の知識の詳細については、こちらをご覧ください:

プログラミング ビデオ###! !

以上がCSS と JS が DOM の解析とレンダリングをどのようにブロックするかについて話しましょうの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:juejin.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート