Maison > Article > interface Web > L'impact de JS, CSS et img sur les compétences DOMContentLoaded event_javascript
前端的纯技术就是对规范的认知
什么是DOMContentLoaded事件?
首先想到的是查看W3C的HTML5规范,DOMContentLoaded事件在什么时候触发:
Une fois que l'agent utilisateur arrête d'analyser le document, l'agent utilisateur doit exécuter les étapes suivantes :
1. Définissez la préparation actuelle du document sur « interactif » et le point d'insertion sur non défini.
Retirez tous les nœuds de la pile d'éléments ouverts.
2. Si la liste des scripts qui s'exécuteront une fois l'analyse du document terminée n'est pas vide, exécutez ces sous-étapes :
2.1 Faites tourner la boucle d'événements jusqu'à ce que le premier script de la liste des scripts qui s'exécuteront lorsque le document aura terminé l'analyse ait son indicateur « prêt à être exécuté par l'analyseur » défini et que le document de l'analyseur n'ait pas de feuille de style qui bloque les scripts.
2.2 Exécutez le premier script de la liste des scripts qui s'exécuteront lorsque l'analyse du document sera terminée.
2.3 Supprimez le premier élément de script de la liste des scripts qui s'exécuteront une fois l'analyse du document terminée (c'est-à-dire décalez la première entrée de la liste).
2.4 Si la liste des scripts qui s'exécuteront une fois l'analyse du document terminée n'est toujours pas vide, répétez à nouveau ces sous-étapes à partir de la sous-étape 1.
3. Mettez en file d'attente une tâche pour déclencher un événement simple qui fait des bulles nommé DOMContentLoaded au niveau du document.
规范总是那么的晦涩,但至少有一点是可以明确了的,就是在JS(不包括动态插入的JS)执行完之后,才会触发DOMContentLoaded事件。
接下来看看MDN上有关DOMContentLoaded事件的文档:
L'événement DOMContentLoaded est déclenché lorsque le document a été complètement chargé et analysé, sans attendre la fin du chargement des feuilles de style, des Limpact de JS, CSS et img sur les compétences DOMContentLoaded event_javascripts et des sous-cadres
Remarque : La feuille de style charge l'exécution du script de bloc, donc si vous avez un<font face="NSimsun"><script></script></font>
après un<font face="NSimsun"><link rel="stylesheet" ...></font>
, la page ne terminera pas l'analyse – et DOMContentLoaded ne se déclenchera pas – tant que la feuille de style n'est pas chargée.
这么看来,至少可以得出这么一个理论:DOMContentLoaded事件本身不会等待CSS文件、图片、iframe加载完成。
它的触发时机是:加载完页面,解析完所有标签(不包括执行CSS et JS),并如规范中所说的设置 <font face="NSimsun">interactive</font>
和执行每个静态的script标签中的JS,然后触发。
Les fichiers JS, les fichiers CSS et les CSS.于它前面的CSS计算出来的样式。
实践是检验真理的唯一标准
实验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="L'impact de JS, CSS et img sur les compétences DOMContentLoaded event_javascript" > </body> </html>
图一
如果页面中没有script标签,DOMContentLoaded事件并没有等待CSS文件、图片加载完成。
Chrome开发者工具的Timeline面板可以帮我们记录下浏览器的一举一动. Il s'agit de DOMContentLoaded, et de la fonction de chargement en premier. peinture, survolez les conseils类的对吧!)。
实验2:DOMContentLoaded事件需要等待JS执行完才触发
index.html :
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title></title> <script type="text/javascript"> console.timeStamp('Inline script before link in head'); window.addEventListener('DOMContentLoaded', function(){ console.timeStamp('DOMContentLoaded event'); }); </script> <link rel="stylesheet" type="text/css" href="./css/main.css" rel="external nofollow" rel="external nofollow" > <script type="text/javascript"> console.timeStamp('Inline script after link in head'); </script> </head> <body> <p>Content</p> <img src="./img/chrome-girl.jpg" alt="L'impact de JS, CSS et img sur les compétences DOMContentLoaded event_javascript" > <script type="text/javascript" src="./js/main.js"></script> </body> </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="L'impact de JS, CSS et img sur les compétences DOMContentLoaded event_javascript" > <script type="text/javascript" src="./js/main.js"></script> </body> </html>
Il est très surprenant que dans une page avec JS mais pas de CSS, img puisse effectivement commencer à décoder et dessiner (paint) immédiatement après avoir reçu les données. En d'autres termes, JS ne bloque pas l'affichage d'img ! Ceci est différent de notre compréhension précédente du concept traditionnel selon lequel JS bloquerait les ressources img. Il semble que Chrome ait apporté de nouvelles optimisations pour le chargement et l'affichage de img.
La méthode $(document).ready() que nous utilisons couramment dans jQuery consiste à surveiller l'événement DOMContentLoaded (bien sûr, elle fournit également une solution de rétrogradation en interne en simulant l'événement DOMContentLoaded et en surveillant l'événement onload). Il est généralement recommandé d'enregistrer les événements pour les éléments DOM lorsque l'événement DOMContentLoaded est déclenché. Ainsi, déclencher l'événement DOMContentLoaded le plus tôt possible signifie que la page peut être rendue interactive au plus vite :
Réduisez la taille des fichiers CSS, divisez un seul fichier CSS en plusieurs fichiers pour un chargement parallèle et réduisez le temps de blocage du CSS sur JS
Les fichiers JS secondaires sont chargés en insérant dynamiquement des balises de script (les balises de script insérées dynamiquement ne bloquent pas le déclenchement de l'événement DOMContentLoaded)
Les sprites utilisés en CSS peuvent être chargés avec le fichier CSS en HTML en préchargeant img
Pendant l'expérience, j'ai senti que le panneau Chronologie des outils de développement Chrome était très puissant et que chaque mouvement du navigateur était enregistré. Dans le passé, si nous voulions comprendre et explorer le comportement interne du navigateur dans le développement front-end, nous faisions soit des tests en boîte noire en palpant les pierres, soit nous étudiions le code source du navigateur avec deux fois plus de résultats et la moitié de l'effort. Le seul moyen efficace était d'apprendre de l'expérience de recherche des autres et d'examiner l'expérience de recherche des étrangers, mais le développement des navigateurs évolue chaque jour (par exemple, le JS trouvé dans cette expérience ne bloque pas l'affichage de img). ), l'expérience des autres n'est jamais la plus récente et la plus appropriée. La clé est de combiner vos propres scénarios d'entreprise et de demande, et de prendre des décisions ciblées. Analyse et optimisation.
PS.
L'environnement de test ci-dessus est Windows/Chrome et Fiddler est utilisé pour simuler un réseau lent