Il team di DevTools è un grande fan di TypeScript, tanto che il nuovo codice in DevTools viene creato in questo linguaggio e stiamo portando avanti una grande migrazione dell'intera codebase per farla controllare da TypeScript. Puoi scoprire di più su questa migrazione nella nostra presentazione al Chrome Dev Summit 2020. Pertanto, aveva perfettamente senso prendere in considerazione anche la migrazione della base di codice di Puppeteer a TypeScript.
Pianificare la migrazione
Durante la pianificazione della migrazione, volevamo fare progressi in piccoli passaggi. In questo modo, i costi generali della migrazione vengono ridotti, in quanto lavori solo su una piccola parte del codice alla volta, e anche il rischio viene ridotto. Se qualcosa va storto in uno dei passaggi, puoi ripristinarlo facilmente. 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 provocano un errore.
Abbiamo anche avuto la fortuna che Puppeteer disponga di un solido insieme di test delle 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 della migrazione e i test sono stati 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 modifiche al codice senza test è rischioso, ma le modifiche che interessano interi file o l'intero codebase sono particolarmente rischiose. Quando si apportano modifiche meccaniche, è facile tralasciare 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 di CI sulle richieste di pull erano instabili e spesso non andavano a buon fine. Questo accadeva così spesso che avevamo preso l'abitudine di ignorare la nostra CI e unire comunque le richieste di pull, supponendo che l'errore fosse un problema isolato della CI piuttosto che un problema di Puppeteer.
Dopo alcuni interventi di manutenzione generale e un periodo di tempo dedicato alla correzione di alcuni problemi regolari dei test, abbiamo ottenuto uno stato di superamento molto più coerente, il che ci ha permesso di ascoltare l'integrazione continua e sapere che un errore indicava un problema reale. Questo lavoro non è affascinante ed è frustrante guardare infinite esecuzioni di CI, ma era fondamentale che la nostra suite di test funzionasse in modo affidabile, dato il numero di richieste di pull che la migrazione le stava lanciando.
Scegli e rilascia un file
A questo punto, la migrazione era pronta e avevamo un server CI affidabile pieno di test per proteggerci. Anziché analizzare un file arbitrario, abbiamo scelto di eseguire la migrazione di un file di piccole dimensioni. 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 ricominciare da capo.
Inoltre, l'analisi file per file (e con le release regolari di Puppeteer, in modo che tutte le modifiche non vengano incluse nella stessa versione di npm) ha ridotto il rischio. Abbiamo scelto DeviceDescriptors.js come primo file perché era uno dei file più semplici del codebase. Potrebbe sembrare un po' deludente fare tutto questo lavoro di preparazione e apportare una modifica così piccola, ma l'obiettivo non è apportare modifiche enormi immediatamente, ma procedere con cautela e metodicamente file per file. Il tempo dedicato alla convalida dell'approccio consente di risparmiare tempo in un secondo momento della migrazione, quando si incontrano file più complessi.
Dimostra il pattern e ripeti
Per fortuna, la modifica a DeviceDescriptors.js è stata inserita correttamente nel codebase e il piano ha funzionato come speravamo. A questo punto, non ti resta che rimboccarti le maniche e metterti al lavoro, 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 i progressi.
Esegui la migrazione e miglioralo in un secondo momento
Per ogni singolo file JavaScript, la nostra procedura era la seguente:
- Rinomina il file da
.jsa.ts. - Esegui il compilatore TypeScript.
- Risolvi eventuali problemi.
- Crea la richiesta di pull.
La maggior parte del lavoro in queste richieste di pull iniziali consisteva nell'estrazione delle interfacce TypeScript per le strutture di dati esistenti. Nel caso della prima richiesta di pull che ha eseguito la migrazione di DeviceDescriptors.js di cui abbiamo parlato in precedenza, il codice è passato da:
module.exports = [
{
name: 'Pixel 4',
… // Other fields omitted to save space
},
…
]
E sono diventati:
interface Device {
name: string,
…
}
const devices: Device[] = [{name: 'Pixel 4', …}, …]
module.exports = devices;
Nell'ambito di questo processo, abbiamo esaminato ogni riga del codebase alla ricerca di problemi. Come per qualsiasi codebase esistente da alcuni anni e cresciuto nel tempo, ci sono aree in cui è possibile eseguire il refactoring del codice e migliorare la situazione. Soprattutto con il passaggio a TypeScript, abbiamo notato che una leggera ristrutturazione del codice ci avrebbe consentito di fare maggiore affidamento sul compilatore e ottenere una migliore sicurezza dei tipi.
Contrariamente a quanto si potrebbe pensare, è molto importante resistere alla tentazione di apportare subito queste modifiche. L'obiettivo della migrazione è portare il codebase in TypeScript e, in qualsiasi momento durante una migrazione di grandi dimensioni, devi pensare al rischio di causare interruzioni al software e ai tuoi utenti. Mantenendo al minimo le modifiche iniziali, abbiamo ridotto questo rischio. Una volta unito e migrato il file a TypeScript, abbiamo potuto apportare modifiche successive per migliorare il codice e sfruttare il sistema di tipi. Assicurati di impostare limiti rigorosi per la migrazione e cerca di rispettarli.
Migrazione dei test per testare le nostre definizioni dei tipi
Una volta eseguita la migrazione dell'intero codice sorgente a TypeScript, abbiamo potuto concentrarci sui test. I nostri test avevano un'ottima copertura, ma erano tutti scritti in JavaScript. Ciò significava che una delle cose che non hanno testato erano le nostre definizioni di tipo. Uno degli obiettivi a lungo termine del progetto (su cui stiamo ancora lavorando) è fornire definizioni dei tipi di alta qualità pronte all'uso con Puppeteer, ma non avevamo controlli nella nostra codebase sulle nostre definizioni dei tipi.
Eseguendo la migrazione dei test a TypeScript (seguendo lo stesso processo, file per file), abbiamo riscontrato 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 di qualità del nostro TypeScript.
In qualità di ingegneri che lavorano sul codebase di Puppeteer, abbiamo già tratto enormi vantaggi da TypeScript. Insieme al nostro ambiente di CI molto migliorato, ci ha permesso di diventare più produttivi quando lavoriamo su Puppeteer e di fare in modo che TypeScript rilevi bug che altrimenti sarebbero stati inclusi in una release npm. Siamo felici di fornire definizioni TypeScript di alta qualità per consentire anche a tutti gli sviluppatori che utilizzano Puppeteer di trarre vantaggio da questo lavoro.
Scaricare i canali in anteprima
Ti consigliamo 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, testare le API della piattaforma web all'avanguardia e trovare problemi sul tuo sito prima che lo facciano i tuoi utenti.
Contatta il team di Chrome DevTools
Utilizza le seguenti opzioni per discutere delle nuove funzionalità, degli aggiornamenti o di qualsiasi altro argomento relativo a DevTools.
- Inviaci feedback e richieste di funzionalità all'indirizzo crbug.com.
- Segnala un problema di DevTools utilizzando Altre opzioni > Guida > Segnala un problema di DevTools in DevTools.
- Invia un tweet a @ChromeDevTools.
- Lascia commenti sui video di YouTube Novità di DevTools o sui video di YouTube Suggerimenti di DevTools.