Puppeteer zu TypeScript migrieren

Wir im DevTools-Team sind große Fans von TypeScript. Deshalb wird neuer Code in den DevTools in TypeScript geschrieben und wir sind gerade dabei, die gesamte Codebasis zu migrieren, damit sie von TypeScript typgeprüft wird. Weitere Informationen zu dieser Migration finden Sie in unserem Vortrag auf dem Chrome Dev Summit 2020. Es war daher nur logisch, auch die Codebasis von Puppeteer zu TypeScript zu migrieren.

Migration planen

Bei der Planung der Migration wollten wir in kleinen Schritten vorankommen. So wird der Aufwand für die Migration gering gehalten, da Sie jeweils nur an einem kleinen Teil des Codes arbeiten. Außerdem wird das Risiko reduziert. Wenn bei einem der Schritte etwas schiefgeht, können Sie ihn ganz einfach rückgängig machen. Puppeteer hat viele Nutzer und eine fehlerhafte Version würde für viele von ihnen Probleme verursachen. Daher war es wichtig, das Risiko von funktionsgefährdenden Änderungen auf ein Minimum zu beschränken.

Wir hatten auch das Glück, dass Puppeteer über umfassende Unittests verfügt, die alle Funktionen abdecken. So konnten wir sicher sein, dass wir bei der Migration keinen Code beschädigten und keine Änderungen an unserer API vornahmen. Ziel der Migration war es, sie abzuschließen, ohne dass Puppeteer-Nutzer überhaupt bemerken, dass wir migriert haben. Die Tests waren ein wichtiger Bestandteil dieser Strategie. Wenn wir keine gute Testabdeckung gehabt hätten, hätten wir sie hinzugefügt, bevor wir mit der Migration fortgefahren wären.

Codeänderungen ohne Tests sind riskant, insbesondere wenn Sie ganze Dateien oder die gesamte Codebasis bearbeiten. Bei mechanischen Änderungen kann leicht ein Schritt übersehen werden. Bei mehreren Gelegenheiten wurde durch die Tests ein Problem erkannt, das sowohl dem Implementierer als auch dem Prüfer entgangen war.

Wir haben von Anfang an Zeit in die Einrichtung von Continuous Integration (CI) investiert. Wir haben festgestellt, dass CI-Ausführungen für Pull-Anfragen instabil waren und oft fehlschlugen. Das ist so oft passiert, dass wir uns daran gewöhnt hatten, unsere CI zu ignorieren und die Pull-Anfragen trotzdem zusammenzuführen, da wir davon ausgingen, dass der Fehler ein einmaliges Problem in der CI und kein Problem in Puppeteer war.

Nach einigen allgemeinen Wartungsarbeiten und der Behebung einiger regelmäßiger Testflakiness konnten wir den Test in einen viel konsistenteren Zustand bringen, sodass wir auf CI hören und wissen konnten, dass ein Fehler auf ein tatsächliches Problem hinwies. Diese Arbeit ist nicht gerade glamourös und es ist frustrierend, endlose CI-Ausführungen zu beobachten. Angesichts der Anzahl der Pull-Anfragen, die die Migration mit sich brachte, war es jedoch wichtig, dass unsere Test-Suite zuverlässig lief.

Eine Datei auswählen und ablegen

Zu diesem Zeitpunkt war die Migration bereit und wir hatten einen robusten CI-Server mit vielen Tests, die uns den Rücken freihielten. Anstatt eine beliebige Datei zu verwenden, haben wir bewusst eine kleine Datei für die Migration ausgewählt. Das ist eine nützliche Übung, weil Sie damit den geplanten Prozess validieren können, den Sie durchführen möchten. Wenn es mit dieser Datei funktioniert, ist Ihr Ansatz richtig. Wenn nicht, müssen Sie noch einmal von vorn anfangen.

Außerdem wurde das Risiko dadurch minimiert, dass wir Datei für Datei vorgegangen sind und regelmäßige Puppeteer-Releases veröffentlicht haben, sodass nicht alle Änderungen in derselben npm-Version enthalten waren. Wir haben DeviceDescriptors.js als erste Datei ausgewählt, weil sie eine der unkompliziertesten Dateien in der Codebasis war. Es kann sich etwas enttäuschend anfühlen, so viel Vorarbeit zu leisten und dann nur eine so kleine Änderung vorzunehmen. Das Ziel ist jedoch nicht, sofort große Änderungen vorzunehmen, sondern vorsichtig und methodisch Datei für Datei vorzugehen. Wenn Sie sich die Zeit nehmen, den Ansatz zu validieren, sparen Sie später bei der Migration Zeit, wenn Sie auf kompliziertere Dateien stoßen.

Muster beweisen und wiederholen

Glücklicherweise wurde die Änderung an DeviceDescriptors.js erfolgreich in die Codebasis aufgenommen und der Plan hat wie erhofft funktioniert. An diesem Punkt sind Sie bereit, sich an die Arbeit zu machen, genau wie wir. Mit einem GitHub-Label lassen sich alle Pull-Anfragen gruppieren. Das ist nützlich, um den Fortschritt im Blick zu behalten.

Migrieren und später verbessern

Für jede einzelne JavaScript-Datei haben wir Folgendes getan:

  1. Benennen Sie die Datei von .js in .ts um.
  2. Führen Sie den TypeScript-Compiler aus.
  3. Beheben Sie alle Probleme.
  4. Erstellen Sie die Pull-Anfrage.

Der Großteil der Arbeit in diesen ersten Pull-Anfragen bestand darin, TypeScript-Schnittstellen für vorhandene Datenstrukturen zu extrahieren. Im Fall der ersten Pull-Anfrage, mit der DeviceDescriptors.js migriert wurde, die wir zuvor besprochen haben, wurde der Code von:

module.exports = [
  { 
    name: 'Pixel 4',
    … // Other fields omitted to save space
  }, 
  …
]

Und wurde:

interface Device {
  name: string,
  …
}

const devices: Device[] = [{name: 'Pixel 4', …}, …]

module.exports = devices;

Im Rahmen dieses Prozesses haben wir jede Zeile der Codebasis auf Probleme überprüft. Wie bei jeder Codebasis, die schon einige Jahre existiert und im Laufe der Zeit gewachsen ist, gibt es Bereiche, in denen Code refaktoriert und die Situation verbessert werden kann. Insbesondere bei der Umstellung auf TypeScript haben wir Stellen gefunden, an denen wir durch eine leichte Umstrukturierung des Codes den Compiler stärker nutzen und eine bessere Typsicherheit erreichen konnten.

Auch wenn es sich vielleicht nicht so anfühlt, ist es wirklich wichtig, diese Änderungen nicht sofort vorzunehmen. Ziel der Migration ist es, die Codebasis in TypeScript zu übertragen. Während einer großen Migration sollten Sie immer das Risiko von Software- und Nutzerbeeinträchtigungen im Blick behalten. Da wir die ursprünglichen Änderungen so gering wie möglich gehalten haben, war das Risiko gering. Nachdem die Datei zusammengeführt und zu TypeScript migriert wurde, konnten wir weitere Änderungen vornehmen, um den Code zu verbessern und das Typsystem zu nutzen. Legen Sie strenge Grenzen für die Migration fest und versuchen Sie, diese einzuhalten.

Tests migrieren, um unsere Typdefinitionen zu testen

Nachdem wir den gesamten Quellcode zu TypeScript migriert hatten, konnten wir uns auf unsere Tests konzentrieren. Unsere Tests hatten eine gute Abdeckung, waren aber alle in JavaScript geschrieben. Das bedeutet, dass sie unsere Typdefinitionen nicht getestet haben. Eines der langfristigen Ziele des Projekts (an dem wir noch arbeiten) ist es, hochwertige Typdefinitionen sofort mit Puppeteer zu liefern. Wir hatten jedoch keine Prüfungen in unserer Codebasis für unsere Typdefinitionen.

Durch die Migration der Tests zu TypeScript (nach demselben Verfahren, Datei für Datei) haben wir Probleme mit unserem TypeScript gefunden, die sonst von Nutzern gefunden worden wären. Jetzt decken unsere Tests nicht nur alle Funktionen ab, sondern dienen auch als Qualitätsprüfung für unser TypeScript.

Wir haben bereits sehr von TypeScript profitiert, da wir als Entwickler an der Puppeteer-Codebasis arbeiten. In Kombination mit unserer stark verbesserten CI-Umgebung können wir so bei der Arbeit an Puppeteer produktiver sein und TypeScript-Fehler erkennen, die sonst in eine npm-Version gelangt wären. Wir freuen uns, dass wir hochwertige TypeScript-Definitionen bereitstellen können, damit alle Entwickler, die Puppeteer verwenden, von dieser Arbeit profitieren können.

Vorschaukanäle herunterladen

Verwenden Sie Chrome Canary, Dev oder Beta als Standardbrowser für die Entwicklung. Über diese Vorschaukanäle haben Sie Zugriff auf die neuesten DevTools-Funktionen, können innovative Webplattform-APIs testen und Probleme auf Ihrer Website finden, bevor Ihre Nutzer sie entdecken.

Chrome-Entwicklertools-Team kontaktieren

Nutzen Sie die folgenden Optionen, um über die neuen Funktionen, Updates oder andere Themen im Zusammenhang mit den Entwicklertools zu diskutieren.

  • Sie können uns Feedback und Feature Requests unter crbug.com senden.
  • Sie können ein Problem mit den Entwicklertools melden, indem Sie in den Entwicklertools auf das Weitere Optionen > Hilfe > Problem mit den Entwicklertools melden klicken.
  • Senden Sie einen Tweet an @ChromeDevTools.
  • Hinterlassen Sie Kommentare zu den YouTube-Videos What's new in DevTools oder DevTools Tips.