I'm experimenting with incremental build to speed up generating .js
from .ts
in a large project for local and CI processes. But, I'm facing an issue where deleting a source file doesn't delete the corresponding .js
file during incremental build. This is causing problems for me because If I have to clean the folder before every build, there would be no point in using the incremental build feature.
Example:
.
├── bar.ts
├── foo.ts
├── index.ts
├── package.json
└── tsconfig.json
After build npx tsc --build --incremental ./
.
├── bar.js
├── bar.ts
├── foo.js
├── foo.ts
├── index.js
├── index.ts
├── package.json
├── tsconfig.json
└── tsconfig.tsbuildinfo
Now delete bar.ts
and run npx tsc --build --incremental ./
.
├── bar.js
├── foo.js
├── foo.ts
├── index.js
├── index.ts
├── package.json
├── tsconfig.json
└── tsconfig.tsbuildinfo
bar.js
won't be deleted.
Is there anything missing in the CLI argument? There is no information about it in the documentation.
To my understanding this is intended behaviour from the TS compiler. The question was posted a long time before this answer and I don't know if the docs have changed in the meantime but the current as of writing documentation on the incremental
flag states the following:
incremental
Tells TypeScript to save information about the project graph from the last compilation to files stored on disk. This creates a series of .tsbuildinfo files in the same folder as your compilation output. They are not used by your JavaScript at runtime and can be safely deleted.
There's no mention of automatic deletion (cleaning) of emitted .js
files so there's no reason expect such behaviour.
It's difficult to say what TSC does in your exact project without seeing the tsconfig.json
but most probably the .js
files aren't being tracked by TSC. So if you move or delete the source file (bar.ts
in your example), the emitted bar.js
file is "just another file" to TSC and it'd be incredibly rude of it to delete it :)
There is a clean
flag that makes sure the output is done to new files, removing the old ones from the way if necessary but that still won't track bar.js
unless a corresponding bar.ts
exists. If you move or delete bar.ts
, TSC still doesn't know that bar.js
is anything special; definitely not that it can be safely deleted.
See a similar discussion at microsoft/TypeScript#36648.
Have you determined that writing the files is the actual bottleneck and not the type check? The incremental
flag's main sell is the tsbuildinfo
datastructure(s); it can be that deleting all the .js
output files isn't as big of a performance hit as you think.
If the file write time actually is a problem, my next suggestion is to avoid doing it with noEmit
until absolutely necessary. And if you really do need incremental file writes, I don't see other ways than using e.g. noEmit
and dry
to (i) get a list of the output files of the project as it currently is and then (ii) remove all the .js
files that aren't in that list. If you're using e.g. a build
script in package.json
, it's easy to just add this as a step before/after a build.
If none of those suggestions are satisfactory, I think you'll have to suggest a feature for this.