Entfernen Sie nicht verwendeten Code.

In diesem Codelab verbessern Sie die Leistung der folgenden Anwendung, indem Sie alle ungenutzten und unnötigen Abhängigkeiten entfernen.

App – Screenshot

Messen

Es empfiehlt sich immer, zuerst die Leistung einer Website zu messen, bevor Sie Optimierungen vornehmen.

  • Wenn Sie sich eine Vorschau der Website ansehen möchten, drücken Sie App ansehen und dann Vollbild Vollbild.

Klicke einfach auf dein Lieblingskätzchen. In dieser Anwendung wird die Realtime Database von Firebase verwendet. Daher wird der Punktestand in Echtzeit aktualisiert und mit allen anderen Nutzern der Anwendung synchronisiert. 🐈

  1. Drücken Sie „Strg + Umschalttaste + J“ (oder „Befehlstaste + Optionstaste + J“ auf einem Mac), um die Entwicklertools zu öffnen.
  2. Klicken Sie auf den Tab Netzwerk.
  3. Klicken Sie das Kästchen Cache deaktivieren an.
  4. Aktualisieren Sie die App.

Originalgröße des Sets: 992 KB

Fast 1 MB JavaScript wird geladen, um diese einfache Anwendung zu laden.

Sehen Sie sich die Projektwarnungen in den Entwicklertools an.

  • Klicken Sie auf den Tab Console.
  • Achten Sie darauf, dass Warnings im Drop-down-Menü „Stufen“ neben der Filter-Eingabe aktiviert ist.

Filter für Warnungen

  • Sehen Sie sich die angezeigte Warnung an.

Konsolenwarnung

Firebase, eine der in dieser Anwendung verwendeten Bibliotheken, gibt eine Warnung aus, um Entwickler darauf hinzuweisen, dass sie nicht das gesamte Paket, sondern nur die verwendeten Komponenten importieren sollen. Mit anderen Worten: Es gibt ungenutzte Bibliotheken, die aus dieser Anwendung entfernt werden können, damit sie schneller geladen wird.

Es gibt auch Fälle, in denen eine bestimmte Bibliothek verwendet wird, für die es möglicherweise eine einfachere Alternative gibt. Das Konzept des Entfernens nicht benötigter Bibliotheken wird später in dieser Anleitung behandelt.

Bundle analysieren

Die Anwendung hat zwei Hauptabhängigkeiten:

  • Firebase: Eine Plattform, die eine Reihe nützlicher Dienste für iOS-, Android- oder Webanwendungen bietet. Hier wird die Realtime Database verwendet, um die Informationen für jedes Kätzchen in Echtzeit zu speichern und zu synchronisieren.
  • Moment.js: Eine Hilfsbibliothek, die die Verarbeitung von Datumsangaben in JavaScript erleichtert. Das Geburtsdatum jedes Kätzchens wird in der Firebase-Datenbank gespeichert und moment wird verwendet, um das Alter in Wochen zu berechnen.

Wie können nur zwei Abhängigkeiten zu einer Bundle-Größe von fast 1 MB beitragen? Nun, einer der Gründe ist, dass jede Abhängigkeit wiederum eigene Abhängigkeiten haben kann. Es gibt also viel mehr als nur zwei, wenn jede Tiefe/jeder Zweig des Abhängigkeitsbaums berücksichtigt wird. Wenn viele Abhängigkeiten enthalten sind, kann eine Anwendung relativ schnell groß werden.

Analysieren Sie den Bundler, um besser zu verstehen, was passiert. Es gibt eine Reihe von Tools, die von der Community entwickelt wurden und Ihnen dabei helfen können, z. B. webpack-bundle-analyzer.

Das Paket für dieses Tool ist bereits als devDependency in der App enthalten.

"devDependencies": {
  //...
  "webpack-bundle-analyzer": "^2.13.1"
},

Das bedeutet, dass sie direkt in der webpack-Konfigurationsdatei verwendet werden kann. Importieren Sie sie ganz am Anfang von webpack.config.js:

const path = require("path");

//...
const BundleAnalyzerPlugin = require("webpack-bundle-analyzer")
  .BundleAnalyzerPlugin;

Fügen Sie es nun als Plug-in ganz am Ende der Datei in das Array plugins ein:

module.exports = {
  //...
  plugins: [
    //...
    new BundleAnalyzerPlugin()
  ]
};

Wenn die Anwendung neu geladen wird, sollte eine Visualisierung des gesamten Bundles anstelle der App selbst angezeigt werden.

Webpack Bundle Analyzer

Nicht so süß wie ein paar Kätzchen 🐱, aber trotzdem unglaublich hilfreich. Wenn Sie den Mauszeiger auf eines der Pakete bewegen, wird seine Größe auf drei verschiedene Arten dargestellt:

Stat-Größe Größe vor der Minimierung oder Komprimierung.
Geprüfte Größe Größe des tatsächlichen Pakets im Bundle nach der Kompilierung. In Version 4 von webpack (die in dieser Anwendung verwendet wird) werden die kompilierten Dateien automatisch minimiert. Daher ist die Größe kleiner als die statische Größe.
Gezipte Größe Größe des Pakets nach der Komprimierung mit Gzip-Codierung. Dieses Thema wird in einer separaten Anleitung behandelt.

Mit dem Tool „webpack-bundle-analyzer“ lassen sich nicht verwendete oder unnötige Pakete, die einen großen Prozentsatz des Bundles ausmachen, leichter identifizieren.

Nicht verwendete Pakete entfernen

Die Visualisierung zeigt, dass das firebase-Paket viel mehr als nur eine Datenbank umfasst. Es enthält zusätzliche Pakete wie:

  • firestore
  • auth
  • storage
  • messaging
  • functions

Das sind alles tolle Dienste von Firebase (weitere Informationen), aber keiner von ihnen wird in der Anwendung verwendet. Es gibt also keinen Grund, sie alle zu importieren.

Machen Sie die Änderungen in webpack.config.js rückgängig, um die Anwendung wieder zu sehen:

  • Entfernen Sie BundleAnalyzerPlugin aus der Liste der Plug-ins:
plugins: [
  //...
  new BundleAnalyzerPlugin()
];
  • Entfernen Sie nun den nicht verwendeten Import oben in der Datei:
const path = require("path");

//...
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;

Die Anwendung sollte jetzt normal geladen werden. Ändern Sie src/index.js, um die Firebase-Importe zu aktualisieren.

import firebase from 'firebase';
import firebase from 'firebase/app';
import 'firebase/database';

Wenn die App jetzt neu geladen wird, wird die DevTools-Warnung nicht mehr angezeigt. Wenn Sie den Netzwerkbereich der Entwicklertools öffnen, sehen Sie auch eine deutliche Reduzierung der Bundle-Größe:

Bundle-Größe auf 480 KB reduziert

Mehr als die Hälfte der Paketgröße wurde entfernt. Firebase bietet viele verschiedene Dienste und Entwickler können nur die Dienste einbinden, die tatsächlich benötigt werden. In dieser Anwendung wurde nur firebase/database zum Speichern und Synchronisieren aller Daten verwendet. Der firebase/app-Import, mit dem die API-Oberfläche für die einzelnen Dienste eingerichtet wird, ist immer erforderlich.

Viele andere beliebte Bibliotheken, z. B. lodash, ermöglichen es Entwicklern auch, verschiedene Teile ihrer Pakete selektiv zu importieren. Wenn Sie die Importe von Bibliotheken in einer Anwendung so aktualisieren, dass nur die verwendeten Elemente enthalten sind, können Sie ohne großen Aufwand die Leistung deutlich verbessern.

Obwohl die Bundle-Größe erheblich reduziert wurde, gibt es noch mehr zu tun. 😈

Nicht benötigte Pakete entfernen

Im Gegensatz zu Firebase ist das Importieren von Teilen der moment-Bibliothek nicht so einfach. Vielleicht kann sie aber auch ganz entfernt werden.

Der Geburtstag jedes süßen Kätzchens wird im Unix (Millisekunden) in der Firebase-Datenbank gespeichert.

Im Unix-Format gespeicherte Geburtstage

Dies ist ein Zeitstempel für ein bestimmtes Datum und eine bestimmte Uhrzeit, der durch die Anzahl der Millisekunden dargestellt wird, die seit dem 1. Januar 1970, 00:00 UTC, vergangen sind. Wenn das aktuelle Datum und die aktuelle Uhrzeit im selben Format berechnet werden können, lässt sich wahrscheinlich eine kleine Funktion erstellen, mit der das Alter jedes Kätzchens in Wochen ermittelt werden kann.

Wie immer solltest du den Code nicht einfach kopieren und einfügen. Entfernen Sie zuerst moment aus den Importen in src/index.js.

import firebase from 'firebase/app';
import 'firebase/database';
import * as moment from 'moment';

Es gibt einen Firebase-Ereignis-Listener, der Wertänderungen in unserer Datenbank verarbeitet:

favoritesRef.on("value", (snapshot) => { ... })

Fügen Sie darüber eine kleine Funktion hinzu, um die Anzahl der Wochen ab einem bestimmten Datum zu berechnen:

const ageInWeeks = birthDate => {
  const WEEK_IN_MILLISECONDS = 1000 * 60 * 60 * 24 * 7;
  const diff = Math.abs((new Date).getTime() - birthDate);
  return Math.floor(diff / WEEK_IN_MILLISECONDS);
}

Bei dieser Funktion wird die Differenz in Millisekunden zwischen dem aktuellen Datum und der aktuellen Uhrzeit (new Date).getTime() und dem Geburtsdatum (dem birthDate-Argument, das bereits in Millisekunden angegeben ist) berechnet und durch die Anzahl der Millisekunden in einer Woche geteilt.

Schließlich können alle Instanzen von moment im Ereignis-Listener entfernt werden, indem Sie stattdessen diese Funktion verwenden:

favoritesRef.on("value", (snapshot) => {
  const { kitties, favorites, names, birthDates } = snapshot.val();
  favoritesScores = favorites;

  kittiesList.innerHTML = kitties.map((kittiePic, index) => {
    const birthday = moment(birthDates[index]);

    return `
      <li>
        <img src=${kittiePic} onclick="favKittie(${index})">
        <div class="extra">
          <div class="details">
            <p class="name">${names[index]}</p>
            <p class="age">${moment().diff(birthday, 'weeks')} weeks old</p>
            <p class="age">${ageInWeeks(birthDates[index])} weeks old</p>
          </div>
          <p class="score">${favorites[index]} ❤</p>
        </div>
      </li>
    `})
});

Laden Sie die Anwendung jetzt neu und sehen Sie sich das Network-Feld noch einmal an.

Bundle-Größe auf 225 KB reduziert

Die Größe unseres Bundles wurde noch einmal um mehr als die Hälfte reduziert.

Fazit

Nach diesem Codelab sollten Sie ein gutes Verständnis dafür haben, wie Sie ein bestimmtes Bundle analysieren und warum es so nützlich sein kann, nicht verwendete oder nicht benötigte Pakete zu entfernen. Bevor Sie mit der Optimierung einer Anwendung mit dieser Technik beginnen, sollten Sie wissen, dass dies bei größeren Anwendungen deutlich komplexer sein kann.

Nicht verwendete Bibliotheken entfernen: Finden Sie heraus, welche Teile eines Bundles verwendet werden und welche nicht. Wenn Sie ein mysteriös aussehendes Paket finden, das nirgends verwendet wird, sollten Sie einen Schritt zurückgehen und prüfen, welche Abhängigkeiten der obersten Ebene es benötigen. Versuchen Sie, sie voneinander zu entkoppeln.

Das Entfernen nicht benötigter Bibliotheken kann etwas komplizierter sein. Es ist wichtig, eng mit Ihrem Team zusammenzuarbeiten und zu prüfen, ob sich Teile der Codebasis vereinfachen lassen. moment in dieser Anwendung zu entfernen, mag jedes Mal richtig erscheinen. Was aber, wenn Zeitzonen und verschiedene Gebietsschemas berücksichtigt werden müssen? Oder was wäre, wenn es kompliziertere Datumsmanipulationen gäbe? Die Bearbeitung und das Parsen von Datums- und Zeitangaben kann sehr kompliziert sein. Bibliotheken wie moment und date-fns vereinfachen dies erheblich.

Alles ist ein Kompromiss. Es ist wichtig, abzuwägen, ob sich der Aufwand für die Entwicklung einer benutzerdefinierten Lösung lohnt, anstatt auf eine Drittanbieterbibliothek zurückzugreifen.