Migrazione di Puppeteer a TypeScript

Nel team di DevTools siamo grandi fan di TypeScript, tanto che il nuovo codice in DevTools viene creato in questo linguaggio e siamo nel bel mezzo di una grande migrazione dell'intero codice di base al controllo dei tipi da parte di TypeScript. Puoi scoprire di più su questa migrazione nel nostro intervento al Chrome Dev Summit 2020. Pertanto, ha perfettamente senso valutare la migrazione anche della base di codice di Puppeteer a TypeScript.

Pianificare la migrazione

Quando abbiamo pianificato la migrazione, volevamo essere in grado di fare progressi a piccoli passi. In questo modo, riduci l'overhead della migrazione, perché lavori solo su una piccola parte del codice alla volta, e anche il rischio. Se qualcosa va storto con uno dei passaggi, puoi ripristinare facilmente la situazione precedente. Puppeteer ha molti utenti e una release non funzionante causerebbe problemi a molti di loro, quindi era fondamentale ridurre al minimo il rischio di modifiche che causano interruzioni.

Inoltre, abbiamo avuto la fortuna che Puppeteer dispone di un solido insieme di test di unità che coprono tutte le sue funzionalità. Ciò significava che potevamo essere certi di non interrompere il codice durante la migrazione, ma anche di non introdurre modifiche alla nostra API. L'obiettivo della migrazione era completarla senza che gli utenti di Puppeteer si accorgessero nemmeno che era stata eseguita e i test erano una parte fondamentale di questa strategia. Se non avessimo avuto una buona copertura dei test, l'avremmo aggiunta prima di continuare con la migrazione.

Eseguire qualsiasi modifica al codice senza test è rischioso, ma le modifiche che interessano interi file o l'intera base di codice sono particolarmente rischiose. Quando apporti modifiche meccaniche, è facile saltare un passaggio e, in più occasioni, i test hanno rilevato un problema che era sfuggito sia all'implementatore sia al revisore.

Una cosa su cui abbiamo investito tempo in anticipo è stata la configurazione dell'integrazione continua (CI). Abbiamo notato che le esecuzioni CI relative alle richieste pull erano inaffidabili e spesso non andavano a buon fine. Questo accadeva così spesso che avevamo preso l'abitudine di ignorare il nostro sistema di CI e di unire comunque le richieste pull, assumendo che l'errore fosse un problema una tantum del sistema di CI anziché un problema di Puppeteer.

Dopo un po' di manutenzione generale e tempo dedicato alla correzione di alcuni errori di test regolari, abbiamo ottenuto uno stato di passaggio molto più coerente, che ci ha permesso di ascoltare il CI e sapere che un errore indicava un problema reale. Questo lavoro non è molto interessante ed è frustrante guardare esecuzioni CI infinite, ma era fondamentale avere la nostra suite di test in esecuzione in modo affidabile, dato il numero di richieste pull generate dalla migrazione.

Scegliere e caricare un file

A questo punto, la migrazione era pronta e avevamo un solido server CI pieno di test per proteggerci. Anziché iniziare con un file qualsiasi, abbiamo scelto intenzionalmente un file di piccole dimensioni per la migrazione. Si tratta di un esercizio utile perché ti consente di convalidare la procedura pianificata che stai per intraprendere. Se funziona su questo file, il tuo approccio è valido; in caso contrario, puoi tornare alla fase di progettazione.

Inoltre, l'approccio file per file (e le release regolari di Puppeteer, che hanno impedito che tutte le modifiche venissero rilasciate nella stessa versione di npm) ha ridotto il rischio. Abbiamo scelto DeviceDescriptors.js come primo file, perché era uno dei file più semplici nel codice di base. Può sembrare un po' deludente fare tutto questo lavoro di preparazione per una modifica così piccola, ma l'obiettivo non è apportare subito modifiche enormi, ma procedere con cautela e metodicamente, file per file. Il tempo impiegato per convalidare l'approccio consente di risparmiare tempo in un secondo momento durante la migrazione, quando si incontrano i file più complicati.

Verifica il pattern e ripeti

Fortunatamente, la modifica a DeviceDescriptors.js è stata inserita correttamente nella base di codice e il piano ha funzionato come speravamo. A questo punto, puoi metterti al lavoro e procedere, ed è esattamente quello che abbiamo fatto. L'utilizzo di un'etichetta GitHub è un ottimo modo per raggruppare tutte le richieste di pull e lo abbiamo trovato utile per monitorare l'avanzamento.

Esegui la migrazione e migliorala in un secondo momento

Per ogni singolo file JavaScript, la nostra procedura è stata la seguente:

  1. Rinomina il file da .js in .ts.
  2. Esegui il compilatore TypeScript.
  3. Risolvi eventuali problemi.
  4. Crea la pull request.

La maggior parte del lavoro in queste richieste di pull iniziali è consistita nell'estrazione delle interfacce TypeScript per le strutture di dati esistenti. Nel caso della prima pull request che ha eseguito la migrazione di DeviceDescriptors.js di cui abbiamo discusso in precedenza, il codice è passato da:

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

e diventa:

interface Device {
  name: string,
  
}

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

module.exports = devices;

Nell'ambito di questa procedura, abbiamo esaminato ogni riga della base di codice per verificare la presenza di problemi. Come per qualsiasi base di codice esistente da alcuni anni e cresciuta nel tempo, esistono aree di opportunità per eseguire il refactoring del codice e migliorare la situazione. In particolare, con il passaggio a TypeScript, abbiamo notato che una leggera riorganizzazione del codice ci avrebbe permesso di fare affidamento maggiormente sul compilatore e di ottenere una maggiore sicurezza del tipo.

In modo controintuitivo, è molto importante resistere all'impulso di apportare queste modifiche immediatamente. Lo scopo della migrazione è trasferire la base di codice in TypeScript e, in ogni momento durante una migrazione di grandi dimensioni, devi tenere presente il rischio di causare interruzioni del software e dei tuoi utenti. Mantenendo le modifiche iniziali minime, abbiamo ridotto al minimo il rischio. Una volta unito il file e eseguita la migrazione a TypeScript, abbiamo potuto apportare modifiche successive per migliorare il codice e sfruttare il sistema di tipi. Assicurati di impostare limiti rigidi per la migrazione e cerca di rispettarli.

Eseguire la migrazione dei test per testare le nostre definizioni di tipo

Dopo aver eseguito la migrazione dell'intero codice sorgente a TypeScript, abbiamo potuto concentrarci sui test. I nostri test avevano una copertura eccezionale, ma erano tutti scritti in JavaScript. Ciò significa che una cosa che non hanno testato sono le nostre definizioni di tipo. Uno degli obiettivi a lungo termine del progetto (su cui stiamo ancora lavorando) è fornire definizioni di tipo di alta qualità con Puppeteer, ma non avevamo controlli nel codice di base relativi alle definizioni di tipo.

Eseguendo la migrazione dei test a TypeScript (seguendo la stessa procedura, file per file), abbiamo rilevato problemi con il nostro TypeScript che altrimenti sarebbero stati lasciati agli utenti. Ora i nostri test non solo coprono tutte le nostre funzionalità, ma fungono anche da controllo qualità del nostro TypeScript.

Abbiamo già tratto enormi vantaggi da TypeScript in qualità di ingegneri che lavorano sulla base di codice di Puppeteer. Insieme al nostro ambiente CI molto migliorato, ci ha permesso di aumentare la produttività quando lavoriamo su Puppeteer e di consentire a TypeScript di rilevare bug che altrimenti sarebbero stati inclusi in una release di npm. Siamo lieti di rilasciare definizioni TypeScript di alta qualità per consentire a tutti gli sviluppatori che utilizzano Puppeteer di trarre vantaggio da questo lavoro.

Scaricare i canali di anteprima

Valuta la possibilità di utilizzare Chrome Canary, Dev o Beta come browser di sviluppo predefinito. Questi canali di anteprima ti consentono di accedere alle funzionalità più recenti di DevTools, di testare API di piattaforme web all'avanguardia e di trovare i problemi sul tuo sito prima che lo facciano i tuoi utenti.

Contatta il team di Chrome DevTools

Utilizza le seguenti opzioni per discutere di nuove funzionalità, aggiornamenti o qualsiasi altro argomento relativo a DevTools.