Il tuo progetto TypeScript inizia a ingrandirsi e diventare lento ma non sai cosa provoca questi rallentamenti ? Vedremo con un esempio come scovare i pezzi che richiedono più tempo durante la compilazione.
Quali strumenti usare ?
Prenderemo come esempio
questo repo GitHub. È un progetto React con un certo numero di chiavi di traduzione i18n (8 workspaces di 150 chiavi, quindi 1200 chiavi).
TypeScript ci offre alcuni strumenti per investigare i problemi di performance legati alla compilazione.
Per iniziare, quando si avvia il compilatore TypeScript, gli si può passare il parametro extendedDiagnostics.
npx tsc --extendedDiagnostics
restituisce qualcosa del tipo :
Files: 90
Lines of TypeScript: 83
Lines of JavaScript: 0
Lines of JSON: 2448
Parse time: 0.42s
ResolveModule time: 0.02s
ResolveTypeReference time: 0.00s
Program time: 0.48s
Bind time: 0.20s
Check time: 2.64s
Emit time: 0.00s
Total time: 3.32s
Done in 3.53s.
Ci si accorge che su questo repo :
Bene, è utile sapere che il type checking richiede tempo, ma sarebbe meglio sapere quali linee nel codice sono responsabili !
Ebbene, la buona notizia è che potremo scoprirlo in 2 passaggi.
Prima di tutto genereremo dei file di debug durante la compilazione :
npx tsc --generateTrace <path>
(bisogna sostituire
con un percorso valido dove tsc creerà una cartella, e poi scriverà i file di debug della compilazione)Per leggere questo file di debug useremo la scheda "Performance" degli strumenti di sviluppo (in un browser basato su Chromium).
Vi troveremo un pulsante "Load profile..." per caricare un file di debug (trace.json) :
Una volta caricato il file, bisognerà navigare, più o meno difficilmente, nell'interfaccia e cliccare sui pezzi del grafico che richiedono più tempo. Per esempio :
Sull'immagine si vede che un'operazione di tipo "checkExpression" nel file App.tsx richiede 3.17 secondi
Si può sapere esattamente a cosa corrisponde nel codice grazie all'indicazione : pos 372 end 378
Bisognerebbe quindi aprire App.tsx e guardare dal carattere 372 fino al carattere 378.
Beh, è un po' fastidioso, lo ammetto, sarebbe bello se uno strumento potesse trovare automaticamente le parti più lunghe della compilazione e calcolare la riga / la colonna al posto nostro...
Buone notizie, questo strumento
esiste !
Per usarlo, niente di più semplice:
npx @typescript/analyze-trace <path>
(sostituisci
con il percorso della cartella in cui hai generato i file di debug)Nel nostro esempio, il risultato sarà:
Hot Spots
└─ Check file /home/mayeul/Projects/tests/test-tsc/src/App.tsx (3700ms)
└─ Check deferred node from (line 17, char 27) to (line 18, char 34) (3186ms)
└─ Check expression from (line 18, char 11) to (line 18, char 21) (3172ms)
└─ Check expression from (line 18, char 22) to (line 18, char 30) (3170ms)
└─ Check expression from (line 18, char 23) to (line 18, char 29) (3170ms)
Se guardiamo nel file App.tsx, riga 18, colonna 23 (esattamente il nostro carattere 372 di prima), ci accorgiamo che il problema è in keys.map()
(il file App.tsx)
export const App = () => {
const { t } = useTranslation();
const keys: AllI18nKeys[] = [
"anotherTest:anotherTest-100",
"hehe:hehe-30",
"login:login-103",
"common:common-126"
];
return (
<div>
<h1>{t("login:login-0")}</h1>
{keys.map((key) => (
<p key={key}>{t(key)}</p>
))}
</div>
);
};
Ora possiamo chiederci perché è lento.
Nel
paragrafo relativo alle unioni, ci accorgiamo che Microsoft sconsiglia di usare delle unioni con molti elementi, ma il tipo AllI18nKeys è una unione di 1200 chiavi di traduzione...
Ed ecco fatto! Ora sei in grado di trovare da dove provengono i rallentamenti di compilazione sul tuo progetto. Per contro, per risolvere questi problemi, è un'altra faccenda 😉