typescript - tsc construirea incrementală curăță fișierul de ieșire la ștergerea fișierului sursă


Experimentez cu compilarea incrementală pentru a accelera generarea fișierelor .js din .ts într-un proiect mare, pentru procese locale și CI. Totuși, mă confrunt cu o problemă în care ștergerea unui fișier sursă nu șterge fișierul corespunzător .js în timpul compilării incrementale. Aceasta îmi creează probleme deoarece dacă trebuie să curăț dosarul înainte de fiecare compilare, nu ar mai avea sens să folosesc funcția de compilare incrementală.

Exemplu :

.
├── bar.ts
├── foo.ts
├── index.ts
├── package.json
└── tsconfig.json

După compilare npx tsc --build --incremental ./

.
├── bar.js
├── bar.ts
├── foo.js
├── foo.ts
├── index.js
├── index.ts
├── package.json
├── tsconfig.json
└── tsconfig.tsbuildinfo

Acum șterge bar.ts și rulează npx tsc --build --incremental ./

.
├── bar.js
├── foo.js
├── foo.ts
├── index.js
├── index.ts
├── package.json
├── tsconfig.json
└── tsconfig.tsbuildinfo

bar.js nu va fi șters.

Lipsește ceva în argumentul CLI? Nu există nicio informație despre asta în documentație.

Răspuns #1

Din câte înțeleg, acesta este un comportament intenționat al compilatorului TS. Întrebarea a fost postată cu mult timp înainte de acest răspuns și nu știu dacă documentația s-a schimbat între timp, dar documentația actuală la momentul scrierii despre flag-ul incremental afirmă următoarele:

incremental
Spune TypeScript să salveze informații despre graficul proiectului de la ultima compilare în fișiere stocate pe disc. Aceasta creează o serie de fișiere .tsbuildinfo în același folder cu rezultatul compilării. Ele nu sunt folosite de JavaScript-ul tău la rulare și pot fi șterse în siguranță.

Nu există nicio mențiune despre ștergerea automată (curățarea) fișierelor .js emise, așa că nu există niciun motiv să ne așteptăm la un astfel de comportament.

Este dificil de spus ce face TSC în proiectul tău exact fără a vedea tsconfig.json, dar cel mai probabil fișierele .js nu sunt urmărite de TSC. Deci, dacă muți sau ștergi fișierul sursă (bar.ts în exemplul tău), fișierul emis bar.js este „doar un alt fișier” pentru TSC și ar fi extrem de nepoliticos din partea lui să-l șteargă :)

Există un flag clean care se asigură că ieșirea se face în fișiere noi, eliminând pe cele vechi dacă este necesar, dar care tot nu va urmări bar.js decât dacă există un bar.ts corespunzător. Dacă muți sau ștergi bar.ts, TSC încă nu știe că bar.js este ceva special; cu siguranță nu că poate fi șters în siguranță.

Vezi o discuție similară la microsoft/TypeScript#36648.


Ați determinat că scrierea fișierelor este adevăratul factor de blocare și nu verificarea tipului? Principalul avantaj al flag-ului incremental este structura de date tsbuildinfo; se poate ca ștergerea tuturor fișierelor de ieșire .js să nu afecteze performanța la fel de mult cum credeți.

Dacă timpul de scriere al fișierului este într-adevăr o problemă, următoarea mea sugestie este să eviți să o faci cu noEmit până când este absolut necesar. Și dacă ai nevoie cu adevărat de scrieri incrementale ale fișierelor, nu văd alte modalități decât folosirea, de exemplu, a noEmit și dry pentru a (i) obține o listă a fișierelor de ieșire ale proiectului așa cum este acum și apoi (ii) să elimini toate fișierele .js care nu se află în acea listă. Dacă folosești, de exemplu, un script build în package.json, este ușor să adaugi acest lucru ca un pas înainte/după o construire.

Dacă niciuna dintre aceste sugestii nu este satisfăcătoare, cred că va trebui să propui o funcție pentru asta.

Răspunsul #2

Cea mai simplă soluție pe care am găsit-o este google/wireit, care gestionează construcțiile incrementale prin urmărirea fișierelor de intrare și ieșire.

Acestea fiind spuse, aceasta nu este o soluție nativă; așa cum a subliniat @Emma în răspunsul ei, tsc --incremental în prezent nu are o modalitate de a curăța rezultatul existent.

Iată un exemplu simplu:

package.json

{
    "scripts": {
        "ts": "wireit"
    },
    "wireit": {
        "ts": {
            "command": "tsc",
            "clean": "if-file-deleted",
            "files": [
                "*.ts",
                "tsconfig.json"
            ],
            "output": [
                ".*.js",
                ".tsconfig.tsbuildinfo"
            ]
        }
    },
    "dependencies": {
        "typescript": "~5.6.0",
        "wireit": "~0.14.9"
    }
}

Rularea npm run ts --watch face ca Wireit să șteargă automat fișierele .js dacă fișierele lor corespunzătoare .ts sunt eliminate.

.
├── index.ts
├── foo.ts
├── package.json
└── tsconfig.json

npm run ts --watch
> ts
> wireit
#
✅ Ran 1 script and skipped 0 in 1.2s.
.
├── index.ts
├── foo.ts
├── index.js
├── foo.js
├── package.json
└── tsconfig.json

Șters foo.ts

✅ Ran 0 scripts and skipped 1 in 0s.
.
├── index.ts
├── index.js
├── package.json
└── tsconfig.json