フロントエンドの高度な技術は、范の認識です
何は DOMContentLoaded イベントですか?
最初に考えられたのは、W3C の HTML5 の評価、DOMContentLoaded イベントの時点での気候トリガー:
ユーザー エージェントがドキュメントの解析を停止したら、ユーザー エージェントは次の手順を実行する必要があります。
1. 現在のドキュメントの準備状態を「対話型」に設定し、挿入ポイントを未定義に設定します。
開いている要素のスタックからすべてのノードをポップします。
2. ドキュメントの解析が完了したときに実行されるスクリプトのリストが空でない場合は、次のサブステップを実行します。
2.1 ドキュメントの解析が完了したときに実行されるスクリプトのリストの最初のスクリプトに「パーサー実行準備完了」フラグが設定され、パーサーのドキュメントにスクリプトをブロックするスタイル シートがなくなるまで、イベント ループをスピンします。
2.2 ドキュメントの解析が完了したときに実行されるスクリプトのリストの最初のスクリプトを実行します。
2.3 ドキュメントの解析が完了したときに実行されるスクリプトのリストから最初のスクリプト要素を削除します (つまり、リストの最初のエントリをシフトアウトします)。
2.4 ドキュメントの解析が終了したときに実行されるスクリプトのリストがまだ空でない場合は、サブステップ 1 からこれらのサブステップをもう一度繰り返します。
3. タスクをキューに入れて、ドキュメントで DOMContentLoaded という名前の単純なイベントを発生させます。
状況は常にそのようなものですが、少なくとも明らかなように、JS (自動挿入された JS を除く) の実行が完了すると、DOMContentLoaded イベントが起動されます。
次下見看MDN 上に DOMContentLoaded イベントの文があります:
DOMContentLoaded イベントは、スタイルシート、画像、サブフレームの読み込みが完了するのを待たずに、ドキュメントが完全に読み込まれて解析されたときに発生しますこれを考慮すると、少なくとも次の処理手順が得られます。DOMContentLoaded イベント自体は、CSS ファイル、画像、iframe の追加が完了するのを待ちません。 トリガー タイム マシンは、次のとおりです。 面のロードが完了し、すべてのスクリプト (CSS と JS の実行を除く) が解析され、規定にあるように注: スタイルシートはブロック スクリプト実行をロードするため、
の後に<font face="NSimsun"><script></script></font>
がある場合、スタイルシートがロードされるまで、ページの解析は終了せず、DOMContentLoaded も起動されません。<font face="NSimsun"><link rel="stylesheet" ...></font>
が設定され、各静的なスクリプト スクリプトが実行され、その後トリガーされます。 🎜>
一方、JS の実行は、JS が先頭にある CSS の計算式に依存する可能性があるため、(外部接続の場合は) 先頭にある CSS の追加を待って実行を完了する必要があります。
实慣は检验真理の唯一の基準<font face="NSimsun">interactive</font>
手順 1:DOMContentLoaded イベントが直接待機していない CSS 文件、画像の追加が完了しました
index.html:
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title></title> <link rel="stylesheet" type="text/css" href="./css/main.css" rel="external nofollow" rel="external nofollow" > </head> <body> <p>Content</p> <img src="./img/chrome-girl.jpg" alt="DOMContentLoadedのevent_javascriptスキルに対するJS、CSS、imgの影響" > </body> </html>
ページ内にスクリプトが存在せず、DOMContentLoaded イベントも待機中の CSS ファイルも存在しない場合、画像の追加は完了します。
实验2:DOMContentLoaded イベント必要等待ちJS実行完才触発
index.html:
main.js:
console.timeStamp('External script after link in body');
图二
如果页面中静态的写有script标签,DOMContentLoaded事件需要等待JS执行完才触发。
而script标签中的JS需要等待位于其前面的CSS的加载完成。
console.timeStamp() 可以向Timeline中添加一条记录,并对应上方的一条黄线。
从图二中可以看出,在CSS之前的JS立刻得到了执行,而在CSS之后的JS,需要等待CSS加载完后才执行,比较明显的是main.js早就加载完了,但还是要等main.css加载完才能执行。而DOMContentLoaded事件,则是在JS执行完后才触发。滑动Timeline面板中表示展示区域的滑块,如图三,放大后即可看到表示DOMContentLoaded事件的蓝线(之前跟黄线和绿线靠的太近了),当然,通过 console.timeStamp() 向TimeLine中添加的记录也可证明其触发时间。
图三
现代浏览器会并发的预加载CSS, JS,也就是一开始就并发的请求这些资源,但是,执行CSS和JS的顺序还是按原来的依赖顺序(JS的执行要等待位于其前面的CSS和JS加载、执行完)。先加载完成的资源,如果其依赖还没加载、执行完,就只能等着。
实验3:img何时开始解码、绘制?
从图三中我们可以发现一个有趣的地方:img的请求老早就发出了,但延迟了一段时间才开始解码。如图二、图三中的红框所示,截图中只框出了一部分表示解码的记录,而实际上这些表示解码的记录一直持续到img加载结束,如图四所示,img是一边加载一边解码的:
图三
现代浏览器会并发的预加载CSS, JS,也就是一开始就并发的请求这些资源,但是,执行CSS和JS的顺序还是按原来的依赖顺序(JS的执行要等待位于其前面的CSS和JS加载、执行完)。先加载完成的资源,如果其依赖还没加载、执行完,就只能等着。
实验3:img何时开始解码、绘制?
从图三中我们可以发现一个有趣的地方:img的请求老早就发出了,但延迟了一段时间才开始解码。如图二、图三中的红框所示,截图中只框出了一部分表示解码的记录,而实际上这些表示解码的记录一直持续到img加载结束,如图四所示,img是一边加载一边解码的:
图四
抱着“猜想——验证”的想法,我猜想这是因为img这个资源是否需要展现出来,需要等 所有的JS和CSS的执行完 才知道,因为main.js可能会执行某些DOM操作,比如删除这个img元素,或者修改其src属性,而CSS可能会将其 <font face="NSimsun">display: none</font>
。
图五
图六
图七
图五中没有JS和CSS,img的数据一接收到就马上开始解码了。
图六中没有JS,但img要等到CSS加载完才开始解码。
图七的代码跟图六的代码唯一的区别是CSS把img给 <font face="NSimsun">display: none;</font>
,这使得img虽然请求了,但根本没有进行解码。
这说明,img是否需要解码、绘图(paint)出来,确实需要等CSS加载、执行完才能知道。也就是说,CSS会阻塞img的展现!那么JS呢?
图八
图八对应的代码:
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title></title> <script type="text/javascript"> console.timeStamp('Inline script in head'); window.addEventListener('DOMContentLoaded', function(){ console.timeStamp('DOMContentLoaded event'); }); </script> </head> <body> <p>Content</p> <img src="./img/chrome-girl.jpg" alt="DOMContentLoadedのevent_javascriptスキルに対するJS、CSS、imgの影響" > <script type="text/javascript" src="./js/main.js"></script> </body> </html>
JS はあるが CSS がないページでは、img が実際にデータを受け取った直後にデコードと描画 (ペイント) を開始できることは非常に驚くべきことです。つまり、JS は img の表示をブロックしません。これは、JS が img リソースをブロックするという従来の概念とは異なります。Chrome は img の読み込みと表示に関して新たな最適化を行っているようです。
私たちが一般的に使用する jQuery の $(document).ready() メソッドは、DOMContentLoaded イベントを監視するものです (もちろん、DOMContentLoaded イベントをシミュレートし、onload イベントを監視することで、内部的にダウングレード ソリューションも提供します)。一般に、DOMContentLoaded イベントがトリガーされたときに DOM 要素のイベントを登録することをお勧めします。したがって、できるだけ早く DOMContentLoaded イベントをトリガーすると、ページをできるだけ早くインタラクティブにできることになります。
CSS ファイルのサイズを削減し、並列読み込みのために 1 つの CSS ファイルを複数のファイルに分割し、JS 上の CSS のブロック時間を短縮します
セカンダリ JS ファイルは、スクリプト タグを動的に挿入することによってロードされます (動的に挿入されたスクリプト タグは、DOMContentLoaded イベントのトリガーをブロックしません)
CSS で使用されるスプライトは、img
をプリロードすることで、CSS ファイルと一緒に HTML に読み込むことができます実験中に感じたのは、Chrome デベロッパー ツールのタイムライン パネルが非常に強力で、ブラウザのあらゆる動きが記録されるということです。以前は、フロントエンド開発でブラウザの内部動作を理解して調査したい場合、石を触ってブラック ボックス テストを行うか、結果を 2 倍、労力を半分にしてブラウザのソース コードを調査するかのどちらかでした。他の人の研究経験から学び、外国人の研究経験を参考にするのが唯一の効率的な方法でしたが、ブラウザの開発は日々変化しています(例えば、今回の実験で見つかったJSはimgの表示をブロックしません)。 )、他の人の経験は決して最新で最も適切なものではありません。重要なのは、自分のビジネスと需要のシナリオを組み合わせて、的を絞った意思決定を行うことです。分析と最適化です。
追記
上記のテスト環境は Windows/Chrome であり、遅いネットワークをシミュレートするために Fiddler が使用されています