Heim >Web-Frontend >js-Tutorial >Nicht blockierende Lösung zur Optimierung der Ladeleistung in JavaScript_Javascript-Kenntnissen

Nicht blockierende Lösung zur Optimierung der Ladeleistung in JavaScript_Javascript-Kenntnissen

WBOY
WBOYOriginal
2016-05-16 16:34:371309Durchsuche

Die Leistung von Javascript im Browser kann als das wichtigste Usability-Problem angesehen werden, mit dem Frontend-Entwickler konfrontiert sind.

Eine der Yslow-23-Regeln von Yahoo besteht darin, JS ganz unten zu platzieren. Der Grund dafür ist, dass die meisten Browser tatsächlich einen einzigen Prozess verwenden, um mehrere Aufgaben wie die Benutzeroberfläche und die Aktualisierung von Javascript zu erledigen, und jeweils nur eine Aufgabe ausgeführt werden kann. Wie lange das Javascript ausgeführt wird und wie lange es dann wartet, bis der Browser inaktiv wird, um auf Benutzerinteraktionen zu reagieren.

Grundsätzlich bedeutet dies, dass das Vorhandensein des <script>-Tags dazu führt, dass die gesamte Seite darauf wartet, dass das Skript analysiert und ausgeführt wird. Unabhängig davon, ob der eigentliche JavaScript-Code inline ist oder in einer unabhängigen externen Datei enthalten ist, muss der Seiten-Download- und Parsing-Prozess angehalten und gewartet werden, bis das Skript diese Verarbeitung abgeschlossen hat, bevor fortgefahren werden kann. Dies ist ein wesentlicher Teil des Seitenlebenszyklus, da Skripte den Seiteninhalt während der Ausführung ändern können. Ein typisches Beispiel ist die Funktion document.write(), zum Beispiel: <br> </p> <div class="codetitle"> <span><a style="CURSOR: pointer" data="5199" class="copybut" id="copybut5199" onclick="doCopy('code5199')"><u>Code kopieren</u></a></span> Der Code lautet wie folgt:</div> <div class="codebody" id="code5199"> <br> <html><br> <Kopf><br> <title>Skriptbeispiel</title><br> </head> <br> <body><br> <p><br>             <script type="text/javascript"><br>                  document.write("Das Datum ist " (new Date()).toDateString());<br>                                                                                               </p><br> </body> </html><br> <br><br> Wenn der Browser auf ein <script>-Tag stößt, wie in der HTML-Seite oben, gibt es keine Möglichkeit vorherzusagen, ob JavaScript Inhalte in das <p>-Tag einfügt. Daher stoppt der Browser, führt diesen JavaScript-Code aus und fährt dann mit dem Parsen und Übersetzen der Seite fort. Das Gleiche passiert, wenn JavaScript mithilfe des src-Attributs geladen wird. Der Browser muss zunächst den Code für die externe Datei herunterladen, was einige Zeit in Anspruch nimmt, und dann den Code analysieren und ausführen. Während dieses Vorgangs werden das Parsen der Seite und die Benutzerinteraktion vollständig blockiert. <br> </div>Da Skripte den Downloadvorgang anderer Seitenressourcen blockieren, empfiehlt es sich, alle <script>-Tags so nah wie möglich am Ende des <body>-Tags zu platzieren, um die Auswirkungen auf den Download der gesamten Seite zu minimieren Seite. Zum Beispiel: <br> <p><br></p> <div class="codetitle">Code kopieren<span><a style="CURSOR: pointer" data="96913" class="copybut" id="copybut96913" onclick="doCopy('code96913')"><u> Der Code lautet wie folgt:</u></a></span> <html></div> <Kopf><div class="codebody" id="code96913"> <title>Skriptbeispiel</title><br> <link rel="stylesheet" type="text/css" href="styles.css" <br> </head><br> <br> <body><br> <p>Hallo Welt!</p><br> <-- Beispiel für die empfohlene Skriptpositionierung -->           <script type="text/javascript" src="file1.js"></script>                    




Dieser Code zeigt die empfohlene Position des <script>-Tags in der HTML-Datei. Obwohl sich die Skript-Downloads gegenseitig blockieren, wurde die Seite heruntergeladen und vor dem Benutzer angezeigt, und die Geschwindigkeit beim Aufrufen der Seite wird nicht zu langsam sein. Dies ist, was oben über die Platzierung von JS ganz unten erwähnt wurde. <br> <br>Darüber hinaus erstellt Yahoo! ein „Union Handle“ für seine „Yahoo! User Interface (YUI)“-Bibliothek, das über sein „Content Delivery Network (CDN)“ implementiert wird. Jede Website kann eine „Union Handle“-URL verwenden, um anzugeben, welche Dateien im YUI-Paket enthalten sind. Die folgende URL enthält beispielsweise zwei Dateien: <br> <br> </div> <p>Code kopieren</p> <p><br> Der Code lautet wie folgt:</p> <div class="codetitle"> <div class="codebody" id="code74887"> <br> <script type="text/javascript" src="http://yui.yahooapis.com/combo?2.7.0/build/yahoo/yahoo-min.js&2.7.0/build/event/event-min.js "></script>

Diese URL ruft die Version 2.7.0 der Dateien yahoo-min.js und event-min.js auf. Bei diesen Dateien handelt es sich um zwei separate Dateien auf dem Server. Wenn der Server jedoch diese URL-Anfrage empfängt, werden die beiden Dateien zusammengeführt und an den Client zurückgegeben. Auf diese Weise sind keine zwei <script>-Tags erforderlich (jedes lädt eine Datei) und ein <script>-Tag kann sie laden. Dies ist die beste Möglichkeit, mehrere externe Javascripts in eine HTML-Seite einzubinden. </p> <p><strong>Noblocking Scripts Non-blocking Scripts</strong></p> <p>Das Obige ist die beste Möglichkeit, mehrere Javascript-Skripte im Anfangszustand der Seite zu laden. Javascript neigt dazu, bestimmte Browserprozesse zu blockieren, wie z. B. HTTP-Anfragen und Schnittstellenaktualisierungen, was das größte Leistungsproblem für Entwickler darstellt. JavaScript-Dateien kurz zu halten und die Anzahl der HTTP-Anfragen zu begrenzen, sind nur die ersten Schritte bei der Erstellung responsiver Webanwendungen. </p> <p>Bei großen Webseiten mit viel JS-Code ist es jedoch nicht immer die beste Wahl, den Quellcode kurz zu halten. Daher sind nicht blockierende Skripte entstanden. Wir müssen der Seite nach und nach Javascript hinzufügen, ohne den Browser in gewissem Maße zu blockieren. </p> <p>Der Schlüssel, um das Skript nicht zu blockieren, besteht darin, mit dem Laden des Javascript-Quellcodes zu warten, bis die Seite vollständig geladen ist. Dies bedeutet, dass mit dem Herunterladen des Codes begonnen wird, nachdem das Ladeereignis des Fensters ausgegeben wurde. </p> <p>Zugehörige Erklärung: </p> <p>Das Ladeereignis des Fensters wird nur einmal und nur einmal nach dem Laden der Seite ausgelöst. <br> window.onload=function(){} muss warten, bis der gesamte Inhalt der Webseite geladen ist (einschließlich aller zugehörigen Dateien des Elements, z. B. Bilder), bevor es ausgeführt werden kann. Das heißt, Javascript kann nur auf jedes Element zugreifen die Seite zu diesem Zeitpunkt. </p> <p>Mehrere Methoden sind wie folgt: </p> <p><strong>Verzögerte Skripte Verzögerte Skripte</strong></p> <p>Html4 definiert ein erweitertes Attribut für das <script>-Tag: defer. </p> <p>Dieses Defer-Attribut gibt an, dass das im Element enthaltene Skript nicht dazu gedacht ist, das DOM zu ändern, sodass der Code später ausgeführt werden kann. Das Defer-Attribut wird nur von Internet Explorer 4 und Firefox 3.5 unterstützt und ist daher keine ideale browserübergreifende Lösung. In anderen Browsern wird das Defer-Attribut ignoriert. Daher wird das <script>-Tag auf die normale Standardweise verarbeitet, was zu einer Blockierung führt. Auch wenn dies von allen gängigen Browsern unterstützt wird, ist dies immer noch eine effektive Lösung. <br> </p> <div class="codetitle"> <span><a style="CURSOR: pointer" data="14408" class="copybut" id="copybut14408" onclick="doCopy('code14408')"><u>Code kopieren</u></a></span> Der Code lautet wie folgt:</div> <div class="codebody" id="code14408"> <br> <script type="text/javascript" src="file1.js" defer></script>

Ein <script>-Tag mit einem Defer-Attribut kann an einer beliebigen Stelle im Dokument platziert werden und startet den Download, während es analysiert wird, bis das DOM geladen wird (bevor der Onload-Ereignishandler aufgerufen wird). Wenn eine verzögerte Javascript-Datei heruntergeladen wird, blockiert sie keine andere Verarbeitung durch den Browser, sodass die Dateien parallel zu anderen Ressourcen heruntergeladen werden können. </p> <p>Mit dem folgenden Code können Sie testen, ob der Browser das Defer-Attribut unterstützt: <br> </p> <div class="codetitle"> <span><a style="CURSOR: pointer" data="95845" class="copybut" id="copybut95845" onclick="doCopy('code95845')"><u>Code kopieren</u></a></span> Der Code lautet wie folgt:</div> <div class="codebody" id="code95845"> <br> <html><br> <Kopf><br> <title>Beispiel für eine Skriptverzögerung</title><br> </head> <br> <body><br> <script defer> warning("defer");</script> <script> Alert("script"); </script> <script> window.onload = function(){ alarm("load");} </script>
;



Wenn der Browser die Verzögerung nicht unterstützt, ist die Reihenfolge der Popup-Dialogfelder „Verzögern“, „Skript“ und „Laden“.

Wenn der Browser die Verzögerung unterstützt, ist die Reihenfolge der Popup-Dialogfelder „Skript“, „Laden“, „Verzögern“.

Dynamische Skriptelemente Dynamische Skriptelemente

DOM ermöglicht es uns, fast alle Dokumentinhalte dynamisch in HTML zu erstellen. Ein neues <script> kann sehr einfach über das Standard-DOM erstellt werden: <strong> </strong></p> <p></p> <p>Code kopieren</p> <div class="codetitle"> <span><a style="CURSOR: pointer" data="78091" class="copybut" id="copybut78091" onclick="doCopy('code78091')"> Der Code lautet wie folgt:<u></u></a> 1 var script = document.createElement ("script");</span> 2 script.type = "text/javascript";</div> 3 script.src = "file1.js"; 4 document.body.appendChild(script);<div class="codebody" id="code78091"> <br> <p>Das neue <script>-Element lädt die Quelldatei file1.js. Der Download dieser Datei beginnt, sobald das Element zur Seite hinzugefügt wird. Der entscheidende Punkt dieser Technologie besteht darin, dass die Datei unabhängig davon, wo der Download gestartet wird, heruntergeladen und ausgeführt wird, ohne andere Seitenverarbeitungen zu blockieren. </p> <p>Wenn eine Datei mithilfe eines dynamischen Skriptknotens heruntergeladen wird, wird der zurückgegebene Code normalerweise sofort ausgeführt (mit Ausnahme von Firefox und Opera, die darauf warten, dass alle vorherigen dynamischen Skriptknoten die Ausführung abschließen). </p> <p>In den meisten Fällen hoffen wir, eine Funktion zum dynamischen Herunterladen von Javascript-Dateien aufrufen zu können. Das folgende Funktionspaket implementiert die Standardimplementierung und IE-Implementierung: </p> <p></p> <div class="codetitle"> <span><a style="CURSOR: pointer" data="4795" class="copybut" id="copybut4795" onclick="doCopy('code4795')"><u>Code kopieren</u></a></span> Der Code lautet wie folgt:</div> <div class="codebody" id="code4795"> <br> Funktion LoadScript(URL, Callback){<br> var script = document.createElement ("script") ;<br> ​ script.type = "text/javascript";<br>        <br> If (script.readyState){ //IE<br>            script.onreadystatechange = function(){<br> If (script.readyState == "loaded" || script.readyState == "complete"){<br>               script.onreadystatechange = null;<br>               callback(); <br>            }<br>         };<br>         } <br>         else { //Andere<br>           script.onload = function(){ callback();<br> }; <br> }<br> Script.src = url;<br> Document.getElementsByTagName("head")[0].appendChild(script); <br> }<br> <br> LoadScript("file1.js", function(){ //Aufruf<br> alarm("Datei wird geladen!"); <br> });<br> </div> <p>Diese Funktion akzeptiert zwei Parameter: die URL der Javascript-Datei und eine Rückruffunktion, die ausgelöst wird, wenn der Javascript-Empfang abgeschlossen ist. Mithilfe einer Objektbesichtigung wird entschieden, welche Ereignisse überwacht werden sollen. Der letzte Schritt ist das src-Attribut und das Hinzufügen der Javascript-Datei zum Head. </p> <p>Dynamisches Laden von Skripten ist der am häufigsten verwendete Modus für nicht blockierende Javascript-Downloads, da er browserübergreifend funktioniert und einfach und benutzerfreundlich ist. </p> <p><strong>XMLHttpRequest-Skriptinjektion XHR-Skriptinjektion</strong></p> <p>Eine andere Möglichkeit, Skripte auf nicht blockierende Weise abzurufen, besteht darin, ein XMLHttpRequest (XHR)-Objekt zu verwenden, um das Skript in die Seite einzufügen. Diese Technik erstellt zunächst ein XHR-Objekt, lädt dann die Javascript-Datei herunter und verwendet dann ein dynamisches <script>-Element, um den Javascript-Code in die Seite einzufügen. Sehen Sie sich die Demo an: </p> <p></p> <div class="codetitle"> <span><a style="CURSOR: pointer" data="24685" class="copybut" id="copybut24685" onclick="doCopy('code24685')"><u>Code kopieren</u></a></span> Der Code lautet wie folgt:</div> <div class="codebody" id="code24685"> <br> var xhr = new XMLHttpRequest(); xhr.open("get", "file1.js", true); xhr.onreadystatechange = function(){<br> If (xhr.readyState == 4){<br> If (xhr.status >= 200 && xhr.status < 300 || xhr.status == 304){ // HTTP-Statuscode prüfen <br>         var script = document.createElement("script");           script.type = "text/javascript";<br>            script.text = xhr.responseText;<br>              document.body.appendChild(script);<br>          } <br> }<br> }; <br> xhr.send(null);<br> <br> <p>Dieser Code sendet eine Dateiabrufanforderung an den Server, um file1.js abzurufen. Der Ereignishandler onreadystatechange prüft, ob readyState 4 ist, und prüft dann, ob der HTTP-Statuscode gültig ist (200 zeigt an, dass die Clientanforderung erfolgreich war, 2xx zeigt eine gültige Antwort an und 304 zeigt eine zwischengespeicherte Antwort an). Wenn eine gültige Antwort empfangen wird, wird ein neues <script>-Element erstellt und sein Textattribut wird auf die vom Server empfangene Antworttextzeichenfolge gesetzt. Dadurch wird tatsächlich ein <script>-Element mit Inline-Code erstellt, und sobald das neue <script>-Element zum Dokument hinzugefügt wird, wird der Code ausgeführt und kann verwendet werden. </p> <p>Der Vorteil dieser Methode besteht darin, dass sie eine gute Kompatibilität aufweist und Sie Javascript-Code herunterladen können, der nicht sofort ausgeführt wird. Da der Code außerhalb des <script>-Tags zurückgegeben wird, wird er nach dem Herunterladen nicht automatisch ausgeführt, sodass Sie die Ausführung verzögern können. </p> <p>Die Bestimmung dieser Methode unterliegt der gleichen Ursprungsbeschränkung des Browsers. Die Javascript-Datei muss in derselben Domäne wie die Seite platziert werden und kann nicht vom CDN (Content Delivery Network) heruntergeladen werden. Aus diesem Grund nutzen große Webseiten in der Regel nicht die XHR-Script-Injection-Technologie. </p> <p><strong>Empfohlenes nicht blockierendes Muster Empfohlenes nicht blockierendes Muster</strong></p> <p>Die empfohlene Methode zum Laden großer Mengen Javascript in eine Seite ist ein zweistufiger Prozess: </p> <p>Der erste Schritt umfasst den Code, der zum dynamischen Laden von Javascript erforderlich ist, und lädt dann die anderen Teile als Javascript, die für die Seiteninitialisierung erforderlich sind. Dieser Teil des Codes sollte so klein wie möglich sein und darf nur die Funktion „loadScript()“ enthalten. Er wird sehr schnell heruntergeladen und ausgeführt und verursacht keine großen Störungen auf der Seite. </p> <p>Wenn der erste Code im zweiten Schritt fertig ist, verwenden Sie ihn, um den Rest des Javascript zu laden. </p> <p>Zum Beispiel: <br> </p> <div class="codetitle"> <span><a style="CURSOR: pointer" data="91573" class="copybut" id="copybut91573" onclick="doCopy('code91573')"><u>Code kopieren</u></a></span> Der Code lautet wie folgt:</div> <div class="codebody" id="code91573"> <br> 1 <script type="text/javascript" src="loader.js"><br> 2 </script>


Platzieren Sie diesen Code vor dem schließenden Tag von body . Dies hat den Vorteil, dass zunächst einmal sichergestellt wird, dass die Ausführung von Javascript die Anzeige anderer Teile anderer Seiten nicht beeinträchtigt. Zweitens wurde beim Herunterladen des zweiten Teils der Javascript-Datei das gesamte für die Anwendung erforderliche DOM erstellt und kann abgerufen werden, sodass keine zusätzliche Ereignisverarbeitung (z. B. window.onload) erforderlich ist, um festzustellen, ob die Seite vorhanden ist bereit. .

Eine weitere Möglichkeit besteht darin, die Funktion „loadScript()“ direkt in die Seite einzubetten, was den Overhead einer http-Anfrage reduzieren kann. Zum Beispiel:

Code kopieren Der Code lautet wie folgt:

1


Sobald der Seiteninitialisierungscode heruntergeladen ist, können Sie auch die Funktion „loadScript()“ verwenden, um zusätzliche Funktionen zu laden, die für die Seite erforderlich sind.

Mit der Einführung eines gemeinsamen Tools hat Ryan Grove von Yahoo! Search die LazyLoad-Bibliothek erstellt (siehe:

http://github.com/rgrove/lazyload/

). LazyLoad ist eine leistungsstarke LoadScript()-Funktion. LazyLoad ist nach der Minimierung nur etwa 1,5 KB groß. Anwendungsbeispiele sind wie folgt:

Code kopieren Der Code lautet wie folgt:



Zusammenfassung

1. Platzieren Sie alle