Teurer Preis für Stile. Yandex-Bericht

Das Laden von CSS auf einer Seite ist ein Blockierungsvorgang. Wenn das asynchrone Laden von JavaScript für den Benutzer möglicherweise nicht sichtbar ist, kann das langsame Auftreten von Stilen einen ungeduldigen Gast von der Site vertreiben. Wie lade ich CSS für Benutzer so effizient und nahtlos wie möglich? Nikita Dubko versucht es herauszufindenDarkMeFoDy aus der Yandex-Suchoberflächengruppe in Minsk.


- Hallo alle zusammen. Ich erzähle dir von den Stilen. Alle reden heute über TypeScript und TypeScript. Und ich werde über Cascade-Skript sprechen.

Kurz über mich. Ich bin ein belarussischer Entwickler - nach dem Film Dudya werde ich das überall sagen. Möglicherweise haben Sie meine Stimme im Web Standards-Podcast gehört, und wenn Sie Tippfehler im Web Standards-Newsfeed sehen, bin ich es wahrscheinlich auch.

Kleiner Haftungsausschluss. Der Bericht wird mehrere Wahnsinnsfälle enthalten - behandeln Sie alles, was ich sage, mit großer Kritik. Überlegen Sie, warum Sie solche Techniken verwenden können und warum Sie sie nicht benötigen. Einige Dinge werden wirklich verrückt sein. Gehen.

Wozu?


Zunächst einmal - warum überhaupt über CSS-Optimierung sprechen?

Wenn Sie in Suchmaschinen nach schnellen JS-Downloads suchen, gibt es viele Ergebnisse. Wenn Sie schnell CSS laden möchten, wird oben nicht einmal das benötigte CSS angezeigt.



Wenn Sie sich Google ansehen, gibt es 111 Millionen Ergebnisse über JS und über CSS nur 26 Millionen.

Vielleicht spielt das also keine Rolle? Warum darüber reden? Wenn Sie nach JS-Leistungsberichten suchen, werden Sie viele davon finden. Es geht um React, um alle möglichen anderen Frameworks, um Vanilla usw. Aber um CSS habe ich nur einen Bericht gefunden. Harry Roberts las 2018 einen coolen Bericht über die CSS-Leistung. Ich dachte, ich hätte einen zweiten Bericht gefundenvon Roma Dvornova, „Parsim CSS: Leistungstipps und -tricks“. Es stellte sich jedoch heraus, dass es sich um einen JS-Bericht handelt, der CSS analysiert. Nicht genau das, was wir brauchen.

Es stellt sich heraus, dass sie nicht viel über CSS nachdenken. Es ist Schande.

Aber wenn ich ins Web gehe, sehe ich normalerweise HTML. Und ich sehe auch CSS, das die Seite stilisiert. Aber ich sehe JS nicht. JS ist eine Sache, die CSS und HTML auf einer Seite verschiebt, damit alles schön aussieht. Dies ist ein Skript. Und wenn JS nicht geladen wird, ist es nicht so schlimm, als ob CSS nicht geladen wird.

Fehler in JS fallen stillschweigend in die Konsole. Und es ist unwahrscheinlich, dass der durchschnittliche Benutzer in DevTools nachschaut: "Oh, Sie haben es dort, ein Fehler in der Konsole." Wenn CSS jedoch nicht geladen wird, wird möglicherweise nicht alles angezeigt, was Sie benötigen.

Übrigens gibt es Studien darüber, dass es vor allem darum geht, einen ersten Eindruck zu hinterlassen.38% der Benutzer können die Website besuchen, und wenn sie feststellen, dass sie direkt widerlich ist, verlassen sie sie sofort. Und 88% werden es tolerieren, es einmal verwenden, und dann werden sie niemals zurückkehren und es ist unwahrscheinlich, dass sie Ihre Website beraten.

Jetzt, da wir alle zu Hause sitzen, ist der Internetverkehr besonders gewachsen. Und wir müssen darüber nachdenken, wie wir den Benutzern effizient Ressourcen bereitstellen können.

Versuchen wir, aus der Sicht von Yandex zu zählen. Wenn wir jede Yandex-Lieferung für 100 ms optimieren und beispielsweise 200 Millionen Seiten pro Tag liefern können (ich kenne die genaue Anzahl nicht), sparen wir an diesem Tag 0,1 s * 200 Millionen = 232 Personentage. Nur durch Optimierung der Ausgabe für 100 Millisekunden. Und CSS macht das auch.

Lassen Sie uns ein wenig Detectives spielen und herausfinden, wie Sie das Beste aus den Ladestilen herausholen können.

Messen!


Der allererste Rat ist, immer alles zu messen. Es macht keinen Sinn, theoretisch Optimierungen vorzunehmen. Sie können davon ausgehen, dass die Optimierung in Ihrem Fall funktioniert, aber echte Messungen zeigen, dass nichts dergleichen ist. Dies ist die wichtigste Regel jeder Optimierung. Andrei Prokopyuk vom SERP Velocity-Team auf HolyJS hat sehr gut darüber gesprochen, wie wir das machen , ich werde mich nicht wiederholen.

Welche Messinstrumente gibt es?

- Wenn Sie auf mehr oder weniger realen Geräten messen möchten, die langsam und nicht so cool sind wie Ihre, verwenden Sie WebPageTest . Normalerweise nehme ich dort Messungen vor.

- Sie haben Lighthouse, wenn Sie Chromium-basierte Browser verwenden. Er zeigt, wie lokale Messungen, ziemlich gute Dinge.

- Wenn Sie sicher sind, dass Sie alles selbst erledigen können, gehen Sie zu DevTools auf die Registerkarte Leistung. Es enthält viele Details. Sie können Ihre eigenen Metriken erstellen und analysieren.



Natürlich ist es bei der Leistung notwendig, reale Bedingungen festzulegen. Sie sitzen auf Ihrem coolen Laptop mit coolem Internet im Büro, hier ist alles fantastisch, aber sie kommen zu Ihnen und sagen: "Ich bin langsam." Und du sagst: "Alles funktioniert für mich." Nicht so.

Versuchen Sie immer zu überprüfen, wie der Benutzer unter den Bedingungen der U-Bahn oder anderswo Ihre Website nutzen wird. Dazu müssen Sie ein sehr langsames Internet einrichten. Es ist auch ratsam, die CPU zu verlangsamen, da jemand von einem Nokia 3110 zu Ihnen kommen kann. Er muss auch die Site anzeigen.

Am wichtigsten: Messung an realen Benutzern. Es gibt eine solche Metrik, genauer gesagt eine ganze Reihe von Metriken - RUM, Real User Monitoring. In diesem Fall messen Sie nicht, was synthetisch in Ihrem Code geschieht, sondern Metriken für echte Benutzer in der Produktion. Zum Beispiel vom Laden einer Seite in eine Aktion. Eine Aktion ist beispielsweise etwas, das im Browser funktioniert, oder sogar ein Klick auf ein wichtiges Element.

Denken Sie daran, dass Sie nicht für Roboter entwickeln. Sotka im Leuchtturm - es ist großartig, es ist wirklich gut. Sie erfüllen also mindestens die Anforderungen, die der Leuchtturm stellt. Es gibt jedoch echte Benutzer, und wenn der Benutzer die Seite beim Heben in Lighthouse nicht sehen kann, machen Sie etwas falsch.



Es gibt Metriken, auf die man sich konzentrieren muss. Dies ist First Contentful Paint, wenn der erste Inhalt auf Ihrer Seite angezeigt wird, mit dem Sie etwas tun können, lesen Sie. Diese Metrik wird in Chromium-Browsern gesendet. Sie können sie abrufen.



In letzter Zeit können Sie sich immer noch Largest Contentful Paint ansehen. Es kommt häufig vor, dass Sie eine Medienseite haben, und es ist beispielsweise wichtig, ein Foto darauf anzusehen. Dann brauchen Sie diese bestimmte Metrik.

CSS wird geladen


Kommen wir schließlich zu CSS, wie CSS geladen wird. Empfänge sind seit langem bekannt. Es gibt einen kritischen Renderpfad, einen kritischen Renderpfad. Es geht darum, was der Browser vom Zeitpunkt des Sendens der Anforderung für die Ressource bis zum Anzeigen der Pixel auf dem Bildschirm des Benutzers tut. Auch darüber gibt es eine Reihe von Artikeln und Berichten. Aber schauen wir uns kurz an, wie dieser Browser das macht.

<!DOCTYPE html>
<html lang="ru">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>CSS —  </title>
    <link rel="stylesheet" href="/main.ac74gsac.css">
</head>

Er beginnt HTML herunterzuladen und sieht Tags. Er analysiert sie nach und nach und versteht, was er mit ihnen anfangen soll. Ladungen. Kam über Link. Es muss verwendet werden. Aber wie? Zuerst müssen Sie es herunterladen. Das Herunterladen ist langsam. Beim Laden wird die Seite weiter analysiert.

 <!DOCTYPE html>
<html lang="ru">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>CSS —  </title>
    <link rel="stylesheet" href="/main.ac74gsac.css">
</head>
<body>
    <h1>-!</h1>
</body>
</html>

Wenn es auf einen anderen Link stößt, wird es erneut blockiert und erlaubt keine Ausführung. Blockiert JS, blockiert das Parsen. Und bis es hochfährt, tut es nichts. Aber dann geht es weiter.

<link>


Lassen Sie uns tiefer gehen - was passiert, wenn Sie auf den Link zugreifen?



Aufzeichnen, wohin wir gehen, ist Standard. Es gibt einen CSS-Stil, der irgendwo liegt. Jetzt ist es in Mode, alle statischen Daten auf das CDN zu setzen.

Wohin gehen?


Zunächst muss der Browser verstehen, wohin er gehen soll.



Er sieht die URL und muss diese URL verstehen - worum geht es? Wir sind daran gewöhnt, dass die URL eine Site-ID ist.



Aber physisch müssen wir die IP-Adresse dieser URL erhalten und unter der IP-Adresse zur realen physischen Maschine gehen.



Für Ihr CDN erhält es einen Eintrag in DNS und geht direkt an die IP-Adresse. Wie kann man in diesem Fall beschleunigen?



Eine verrückte Idee ist es, die Entfernung vom Benutzer zum DNS-Server zu verringern. Nehmen Sie den Benutzer und verpflanzen Sie ihn. Zum Beispiel, um die Meldung anzuzeigen: "Näher sitzen" oder "Näher gehen".

Sie können die IP-Adresse sofort im Link angeben. Warum müssen wir nach DNS suchen, Domains auflösen, wenn Sie das Ergebnis sofort anhand der IP-Adresse angeben können? Dies ist ein verrückter Weg, aber im Fall von globalen DDoS-DNS-Servern kann er Sie sogar retten.

Und wir können es loswerden, eine IP-Adresse zu bekommen.



Wenn Sie sich Ihrer index.html oder einer anderen Datei zuwenden, kennen Sie bereits die Domain-Adresse, an die Sie gehen. Dies ist nur dann der Fall, wenn Sie die Statik nicht in einer separaten Domain oder Subdomain speichern, sondern näher an Ihrer Domain platzieren können, nämlich an dieser Domain selbst. Dann muss DNS nicht aufgelöst werden, es ist bereits.



Wir haben herausgefunden, wohin wir gehen sollen. Aber wir können solche Dinge im Voraus für den Browser tun. Wenn Ihr Stylesheet beispielsweise viel später über den DOM-Baum geladen wird, können Sie dem Browser mithilfe von <link rel = "dns-prefetch"> mitteilen, dass "Ich gehe noch nicht dorthin, aber Sie werden die Ressourcen aufwärmen, ich werde sie definitiv später benötigen." ".

Mit diesem Eintrag weisen Sie den Browser an, diesen DNS abzurufen. Wenn der Link im Code angezeigt wird, kennt der Browser bereits die IP-Adresse dieser Domain. Sie können solche vorbereitenden Dinge tun. Das Gleiche zum Beispiel, bevor Sie die nächste Seite aufrufen, auf die Sie auf jeden Fall gehen werden.

Ok, der Browser weiß, wohin er gehen muss. Er muss verstehen, wie man geht.

Wie weitergehen


Wir beobachten das Protokoll. Jetzt ist https natürlich eine direkte Anforderung. Das Einbeziehen von Suchmaschinen markiert Ihre Websites, die nicht auf https sind, mit Formularen als nicht ganz sicher.

Ich fand eine erstaunliche Reihe von Comics über die Funktionsweise des Boards https. Aber wir sind IT-Leute, wir lieben coole komplexe Diagramme und lustige Comics sind zu einfach.



Hier habe ich in eigenen Worten formuliert, wie https funktioniert. Zuerst erhalten Sie ein SSL-Zertifikat von Ihrem Server. Anschließend müssen Sie das Zertifikat bei einer Zertifizierungsstelle überprüfen. Hierbei handelt es sich um spezielle Server, die wissen, was gültig ist und was nicht, und Browser auffordern können: "Ja, hier ist alles in Ordnung, verwenden Sie dieses Zertifikat."

Als nächstes werden die Schlüssel für die Kommunikation zwischen dem Server und dem Client generiert, verschlüsselt und mit verschiedenen Schlüsseln entschlüsselt. Der Prozess ist interessant, wenn man ihn kryptografisch betrachtet. Aber wir wollen beschleunigen. Wie?



Wir können den Benutzer wieder näher an die Server übertragen. Wir haben bereits ein DNS, jetzt können wir es näher an die Zertifizierungsstelle bringen. Und zwischen diese Server zu stellen wird perfekt sein.

Sie können https deaktivieren. Warum brauchen wir es? Wir verbringen Zeit damit, ein Zertifikat zu erhalten, zu verschlüsseln, zu entschlüsseln. Nicht wirklich. Dies ist der schädlichste Rat im Bericht. Tun Sie dies nicht. https ist der Schutz von Benutzerdaten, und http / 2 funktioniert ohne https nicht. http / 2 ist eine weitere Möglichkeit, die Geschwindigkeit zu erhöhen.



Es gibt auch die OCSP-Hefttechnologie. Sie können ein Zertifikat ohne Zertifizierungsstelle überprüfen. Dies ist wahrscheinlich näher an DevOps. Sie müssen Ihren Server auf eine bestimmte Weise konfigurieren, damit er die Antwort der Zertifizierungsstelle zwischenspeichern und dem Benutzer Folgendes ausgeben kann: "Glauben Sie mir, mein Zertifikat ist wirklich echt." Auf diese Weise können wir zumindest den Schritt speichern, in dem wir zur Zertifizierungsstelle gehen.

Aber es gibt eine Nuance - in Chrome funktioniert dies lange Zeit nicht. Für Benutzer anderer Browser können Sie diesen Vorgang jedoch beschleunigen.

Ich habe bereits zweimal gesagt, dass es notwendig ist, den Benutzer zu transplantieren, und die Idee schwebt in der Luft - um den Server näher an den Benutzer heranzuführen. Ich habe nichts Neues für dich entdeckt. Dies ist ein CDN, ein Netzwerk zur Bereitstellung verteilter Inhalte. Die Idee ist, dass Sie fertige Sidienki verwenden, unabhängig Ihre eigene Infrastruktur erstellen und eine Reihe von Servern auf der ganzen Welt installieren können, soweit es Geld und Möglichkeiten zulassen. Sie müssen den Server jedoch so einrichten, dass ein Benutzer aus Australien zu australischen Servern wechselt. Hier spielt die Lichtgeschwindigkeit auf Sie, je kleiner die Entfernung, desto schneller passieren die Elektronen sie.

Lassen Sie uns tiefer graben. Was ist sonst noch in der Anfrage los? In der Tat ist https nur ein Wrapper über http. Nicht nur eine coole Hülle. Und wenn es noch tiefer geht, ist http eine solche Anfrage der TCP / IP-Familie.



Wie werden Pakete und Bytes im Netzwerk gesendet, damit alle Browser, Clients und Server miteinander kommunizieren? Das erste, was ein Client / Server über eine TCP / IP-Verbindung tut, ist ein Handshake.

Im Jahr 2020 empfiehlt die WHO jedoch, Händedrucke zu vermeiden. Es gibt so eine coole TCP Fast Open-Technologie. Sie können zum Zeitpunkt des Handshakes die gesamte Kette „Hallo, ich bin ein Kunde“ - „Hallo, ich bin ein Server“ - „Ich glaube Ihnen“ - „Und ich glaube Ihnen. Gehen". Zu diesem Zeitpunkt können Sie bereits nützliche Daten senden. Und wenn der Handshake erfolgreich war, ist ein Teil der nützlichen Daten vergangen. Dies ist TCP Fast Open.

Was soll ich abholen?


Lassen Sie uns herausfinden, was der Client vom Server abholen soll. Die Hauptsache ist nicht, dass der Client etwas vom Server nimmt, sondern dass der Server die Daten an den Client weitergibt. Dann könnten Sie denken: User-Agent. Ich kann den User-Agent vom Client abrufen und herausfinden, bei welchem ​​Browser sich der Benutzer angemeldet hat. Finden Sie ungefähr heraus, ob es mich nicht täuscht, diesen Browser.

.example {
    display: -ms-grid;
    display: grid;
    -webkit-transition: all .5s;
    -o-transition: all .5s;
    transition: all .5s;
    -webkit-user-select: none;
       -moz-user-select: none;
        -ms-user-select: none;
            user-select: none;
    background: -webkit-gradient(linear, left top, left bottom, from(white), to(black));
    background: -o-linear-gradient(top, white, black);
    background: linear-gradient(to bottom, white, black);
}

Angenommen, er hat sich von Firefox aus angemeldet. Ich habe wie üblich eine Assembly, in der der Autoprefixer kitschig verbunden ist. Er hat eine Menge Code für mich generiert. Ja, das ist ein cooler Ansatz, bei dem alles überall funktioniert. Ich weiß aber bereits, dass sich der Benutzer von Firefox aus angemeldet hat.

Warum nicht den ganzen Überschuss ausschalten? Stimmen Sie zu, es gibt viel weniger Zeilen, wir senden weniger Bytes, das ist cool.

Wir haben eine Lite-Version von SERP, Oma. Vitaly Kharisov sprach über sievitharKlasse Bericht über Web Standards Tage. Es verwendet genau diesen Ansatz. Wir können mehrere Bundles generieren und diese auf unterschiedliche Weise an verschiedene Kunden weitergeben. Sie wiegen viel weniger, weil Firefox sein eigenes bekommt, WebKit sein eigenes bekommt und es funktioniert, es ist verifiziert.



Des Weiteren. Wir verarbeiten höchstwahrscheinlich Benutzeranfragen, wir wissen, dass die Person autorisiert ist, und verwenden einige persönliche Informationen für sie. Es ist logisch, dass wir etwas aus der Datenbank bekommen sollten. Aber nicht alles! Es gibt statische Dinge, die sich für keinen der Benutzer unterscheiden, sie sind genau gleich.

James Akvuh las einen coolen Bericht darüber„Serverseitiges Rendern. Mach es selbst". Was ist der Sinn? Sie wissen bereits, dass Sie über HTML und eine Art CSS verfügen, die für alle Benutzer gleich ist. Bevor Sie Daten abrufen, können Sie die Ausgabe aus diesen statischen Daten generieren und sofort die nützlichsten Daten in einem Stream vom Server senden. Und danach - holen Sie sich die Daten, empfangen Sie sie schnell, konvertieren Sie sie in Vorlagen und geben Sie sie dem Kunden. Und der Benutzer wird bereits etwas Nützliches sehen.



Wir haben dies vor langer Zeit umgesetzt. Wir haben auf SERP auf der Hauptsuchseite zwei Phasen - Vorsuche und Nachsuche. Vorsuche ist, wenn wir alle Teile senden, die kein Wissen darüber benötigen, welcher Benutzer sich angemeldet hat. Wir können ihm zum Beispiel schon einen Hut geben.

Das heißt, wir haben eine Suchleiste, die der Benutzer verwenden kann, bevor alles andere geladen wird. Dies ist nützlich bei einer langsamen Verbindung. Wir machen es, es funktioniert.

Und ich habe auch über http / 2 gesprochen. Dies wird von modernen Browsern vollständig unterstützt. Wenn Sie es also noch nicht auf Ihrem Server konfiguriert haben, sollten Sie zumindest herausfinden, wie Sie es konfigurieren.

Server Push ist eine coole Technologie, die besagt: „Browser, ich habe Ihnen noch nicht das Wissen vermittelt, dass Sie eine Art CSS benötigen. Aber ich weiß genau, was gebraucht wird. Also halte es, lade es vor. “





Es ist nicht schwer. Sie müssen einige Header auf dem Server konfigurieren, und alles funktioniert. Wenn der Browser diesen Titel nicht kennt, wird nichts kaputt gehen, dies ist der schönste. Lassen Sie uns noch weiter graben. TCP Wir haben bereits darüber gesprochen: Ein Handshake, Bytes werden gesendet.



Waschen Sie Ihre Hände nach einem Händedruck. In Bezug auf TCP beginnen wir jedoch, Bytes weiterzuleiten, und die Algorithmen sind so optimiert, dass der Client-Server nicht inaktiv ist.

Daher wird zuerst ein bestimmtes Datensegment gesendet. Standardmäßig (dies können Sie in den Einstellungen ändern) sind es 1460 Bytes. Der Server sendet keine Informationen zu einem Segment. Er schickt Fenster.

Das erste Fenster ist 14600 Bytes, zehn Segmente. Wenn die Verbindung gut ist, beginnt er, die Fenster zu vergrößern. Wenn die Verbindung schlecht ist, kann das Fenster verkleinert werden. Was ist wichtig zu verstehen? Es gibt das erste Fenster mit zehn Segmenten, in das Sie die gesamte Site einpassen müssen, wenn Sie möchten. Und dann gibt es eine maximale Geschwindigkeit für das Erscheinen von Inhalten. Vitaliy Kharisov las auch einen Bericht darüber . Und ja, es ist möglich, eine Site mit allem, was Sie benötigen, in ein Fenster zu integrieren, wenn Sie beispielsweise JS deaktivieren.

Eine wichtige Nuance. Wenn Sie ein ganzes Segment füllen, ist es ein Segment. Wenn Sie jedoch nur ein zusätzliches Byte senden, sendet der Server immer noch ein ganzes zusätzliches Segment.



Sie können eine coole Optimierung durchführen, die Leistung um ein ganzes Kilobyte reduzieren, aber Sie werden bei Ihren Messungen nichts sehen - vielleicht deshalb. Versuchen Sie, die Optimierung normal für mehrere Segmente durchzuführen.

Seltsam: Ich bin ein Schriftsetzer und erzähle so komplexe Server-Dinge. Kommen wir dem echten CSS noch näher.

Versenden Sie weniger


Wir senden also weniger an den Benutzer, weniger Segmente, kommen schneller, der Benutzer ist glücklich.



Minimierung. Sie war alle auf ihre Projekte eingestellt. Es gibt eine Reihe cooler Tools, Webpack-Plugins und Schluckeinstellungen - im Allgemeinen werden Sie es selbst herausfinden. Sie können es von Hand anpassen, aber es scheint nur, wenn Sie sicher sind, dass Sie Ihren CSS-Kühler als jedes andere CSSO komprimieren können.

Denken Sie daran, die Komprimierung zu aktivieren. Wenn mindestens gzip im Jahr 2020 nicht aktiviert ist, machen Sie definitiv etwas falsch, da dies eine alte Komprimierungstechnik ist. Im Allgemeinen ist es im Jahr 2020 Zeit, Brotli zu verwenden. Dies ist eine gute Möglichkeit, die Ausgabe in Chromium-Browsern geringfügig zu reduzieren. Oder wenn Sie brotli nicht unterstützen möchten, können Sie zumindest zopfli ausprobieren.

Dies ist ein ziemlich langsamer Komprimierungsalgorithmus für gzip, der einfach die besten Komprimierungsergebnisse liefert und so schnell wie normales gzip dekomprimiert. Daher muss zopfli mit Bedacht konfiguriert und nur verwendet werden, wenn Sie keine Daten im laufenden Betrieb ausgeben müssen. Sie können gzip-Archivierer so konfigurieren, dass sie während der Montage mithilfe des zopfli-Algorithmus erfasst und statisch gesendet werden, und zwar tatsächlich nicht im laufenden Betrieb. Dies kann Ihnen helfen. Messen Sie aber auch die Ergebnisse.



Alle diese Algorithmen verwenden eine Art Wörterbuch: Ein Wörterbuch basiert auf sich wiederholenden Codefragmenten. Aber manchmal sagen sie: Es ist notwendig zu inline, wenn wir inline, dann werden wir die Anfrage los. Das Verknüpfen des gesamten CSS in HTML ist sehr schnell. Der Trick ist, dass gzip etwas effizienter arbeitet, wenn Sie Stile und HTML aufschlüsseln, da die Wörterbücher unterschiedlich und effizienter sind.

In meinem Fall habe ich einfach die Bootstrap-Seite genommen, dort den Bootstrap verknüpft und die beiden Versionen verglichen. Gzip über einzelne Ressourcen ist 150 Bytes weniger. Ja, der Gewinn ist sehr gering. Auch hier müssen Sie alles messen. In Ihrem Fall kann dies beispielsweise die Anzahl der Segmente um eins verringern.

Wie optimiere ich den Code? Ich spreche nicht von Minifizierung. Nehmen Sie weg, was Sie nicht im Projekt verwenden. Höchstwahrscheinlich haben Sie Code, der niemals auf dem Client ausgeführt wird. Wozu?



Damit Sie dies automatisieren können, sind spezielle Registerkarten in den Browser integriert, z. B. in Chrome DevTools. Dies ist Coverage, das Ihnen sagt: "Ich habe dieses CSS oder dieses JS nicht verwendet, Sie können es ausschneiden."

Möglicherweise haben Sie jedoch Hover, Focus, Active und etwas, das mit JS installiert wurde. Sie müssen alle möglichen Aktionen auf der Site simulieren. Erst dann können Sie sicher sein, dass dieses CSS gekürzt werden kann. Chris Coyer hat eine gute Bewertung Artikel über automatische Tools , die mit Schwebe- und Fokus , alles zu tun versuchen. Aber er kam zu dem Schluss, dass es unmöglich war, dies zu automatisieren. Es klappt noch nicht.

Es gibt einen guten Bericht von Anton Kholkin von Booking.com, in dem auch versucht wurde, Haufen von Legacy-Code zu entfernen. Aber sie hatten eine Besonderheit: einen Legacy-Code, der aus externen Projekten stammte. Es war notwendig, es zu entfernen. Sehen Sie, auf welche interessanten Lösungen sie gestoßen sind.

Sie können selbst versuchen, mit demselben Puppenspieler zu spielen, der Chrome ähnelt. Sie können Tests durchführen, die automatisch alles durchlaufen, versuchen, den Schwebeflug auszuführen und sich zu konzentrieren. Und verwenden Sie dieselbe Abdeckung.

Mein Kollege Vitya KhomyakovVictor-HomyakovIch habe mein eigenes Skript erstellt , z. B. das Auffinden von Duplikaten und Stilen auf einer Seite. Einfach nehmen, kopieren und einfügen. Er wird Ihnen in der Konsole schreiben: "Diesen Selektor brauchen Sie anscheinend nicht." Bis zu dem Punkt, den Sie gerade in DevTools eingeben. Es ist toll.



Eine Funktion, die ich an den Tools der Firefox-Entwickler sehr mag: eine Gelegenheit, Stile zu sehen, die anscheinend verwendet werden, aber der Browser wendet sie tatsächlich nicht an.

Sie können beispielsweise display: inline festlegen, und es scheint, dass diese display: inline zum Festlegen von Größen nicht sinnvoll ist. Oder vertikal ausgerichtet, funktioniert es nur für Inline- oder Tabellenzellen. Bisher habe ich nur in Firefox gesehen, dass es hervorheben kann: "Sie brauchen diese Zeile nicht."

Auch hier müssen Sie vorsichtig sein: Vielleicht verwenden Sie diesen Stil, um die Klasse später einzufügen. Aber meiner Meinung nach eine coole Funktion.

Stellen Sie sich jetzt die Frage: Benötigen Sie den gesamten Bootstrap für das Projekt? Platzieren Sie ein beliebiges CSS-Framework, das Sie anstelle von Bootstrap verwenden. Höchstwahrscheinlich verwenden Sie Bootstrap für Raster und mehr oder weniger häufig verwendete Elemente, und die Hälfte von Bootstrap benötigen Sie nicht.

Versuchen Sie, die Baugruppe richtig zu verwenden. In fast allen modernen CSS-Frameworks können Sie Quellcode für die Assemblierung verwenden und nur das auswählen, was Sie benötigen. Dies kann die Größe des CSS-Bundles drastisch reduzieren.

Nicht unbenutzt verschenken. Anstatt nach meinem Vermächtnis zu suchen, können Sie das Verständnis auf Build-Ebene verwenden, dass diese Seite dieses CSS nicht verwendet.

Mit einem vollständigen BEM-Stapel können Sie beispielsweise die Baugruppe erstellen, sodass Sie, wenn Sie die Seite bereits angeben, einen Baum aller Komponenten der BEM-Blöcke erstellen können, die sich auf der Seite befinden. Mit BEM können Sie feststellen, dass dieses CSS nicht geladen werden muss, wenn sich dieser Block nicht auf der Seite befindet. Versenden Sie nur das Notwendige.

Sogar die Leute von Google sagen : Verwenden Sie BEM, es kann Ihnen wirklich bei der Optimierung helfen.

Ich glaube nicht, dass ich es laut ausspreche, aber in diesem Fall scheint CSS-in-JS ein guter Ansatz zu sein. Wenn Sie unabhängige unabhängige Komponenten schreiben und die Assembly sorgfältig konfigurieren oder zur Laufzeit bestimmen, welche Blöcke verwendet werden und welche nicht, können Sie das Problem der Suche nach einem Legacy-Code beseitigen, indem Sie diesen Code einfach nicht an den Client senden. Klingt einfach, aber Disziplin ist erforderlich. Denken Sie zu Beginn des Projekts im Voraus darüber nach.



Welche andere Option gibt es? Ein bisschen verrückt. In diesem Code scheint der Stil nicht benötigt zu werden, da wir ein div verwenden - der Standardwert ist bereits display: block. Und lassen Sie uns alle Standardeinstellungen löschen? Wenn Sie in Ihrem Projekt sicher sind, dass sich das HTML-Markup nie wieder ändert, gehen Sie die Standardwerte durch, die der Browser bereits bereitstellt, und entfernen Sie sie.

Weniger Styles - großartig! Aber das ist wieder eine verrückte Idee. CSS muss sich nicht mit HTML auskennen, da es sich um einen Stil handelt. Es ist ziemlich unabhängig, Sie müssen es mit einem anderen Projekt verbinden, es sollte dort funktionieren. Und ja, es ist schwer zu pflegen. Ändern Sie das Tag - alles bricht. Verrückte Idee wie versprochen.

Verwenden Sie Variablen. CSS hat sehr alte Variablen wie currentColor.



Oft gibt es ein Muster: Sie möchten beispielsweise eine Schaltfläche erstellen, deren Text und Rand farblich gleich sind. Und durch Schweben ändern wir beide. Wozu?



Es gibt eine currentColor-Variable, die einen Wert aus der Farbe übernimmt. Sie platzieren ihn beispielsweise am Rand, stellen diese Eigenschaft als Proxy dar und ändern nur eine Zeile durch Bewegen des Mauszeigers, durch Fokussieren, durch Aktivieren, was auch immer Sie möchten. Dies scheint praktisch zu sein, und der Code ist eine Zeile weniger geworden. Sie können optimieren. In diesem Beispiel können Sie die Rahmenfarbaufgabe übrigens überhaupt nicht verwenden, da sie standardmäßig bereits einen Wert aus der Farbeigenschaft übernimmt.

Es ist manchmal sehr traurig zu sehen, wie base64 verwendet wird. In CSS wurde zuvor aktiv empfohlen: Verwenden Sie base64, um kleine Symbole einzufügen. Wenn es über TCP in ein Segment passt, ist es gut für Sie.



Aber auch Harry RobertsDurchführung einer klassischen Studie darüber, wie sich base64 auf das Laden von Seiten auswirkt. Ja, es gibt weniger Anforderungen, aber solche Stile werden manchmal langsamer analysiert.

Okay, das Parsen ist eine sehr schnelle Operation, die der Benutzer höchstwahrscheinlich nicht bemerkt. Wir haben jedoch eine wichtige Metrik - das erste Rendering, damit der Benutzer etwas auf der Seite sieht. Auf Mobiltelefonen erfolgt das erste Rendern laut einer Studie von Harry Roberts zehnmal später. Überlegen Sie, ob Sie base64 benötigen? Ja, es gibt weniger Anfragen, aber hat sich das ausgewirkt?

Und bitte verwenden Sie base64 nicht für SVG. Weil SVG hervorragend für die Verwendung von URL-Encodern geeignet ist. Julia Bukhvalova hat ein cooles Werkzeug: Kommen Sie herein, fügen Sie Ihre SVG ein und es wird CSS in einer einfügbaren Form ausgeben. Möglicherweise stellen Sie fest, dass es keine base64 gibt, aber einige Dinge werden übersehen, die in CSS möglicherweise nicht richtig wahrgenommen werden. Es ist viel effizienter.

Im Durchschnitt gibt base64 ein Plus von 30% für die Größe Ihrer Komprimierung. Wozu?

Verwenden Sie moderne Technologie. Möglicherweise müssen wir Internet Explorer unterstützen - die üblichen Argumente, wenn es um Raster geht.



Aber denken Sie darüber nach: Wenn Sie keine IE-Unterstützung haben und immer noch auf Float oder Tabellen setzen, können Sie mithilfe von Gittern ein dreispaltiges Layout mit einer Lücke von 20 Pixel erstellen - dies ist der Abstand zwischen den Spalten. Drei Zeilen. Nun, fünf, wenn man die Ankündigung selbst betrachtet.

Versuchen Sie dies auf einem Schwimmer. Und ich meine, wir ändern drei Zeilen, einschließlich des Namens der Klassen, wenn Sie HTML berühren. Ich habe keinen Weg gefunden, auf einem Schwimmer das Gleiche zu tun. Wirf deine Entscheidungen ab. Aber nutzen Sie moderne Technologie. Mit ihnen können Sie das Markup kompakter anzeigen.



Sie können Atomic CSS ausprobieren. Was ist das? Sie schreiben diese etwas verrückten Klassennamen. Und nach einiger Zeit beginnt man zu verstehen, dass Sie die Hintergrundfarbe oder nur die Farbe eingestellt haben. Dies sind die "Funktionen" für CSS. Sie haben jedoch einen festen CSS-Satz, den Sie dann in HTML als Stilangabe verwenden. Und CSS wird plötzlich kleiner. Bei großen Projekten wird es wirklich kleiner, da es weniger einzigartige Stile gibt. Aber Sie wachsen HTML.



Sie können in Richtung Rückenwind-CSS schauen, das jetzt immer beliebter wird. Es handelt sich nicht um Atomic CSS, sondern um Dienstprogrammklassen, ähnlich wie Bootstrap, die nur nützlicher sind. Sie können einen bestimmten Satz verwenden. Es scheint genug für dich zu sein. Eine Reihe von Klassen, die ihre Funktionen ausführen. Sie können es auch versuchen, aber übertreiben Sie es nicht viel.



Eine andere verrückte Idee - warum brauchen wir ganze Klassennamen auf dem Client? Ja, es ist praktisch für die Entwicklung und das Debuggen, aber nehmen wir alle Klassennamen und machen sie aus einem Buchstaben. Es wird weniger sein.

Hier ist ein Artikel dazu. Sie können beim Erstellen ein Webpack oder ein anderes Plugin konfigurieren. Aber es hat uns nicht geholfen. Wir haben es versucht.

Es stellte sich heraus, dass gzip so cool ist, dass alles für uns ziemlich gut optimiert wurde, und BEM und gzip sind unglaublich freundlich. Weil Textkonstrukte wiederholt werden, um Blöcke und Elemente im Code zu beschreiben.

Im Allgemeinen brachte uns dies fast keinen Gewinn. Wenn Sie beispielsweise keine BEM und eine Reihe unterschiedlicher Klassen haben, können Sie es versuchen.

Wichtig: messen. Messen Sie alle diese experimentellen Stücke. Vielleicht funktioniert es jetzt für Sie, und dann haben Sie die Architektur des Projekts leicht verändert, es begann sich anders zusammenzusetzen und alles verlangsamte sich.

Lade es herunter!


Bisher habe ich nur darüber gesprochen, wie man eine Datei herunterlädt. Wir haben es heruntergeladen. Was hat der Benutzer die ganze Zeit gesehen?



Er sah so einen erstaunlichen Bildschirm. Während des Herunterladens war der Bildschirm leer. Wir haben heruntergeladen und der Browser beginnt mit sechs weiteren Schritten. Seien Sie etwas geduldig, ich werde etwas schneller über sie sprechen als über das Herunterladen.



Beginnen wir mit dem Parsen. Beim Parsen hat ein Browser einen Bytestrom heruntergeladen und beginnt, ihn in Entitäten zu unterteilen, die er versteht.



Zum Beispiel stieß er auf Import. Dies muss erneut heruntergeladen werden. Lesen Sie den ersten Teil des Berichts noch einmal? Import ist eine Blockierungsoperation. Aber Browser sind schlau. Sie haben einen Preload-Scanner. Ich sagte, dass dort alles blockiert ist, das ist nicht wahr. Browser wissen, dass wenn beispielsweise drei Link-Tags in einer Reihe dem Stil folgen, Sie beim Herunterladen des ersten mit dem Herunterladen des zweiten und dritten Tags beginnen können. Es kann nicht analysiert werden, da die gesamte Struktur des Parsens unterbrochen wird. Aber im Voraus herunterladen - es kann.



Import ist also eine schlechte Sache. Wenn die Stile in HTML konsistent sind, wird der Browser sehen, dass wir für eine andere Datei weiter gehen werden.



Und wenn Sie es direkt in den Import einfügen, sollte es zuerst Ihre style.css herunterladen und dann den Import darin sehen. Er beginnt dieses CSS zu analysieren ... Ja, wir blockieren alles auf eine neue Art und Weise und greifen nach der Datei! So können Sie einen kühlen Wasserfall mit Deoptimierung auf der Baustelle machen.

Vergessen Sie den Import oder konfigurieren Sie ihn so, dass nach dem Build kein Import erfolgt. Für die Entwicklungsumgebung ok, aber nicht für den Benutzer.



Als nächstes gehen wir mit Cascade durch die Phasen des Baumbaus.



All dies wird auch schon lange beschrieben. Das CSS-Objektmodell wird erstellt - ein spezieller Baum, in dem der Browser Tags und Klassen Stilen zuordnet. Er verbindet alles mit dem DOM und stellt diese Verbindungen sehr schnell her. Wenn Sie etwas ändern, reicht es für ihn, es im Baum zu ändern.



Je größer die Auswahl, desto schwieriger ist es für den Browser, einen Baum zu zeichnen. Er muss den Selektor analysieren und in Baumstrukturen konvertieren. Und wenn Sie dort eingefügt haben! Wichtig, dann sollte er dies berücksichtigen.



Es scheint an der Zeit zu sein, wieder über BEM zu sprechen. BEM ist jedoch nicht erforderlich, wenn Sie wissen, wie Dienstprogrammklassen verwendet werden, wenn eine Klasse für eine Funktionalität verantwortlich ist und sie sich nicht gegenseitig stören. Dann ist es sehr einfach, einen Baum zu bauen. Sie haben eine ziemlich flache Struktur und dann sollte der Browser sie korrekt mit dem DOM verknüpfen.



Wenn Sie dies tun, sagen sie, dass solche Selektoren das CSS-Parsing verlangsamen. Aber das sind Legenden vor langer Zeit, der Unterschied ist für den Browser so gering, dass Sie ihn in einem durchschnittlichen Projekt nicht bemerken, wenn Sie Selektoren mit Sternchen optimieren. Aber möchten Sie solchen Code entwickeln und pflegen?



Früher hörte ich Tipps: Versuchen Sie, alles in eine Verknüpfung zu setzen. Hintergrund ist eine Verknüpfung für viele andere Eigenschaften. Wir haben alles in einer Immobilie zusammengefasst und es wird optimal.

Byte, ja, es wird kleiner. Wenn Sie jedoch die Zusammensetzung von CSS OM optimieren möchten, werden alle diese Eigenschaften vom Browser aus dem Hintergrund entfernt. Browser für jedes DOM-Element erstellen eine Tabelle mit allen Eigenschaften, die es haben kann. Wenn Sie sich die von DevTools berechneten Werte ansehen, sind sie nicht vorhanden, da der Browser sie gemäß Ihren Anforderungen berechnet hat. Es speichert dies im Speicher, da es viel einfacher ist, eine Eigenschaft neu zu schreiben, und alles funktioniert.

Dies ist auch ein sehr seltsamer Rat, aber wenn Sie CSS OM schneller machen möchten, können Sie sofort alle Eigenschaften einzeln festlegen. Das könnte funktionieren. Die Größe des Bündels wird jedoch stark zunehmen. Sie müssen messen. Ich bezweifle, dass es einen Gewinn bringen wird, aber plötzlich!

Wenn CSS OM erstellt wird, ist JS an dieser Stelle ebenfalls gesperrt. Wenn das Erstellen von OM CSS zwei Sekunden dauert, schlägt JS fehl. Obwohl ich mir nicht vorstellen kann, wie Sie es geschafft haben, so viel in CSS zu schreiben, dass der Baum zwei Sekunden lang erstellt wird.



Weiter macht der Browser Layout. Dies ist die Position aller DOM-Elemente, die Verwendung von Positionen. Er versteht, wo sich das Element befinden soll und mit welchen Abmessungen. Es scheint, dass der Benutzer zu diesem Zeitpunkt bereits eine Art Bild sehen sollte. Aber er sieht alles im Ansichtsfenster, kann durch ein begrenztes Fenster schauen. Wenn etwas von unten nicht stimmt, sieht er es einfach nicht.



Die Idee heißt Critical CSS und ist auch ziemlich alt. Sie fügen zu Beginn des Downloads einige wichtige Dinge für den ersten Bildschirm ein. Wenn Sie beispielsweise in Ihrem HTML-Code inline arbeiten, werden zusätzliche Anforderungen entfernt. Der Benutzer sieht diesen Bildschirm zuerst und lädt ihn dann nach Belieben herunter. Höchstwahrscheinlich beginnt er mit dem Scrollen, wenn Sie Zeit zum Laden haben.



Dies geschieht einfach. Es gibt Tools, die all dies automatisieren, einschließlich Plugins für Webpack und React. Einfach suchen und richtig konfigurieren.

- github.com/addyosmani/critical
- github.com/pocketjoso/penthouse
- github.com/anthonygore/html-critical-webpack-plugin
- github.com/GoogleChromeLabs/critters



Haben Sie einen guten Ansatzfrom Filament Group - asynchrones Laden ohne Blockieren von CSS. Alles ist ganz einfach.

Wenn Sie <link rel = pretoad> eingeben, teilen Sie dem Browser mit: „Ich werde diesen Stil benötigen, aber jetzt blockieren wir nichts. Sie laden es jetzt herunter, zwischenspeichern es und wenn ich mich ihm zuwende, beginnen Sie mit dem Erstellen von CSS OM. “ Und Sie müssen nur das herunterladen und verarbeiten: "OK, da ich es heruntergeladen habe, machen Sie es rel = Stylesheet, aktivieren Sie das Parsen."

Ein ziemlich einfacher Ansatz, aber auch mit Bedacht. Wenn Sie zu viel Vorspannung haben, können Sie es schlechter machen.



Sie können auch mit Medienausdrücken spielen. Fügen Sie sie ein und teilen Sie dem Browser mit: "Dieser Stil wird jetzt nicht benötigt, aber wenn dieser Medienausdruck funktioniert, wird er benötigt." Der Browser wird auch proaktiv heruntergeladen, jedoch mit einer niedrigeren Priorität und ohne Blockierung.



Ein weiterer verrückter Ansatz, aber nicht so verrückt - wenn Sie http / 2 Push haben. Sie können CSS direkt vor dem Block einbetten. Ohne CSS sieht Ihr Block nicht sehr gut aus. Warum also nicht das CSS einbinden, das Sie für den nächsten Block vor diesem Block benötigen? Dies ist logisch und mit http / 2 Push können Sie es optimieren.

Ein einfacher Ansatz. Wenn Sie es erweitern, verwenden Sie Lazy Loading. Warum sollte ein Benutzer etwas herunterladen, das er nicht verwenden wird? Sie können React-Komponenten so konfigurieren, dass sie Stile für sich selbst herunterladen sollten, wenn sie den Sichtbarkeitsbereich der Seite noch nie erreicht haben.

Wenn Sie die Intersection Observer-API kennenlernen, können Sie Ihre Seite möglicherweise erheblich beschleunigen.



Der letzte Schritt ist das Zeichnen und Auftragen auf Verbundschichten, das Kleben usw.



Der Browser erstellt in einer Vielzahl von Fällen zusammengesetzte Ebenen. Meiner Meinung nach passt hier nur ein Viertel des Chromium- Quellcodes . Sie können selbst sehen, wann zusammengesetzte Ebenen im Browser-Code erstellt werden.

Der Videospeicher ist begrenzt, insbesondere bei Mobiltelefonen. Wenn Sie alles auf neue Ebenen bringen, um Animationen mithilfe von Willensänderung: Transformation oder etwas anderem zu optimieren, geht es Ihnen möglicherweise schlechter.

Erstellen Sie weniger Ebenen - genau so viel, wie Sie für die aktuelle Optimierung benötigen.

Großartig, wir haben alle analysiert.

Und wenn ich zurückkomme?


Und was ist, wenn ich zur Seite zurückkehre? Dies ist nur das erste Mal, dass ich ging.

Zurück zur Seite, ich scheine in der Lage zu sein, alles sofort herunterzuladen. Ich habe bereits alle Ressourcen heruntergeladen. Warum nicht ein zweites Mal verwenden?



Wenn der Server den Cache-Control-Header nicht angibt, versucht der Browser, Ihre Datei zwischenzuspeichern, um sie wiederzuverwenden. Sie können Ihren Server standardmäßig konfigurieren, z. B. "Diese Datei für ein ganzes Jahr zwischenspeichern". Wird sich nicht ändern. In diesem Fall müssen Sie sich jedoch mit dem Problem der globalen Cache-Ungültigmachung befassen. Dies ist jedoch das Thema eines separaten Berichts.

Verwenden Sie Servicemitarbeiter! 2020 ist es Zeit, progressive Webanwendungen! Kirill Chugainov hatte einen guten Berichtdarüber, wie Servicemitarbeiter für verschiedene Anlässe eingesetzt werden können. In diesem Fall fangen Sie die CSS-Anforderung ab, speichern sie und geben sie aus dem Cache ab, wenn der Browser diesem Stil zum zweiten Mal folgt.

Aber der Browser verspricht Ihnen nichts. Sie können sich immer der Tatsache stellen, dass dem Browser der Speicherplatz ausgeht. Er wird versuchen, zwischenzuspeichern, aber es gibt keinen Speicher. Caching ist nicht hundertprozentig. Gehen Sie immer mit solchen Situationen um.

Sie können versuchen, den lokalen Speicher zu verwenden. Aber er ist wild langsam. Das Herunterladen einer Datei ist manchmal schneller als das Aufrufen der lokalen Speicher-API.

Sie können die integrierte Browser-Datenbank ausprobieren. Aber messen Sie es. Vielleicht dauert eine Reise zu JS aufgrund eines schwachen Prozessors länger.

Sie können dem Browser auch im Voraus mitteilen, dass Sie etwas herunterladen werden.



<link rel> - Erfahren Sie, wie dieses Attribut funktioniert. Es gibt Preconnect, Prefetch, Prerender - ich möchte separat darüber sprechen. Er sagt: „Ich bin jetzt auf dieser Seite und gehe dann zur nächsten. Laden Sie alles für diese Seite im Hintergrund herunter und zeichnen Sie. “ Cooles Zeug. Funktioniert nirgendwo.



In gewissem Sinne wird es in IE und Edge unterstützt. In Chrome wird dies nicht wirklich ausgeführt, es wird nicht gerendert. Es funktioniert wie Prefetch: Lädt diese Dateien und Caches herunter. Leider funktioniert ein vollwertiger Prerender nirgendwo.

Aber Sie können diese Idee entwickeln. Zum Beispiel wird in der Yandex-Anwendung - natürlich ohne CSS - ein Prerender erstellt. Wenn Sie nach etwas suchen, können Sie Ihre Ergebnisse wahrscheinlich sofort erhalten. Wir können vorhersagen, wohin Sie gehen werden, und im Voraus mit unseren eigenen Methoden alle erforderlichen Ressourcen beschaffen.

Was weiter? Es gab viele Links. Ich rate Ihnen auch, sich eine erstaunliche Sammlung von Optimierungen von Vanya Akulov anzuseheniamakulov. Erfahren Sie, wie Sie sowohl HTML als auch JS und Assembly optimieren.

Und vergessen Sie nicht aufzuräumen. Jetzt funktioniert mein Rat wirklich und schlägt vor, wie man es schnell macht, aber höchstwahrscheinlich werden sie nach fünf Jahren sogar schädlich sein. Es wird eine Technologie geben, die mit ihnen nicht kompatibel ist. Behalten Sie dies im Auge und versuchen Sie, Ihren Code auch nach einer Weile optimal zu halten. Vielen Dank für Ihre Aufmerksamkeit.

All Articles