Optimierung der Frontend-Leistung von Websites: JavaScript und CSS

Optimierung der Frontend-Leistung von Websites: JavaScript und CSS

Ich habe einen Artikel des Yahoo-Teams über die Optimierung der Website-Leistung gelesen. Der Artikel wurde etwa 2010 geschrieben. Obwohl er schon etwas älter ist, ist er in vielerlei Hinsicht immer noch sehr lehrreich. In Bezug auf die Leistungsoptimierung von CSS erwähnte er die folgenden Punkte:

CSS-Leistungsoptimierung

1. Platzieren Sie das Stylesheet ganz oben

Das Platzieren des Stylesheets im <head /> des Dokuments scheint das Herunterladen der Seite zu beschleunigen. Dies liegt daran, dass das Platzieren des Stylesheets im <head /> dazu führt, dass die Seite schrittweise geladen und angezeigt wird.

Leistungsorientierte Front-End-Server möchten oft, dass Seiten in einer geordneten Reihenfolge geladen werden. Gleichzeitig hoffen wir auch, dass der Browser die empfangenen Inhalte bestmöglich darstellt. Dies ist besonders wichtig für Seiten mit mehr Inhalt und für Benutzer mit langsameren Verbindungen. Die Rückgabe visueller Rückmeldungen an den Benutzer, beispielsweise in Form eines Fortschrittszeigers, wurde gut erforscht und dokumentiert. In unserer Forschung ist die HTML-Seite der Prozesszeiger. Wenn der Browser den Dateikopf, die Navigationsleiste, das obere Logo usw. ordnungsgemäß lädt, kann dies als visuelles Feedback für Benutzer dienen, die auf das Laden der Seite warten. Dies verbessert das Benutzererlebnis insgesamt.

Das Problem beim Einfügen des Stylesheets am Ende des Dokuments besteht darin, dass dadurch die ordnungsgemäße Darstellung des Inhalts in vielen Browsern, einschließlich Internet Explorer, gestört wird. Der Browser unterbricht das Rendern, um ein Neuzeichnen der Seitenelemente aufgrund von Stiländerungen zu vermeiden. Der Benutzer wird mit einer leeren Seite konfrontiert.

In der HTML-Spezifikation wird eindeutig festgelegt, dass Stylesheets im Abschnitt <head /> der Seite platziert werden müssen: „Im Gegensatz zu <a /> kann <link /> nur im Abschnitt <head /> eines Dokuments erscheinen, obwohl es mehrfach verwendet werden kann.“ Es lohnt sich nicht, es auszuprobieren, unabhängig davon, ob dadurch ein weißer Bildschirm oder unformatierter Inhalt angezeigt wird. Die beste Lösung besteht darin, Ihr Stylesheet gemäß der HTML-Spezifikation im <head /> des Dokuments zu laden.

2. Vermeiden Sie die Verwendung von CSS-Ausdrücken

Das Problem mit Ausdrücken ist, dass sie häufiger ausgewertet werden, als wir denken. Nicht nur beim Anzeigen und Zoomen der Seite, sondern auch beim Scrollen der Seite oder sogar bei Bewegungen der Maus muss eine Neuberechnung erfolgen. Durch Hinzufügen eines Zählers zu einem CSS-Ausdruck können Sie verfolgen, wie oft der Ausdruck ausgewertet wird. Allein durch Bewegen der Maus über die Seite können leicht über 10.000 Berechnungen erreicht werden.

Eine Möglichkeit, die Anzahl der Berechnungen von CSS-Ausdrücken zu reduzieren, besteht darin, einen einmaligen Ausdruck zu verwenden, der das Ergebnis bei der ersten Ausführung der angegebenen Stileigenschaft zuweist und diese Eigenschaft anstelle des CSS-Ausdrucks verwendet. Wenn Stileigenschaften während des Seitenlebenszyklus dynamisch geändert werden müssen, ist die Verwendung von Ereignishandlern anstelle von CSS-Ausdrücken ein praktikabler Ansatz. Wenn Sie CSS-Ausdrücke verwenden müssen, denken Sie daran, dass diese tausende Male ausgewertet werden und sich auf die Leistung Ihrer Seite auswirken können.

3. Verwenden Sie externes JavaScript und CSS

Viele Leistungsregeln betreffen den Umgang mit externen Dateien. Bevor Sie diese Schritte ausführen, sollten Sie sich jedoch eine grundlegendere Frage stellen: Sollten JavaScript und CSS in externen Dateien oder auf der Seite selbst platziert werden?

In der Praxis kann die Verwendung externer Dateien die Seitengeschwindigkeit verbessern, da sowohl JavaScript- als auch CSS-Dateien im Browser zwischengespeichert werden können. In HTML-Dokumenten eingebettetes JavaScript und CSS werden bei jeder Anforderung zusammen mit dem HTML-Dokument erneut heruntergeladen. Dadurch verringert sich zwar die Anzahl der HTTP-Anfragen, die Größe des HTML-Dokuments erhöht sich jedoch. Wenn andererseits JavaScript und CSS in externen Dateien vom Browser zwischengespeichert werden, kann die Größe des HTML-Dokuments reduziert werden, ohne die Anzahl der HTTP-Anfragen zu erhöhen.

Der entscheidende Punkt ist, dass die Häufigkeit, mit der externe JavaScript- und CSS-Dateien zwischengespeichert werden, mit der Anzahl der Anforderungen an das HTML-Dokument zusammenhängt. Auch wenn es etwas schwierig ist, gibt es dennoch einige Indikatoren, mit denen es gemessen werden kann. Wenn ein Benutzer während einer Sitzung mehrere Seiten Ihrer Site durchsucht und auf allen Seiten dieselben Skripts und Stylesheets wiederverwendet werden, ist das Zwischenspeichern externer Dateien von größerem Nutzen.

Für Homepages mit viel Verkehr gibt es eine Technik, mit der die durch integrierten Code bedingte Reduzierung der HTTP-Anfragen mit den Vorteilen des Caching durch die Verwendung externer Dateien in Einklang gebracht werden kann. Eine davon besteht darin, JavaScript und CSS in die Homepage einzubetten, externe Dateien aber nach dem Download der Seite dynamisch herunterzuladen. Wenn diese Dateien in den Unterseiten verwendet werden, wurden sie bereits im Browser zwischengespeichert.

4. Reduzieren Sie JavaScript und CSS

Unter Minimierung versteht man die Reduzierung der Dateigröße durch das Entfernen unnötiger Zeichen aus dem Code, wodurch die Downloadzeit verkürzt wird. Beim Minimieren des Codes sollten alle Kommentare, unnötigen Leerzeichen (Leerzeichen, Zeilenumbrüche, Tabulatoreinzüge) usw. entfernt werden. In JavaScript wird die Reaktionszeit verkürzt, da die Größe der herunterzuladenden Datei kleiner wird. Die beiden am häufigsten verwendeten Tools zum Minimieren von JavaScript sind JSMin und YUI Compressor. YUI Compressor kann auch zum Minimieren von CSS verwendet werden. Die Adresse meines vorherigen Artikels zur Front-End-Bereitstellung und zum Ant+YUI Compressor lautet: http://www.haorooms.com/post/ant_yuicom Dort wird auch die Verwendung von Ant im Gadget beschrieben: http://www.haorooms.com/tools/ant_book/

Eine weitere Methode, die zur Quellcode-Optimierung eingesetzt werden kann, ist die Verschleierung. Dieser Ansatz ist komplexer als die Vereinfachung und neigt eher zu Problemen während des Verschleierungsprozesses. Eine Umfrage unter den zehn größten Websites in den USA ergab, dass die ursprüngliche Codegröße durch Rationalisierung um 21 % reduziert werden kann, während durch Verschleierung eine Reduzierung um 25 % möglich ist. Obwohl sich Code durch Verschleierung besser verkleinern lässt, ist die Minimierung bei JavaScript weniger riskant.

Zusätzlich zum Minimieren externer Skript- und Stylesheetdateien können und sollten auch <script>- und <style>-Codeblöcke minimiert werden. Selbst wenn Sie Ihre Skripte und Stylesheets mit GZIP komprimieren, können Sie durch das Minimieren dieser Dateien immer noch mehr als 5 % Speicherplatz sparen. Da JavaScript und CSS immer leistungsfähiger und größer werden, ist eine Reduzierung des Codes von Vorteil.

5. Verwenden Sie anstelle von @import

In der vorherigen Best Practice wurde erwähnt, dass CSS oben platziert werden sollte, um ein geordnetes Laden und eine geordnete Präsentation zu ermöglichen.

Im Internet Explorer hat @import am unteren Seitenrand die gleiche Wirkung wie <link> und sollte daher besser nicht verwendet werden.

6. Vermeiden Sie die Verwendung von Filtern

Die IE-spezifische Eigenschaft AlphaImageLoader wird verwendet, um den halbtransparenten Effekt von PNG-Bildern zu korrigieren, die in Versionen unter 7.0 angezeigt werden. Das Problem mit diesem Filter besteht darin, dass er die Darstellung des Inhalts stoppt und den Browser einfriert, während er das Bild lädt. Die Berechnung erfolgt einmal für jedes Element (nicht nur für Bilder), was den Speicherbedarf erhöht und somit vielschichtige Probleme mit sich bringt.

Die beste Möglichkeit, die Verwendung von AlphaImageLoader vollständig zu vermeiden, besteht darin, stattdessen das PNG8-Format zu verwenden, das im Internet Explorer gut funktioniert. Wenn Sie AlphaImageLoader wirklich verwenden müssen, deaktivieren Sie es mit dem Underscore_filter für Benutzer von IE7 und höher.

JavaScript-Leistungsoptimierung

1. Platzieren Sie das Skript am unteren Ende der Seite

Das Problem mit dem Skript besteht darin, dass es den parallelen Download der Seite verhindert. Die HTTP/1.1-Spezifikation empfiehlt, dass Browser nicht mehr als zwei Elemente pro Hostnamen parallel herunterladen. Wenn Ihre Bilder auf mehreren Hostnamen gehostet werden, können Sie bei jedem parallelen Download mehr als zwei Dateien gleichzeitig herunterladen. Beim Herunterladen eines Skripts lädt der Browser jedoch nicht gleichzeitig andere Dateien herunter, selbst wenn der Hostname ein anderer ist.

In manchen Fällen ist es nicht einfach, das Skript an das Ende der Seite zu verschieben. Wenn das Skript beispielsweise document.write verwendet, um Seiteninhalte einzufügen, kann es nicht nach unten verschoben werden. Auch hier kann es zu Umfangsproblemen kommen. In vielen Fällen werden wir auf dieses Problem stoßen.

Eine häufig genutzte Alternative ist die Verwendung eines Verzögerungsskripts. Das DEFER-Attribut gibt an, dass das Skript kein document.write enthält, wodurch der Browser angewiesen wird, mit der Anzeige fortzufahren. Leider unterstützt Firefox das DEFER-Attribut nicht. Im Internet Explorer kann es zu Verzögerungen bei der Ausführung von Skripts kommen, die Wirkung entspricht jedoch möglicherweise nicht den Erwartungen. Wenn das Skript verzögert werden kann, kann es an das Ende der Seite verschoben werden. Dadurch wird Ihre Seite schneller geladen.

2. Verwenden Sie externes JavaScript und CSS

Wie oben, es ist in CSS geschrieben. Ich habe das CDN in meinem vorherigen Artikel aufgelistet, das extern aufgerufen werden kann.

3. Reduzieren Sie JavaScript und CSS

Wie oben, in CSS geschrieben

4. Eliminieren Sie doppelte Skripte

Das wiederholte Verweisen auf JavaScript-Dateien auf derselben Seite beeinträchtigt die Leistung der Seite. Sie denken vielleicht, dass dies kein alltägliches Vorkommnis ist. Eine Untersuchung unter den zehn wichtigsten Websites in den USA ergab, dass zwei von ihnen über doppelte Skripte verfügten. Es gibt zwei Hauptfaktoren, die zu dem seltsamen Phänomen beitragen, dass ein Skript wiederholt referenziert wird: die Teamgröße und die Anzahl der Skripte. In diesem Fall führen doppelte Skripte zu unnötigen HTTP-Anfragen und nutzlosen JavaScript-Berechnungen, was die Leistung der Website verringert.

Im Internet Explorer werden unnötige HTTP-Anfragen gestellt, im Firefox jedoch nicht. Wenn im Internet Explorer zweimal auf ein Skript verwiesen wird und es nicht zwischengespeichert werden kann, generiert es während des Seitenladevorgangs zwei HTTP-Anfragen. Auch wenn Skripte zwischengespeichert werden können, werden zusätzliche HTTP-Anfragen gestellt, wenn der Benutzer die Seite neu lädt.

Abgesehen davon, dass zusätzliche HTTP-Anfragen gestellt werden, ist durch die mehrmalige Ausführung des Skripts Zeitverschwendung verbunden. Sowohl Internet Explorer als auch Firefox haben das Problem, JavaScript neu auszuwerten, unabhängig davon, ob das Skript zwischengespeichert werden kann oder nicht.

Eine Möglichkeit, versehentliche zweimalige Referenzierung desselben Skripts zu vermeiden, besteht darin, mithilfe des Skriptverwaltungsmoduls auf das Skript in der Vorlage zu verweisen. Die gebräuchlichste Methode zum Verweisen auf ein Skript in einer HTML-Seite ist die Verwendung des Tags <script />:

 <script type="text/javascript" src="menu_1.0.17.js"></script>

In PHP können Sie stattdessen eine Methode namens insertScript erstellen:

 <?php insertScript("menu.js") ?>

Um mehrere Skriptverweise zu verhindern, sollte diese Methode auch andere Mechanismen zur Verarbeitung von Skripten verwenden, z. B. das Überprüfen des Verzeichnisses, zu dem sie gehören, und das Hinzufügen einer Versionsnummer zum Skriptdateinamen zur Verwendung im Expire-Dateiheader.

5. Reduzieren Sie den DOM-Zugriff

Der Zugriff auf DOM-Elemente mit JavaScript ist langsam. Um mehr von der Seite zu erhalten, sollten Sie daher Folgendes tun:

Besuchte zugehörige Elemente im Cache speichern

Aktualisieren Sie Knoten offline, bevor Sie sie zum Dokumentbaum hinzufügen.

Vermeiden Sie die Verwendung von JavaScript zum Ändern des Seitenlayouts

6. Entwickeln Sie intelligente Eventhandler

Manchmal haben wir möglicherweise das Gefühl, dass die Seite nicht reagiert, weil zu viele Ereignishandler an die DOM-Baumelemente angehängt sind und diese Ereignishandler häufig ausgelöst werden. Aus diesem Grund ist die Verwendung der Ereignisdelegation ein guter Ansatz. Wenn Sie 10 Schaltflächen in einem Div haben, müssen Sie den Ereignishandler nur einmal an das Div anhängen, anstatt für jede Schaltfläche einen Handler hinzuzufügen. Wenn Ereignisse auftauchen, können Sie die Ereignisse erfassen und bestimmen, welches Ereignis gesendet wurde.

Sie müssen auch nicht auf das Auftreten des Onload-Ereignisses warten, um den DOM-Baum zu bearbeiten. Sie müssen lediglich warten, bis das Element, auf das Sie zugreifen möchten, in der Baumstruktur angezeigt wird. Sie müssen auch nicht warten, bis alle Bilder geladen sind.

Wie lädt man JS und wo platziert man JS?

Blockieren des Downloads von externem JS

Beim Herunterladen von JS blockieren alle Browser alle anderen Aktivitäten, wie das Herunterladen anderer Ressourcen, das Präsentieren von Inhalten usw. Erst nachdem JS heruntergeladen, analysiert und ausgeführt wurde, beginnt es, andere Ressourcen parallel herunterzuladen und den Inhalt anzuzeigen.

Manche Leute fragen vielleicht: Warum kann JS nicht parallel wie CSS und Bilder heruntergeladen werden? Hier müssen wir kurz das Prinzip des Browserseitenaufbaus vorstellen. Wenn der Browser das HTML-Dokument vom Server empfängt und das HTML in einen DOM-Baum im Speicher konvertiert und feststellt, dass während des Konvertierungsprozesses auf einem Knoten auf CSS oder IMAGE verwiesen wird, sendet er eine weitere Anforderung, um CSS oder Bild anzufordern, und führt dann die folgende Konvertierung weiter aus, ohne auf die Rückkehr der Anforderung zu warten. Wenn die Anforderung zurückkehrt, müssen Sie nur den zurückgegebenen Inhalt an die entsprechende Position im DOM-Baum setzen. Wenn jedoch auf JS verwiesen wird, sendet der Browser eine JS-Anfrage und wartet auf die Rückgabe der Anfrage. Da der Browser eine stabile DOM-Baumstruktur benötigt, besteht eine hohe Wahrscheinlichkeit, dass es in JS Code gibt, der die DOM-Baumstruktur direkt ändert, z. B. durch die Verwendung von document.write oder appendChild oder sogar durch direkte Verwendung von location.href zum Springen. Um zu verhindern, dass JS den DOM-Baum ändert, muss der Browser den DOM-Baum neu erstellen, damit andere Downloads und Renderings blockiert werden.

Diagramm zum Blockieren von Downloads: Die folgende Abbildung zeigt ein Zeitwasserfalldiagramm des Zugriffs auf die BlogJava-Startseite. Es ist ersichtlich, dass die ersten beiden Bilder parallel heruntergeladen werden, während die folgenden beiden JS für den Download blockiert sind (nacheinander heruntergeladen).

Blockieren von Downloads mit eingebettetem JS

Eingebettetes JS bezieht sich auf JS-Code, der direkt in das HTML-Dokument geschrieben ist. Wie oben erwähnt, blockiert das Verweisen auf externes JS nachfolgende Ressourcen-Downloads und die nachfolgende Inhaltspräsentation. Wie blockiert eingebettetes JS dies? Sehen Sie sich die folgenden beiden Codes an:

 **Code 1:** 

<div>
         <ul>
             < li > blogjava </ li >
             < li > CSDN </ li >
             < li > Haorooms-Blog </ li >
             < li > ABC </ li >
             < li > AAA </ li >
         <ul>     
     </div>
     < Skripttyp ="text/javascript" >
        // Schleife für 5 Sekunden var n = Number( new Date());
     var n2 = Zahl (neues Datum());
    während ((n2 - n) < ( 6 * 1000 )){
       n2 = Zahl (neues Datum());
     }
     </ Skript >
   <div>
         <ul>
             < li > MSN </ li >
             < li > GOOGLE </ li >
             < li > YAHOO </ li >
         <ul>     
</div>

Nach dem Ausführen werden Sie feststellen, dass in Code 1 die Seite in den ersten 5 Sekunden leer ist und nach 5 Sekunden die gesamte Seite angezeigt wird. In Code 2 werden in den ersten 5 Sekunden zuerst BlogJava, CSDN usw. und 5 Sekunden später MSN angezeigt.

Es ist ersichtlich, dass eingebettetes JS die Darstellung des gesamten Inhalts blockiert, während externes JS nur die Anzeige nachfolgender Inhalte blockiert. Beide Methoden blockieren den Download nachfolgender Ressourcen.

Das Einbetten von JS führt dazu, dass CSS das Laden blockiert

Wie kann CSS das Laden blockieren? CSS kann parallel heruntergeladen werden. Unter welchen Umständen wird das Laden blockiert? (In der Testbeobachtung wird das Laden von CSS unter IE6 blockiert. Der folgende Test wird unter Nicht-IE6 durchgeführt):

Code 1 (der Wirkung halber wurde hier ein CSS von einem fremden Server gewählt):

 < html xmlns ="http://www.w3.org/1999/xhtml" >
         <Kopf>
           <Titel> js-Test</Titel>
           < meta http-equiv ="Inhaltstyp" content ="text/html; charset=UTF-8" />  
           < Linktyp ="text/css" rel ="Stylesheet" href ="http://69.64.92.205/Css/Home3.css" />
         </ Kopf >
         < Textkörper >
             < img src ="http://www.haorooms.com/images/logo.gif" />< br />
              <img src="http://www.haorooms.com/images/csdnindex_piclogo.gif" />
         </ Körper >
</ html >

Zeit-Wasserfalldiagramm:

Code 2 (es wird nur 1 leeres Embed JS hinzugefügt):

 <Kopf>
     <Titel> js-Test</Titel>
     < meta http-equiv ="Inhaltstyp" content ="text/html; charset=UTF-8" />  
   < Linktyp ="text/css" rel ="Stylesheet" href ="http://69.64.92.205/Css/Home3.css" />
   < Skripttyp ="text/javascript" >
         Funktion a(){}
   </ Skript >
</ Kopf >
< Textkörper >
         < img src ="http://www.haorooms.com/images/logo.gif" />< br />
         <img src="http://www.haorooms.com/images/csdnindex_piclogo.gif" />
</ Körper >

Zeit-Wasserfalldiagramm:

Aus dem Zeit-Wasserfalldiagramm können wir erkennen, dass in Code 2 CSS und Bilder nicht parallel heruntergeladen werden. Stattdessen beginnt der Download der folgenden beiden Bilder, nachdem das CSS heruntergeladen wurde. Wenn auf das CSS eingebettetes JS folgt, blockiert das CSS den Download nachfolgender Ressourcen.

Manche Leute fragen sich vielleicht, warum wir nicht davon sprechen, dass das eingebettete JS die nachfolgenden Ressourcen blockiert, sondern sagen, dass CSS blockiert ist? Bedenken Sie, wir verwenden jetzt eine leere Funktion und das Parsen dieser leeren Funktion dauert nur 1 ms, während der Download der nächsten beiden Bilder erst 1,3 s nach dem Download des CSS beginnt. Sie können auch versuchen, JS vor CSS einzubetten, dann kommt es zu keiner Blockierung.

Grundursache: Da der Browser die Reihenfolge von CSS und JS in HTML beibehält, muss das Stylesheet geladen und analysiert werden, bevor das eingebettete JS ausgeführt wird. Das eingebettete JS blockiert das nachfolgende Laden der Ressource, sodass die oben beschriebene Situation auftritt, in der CSS den Download blockiert.

Wo soll eingebettetes JS platziert werden?

1. Platzieren Sie es ganz unten. Dadurch werden zwar alle Präsentationen blockiert, das Herunterladen von Ressourcen wird jedoch nicht blockiert.
2. Wenn Sie JS in den Kopf einbetten, platzieren Sie das eingebettete JS bitte vor CSS.
3. Verwenden Sie „defer“
4. Rufen Sie keine Funktionen auf, deren Ausführung in eingebettetem JS lange dauert. Wenn Sie sie verwenden müssen, können Sie setTimeout verwenden, um sie aufzurufen. Ich habe in einem früheren Artikel über settimeout geschrieben, siehe: https://www.jb51.net/article/20741.htm

<<:  Regenbogen-Button-Stil erstellt mit CSS3

>>:  Detaillierte Erklärung des Unterschieds zwischen var, let und const in JavaScript

Artikel empfehlen

MySQL5.6.31 winx64.zip Installations- und Konfigurationstutorial

#1. Herunterladen # #2. Entpacken Sie die Datei l...

Zusammenfassung der MySQL-Anweisungen

Inhaltsverzeichnis 1. Datenbank USE auswählen 2. ...

Vue implementiert Login-Sprung

In diesem Artikelbeispiel wird der spezifische Co...

Vue verwendet Echart, um Beschriftungen und Farben anzupassen

In diesem Artikelbeispiel wird der spezifische Co...

So verwenden Sie CSS-Attributselektoren zum Spleißen von HTML-DNA

CSS-Attributselektoren sind großartig. Sie können...

JavaScript-Simulationsrechner

In diesem Artikel wird der spezifische Code des J...

Lösen Sie das Problem, dass Docker Pull zurückgesetzt wird

In diesem Artikel wird beschrieben, wie Sie das P...

Detailliertes Tutorial zur Installation von Anaconda3 auf Ubuntu 18.04

Anaconda bezeichnet eine Open-Source-Python-Distr...