I have an Angular12 project composed of 590 TypeScript files. When I do ng lint
it runs TSLint and finishes in about 5 seconds. Nonetheless, I tried upgrading to eslint following the instructions on this official video from Angular, and now ng lint
takes more than 10 minutes (I actually didn't let the process finish, I stopped it at the 10 minutes mark).
I tried to isolate the issue to know if the cause was ng
or eslint
so I installed eslint globally with npm i -g eslint
and run it with timing information for a single file:
time TIMING=1 eslint /home/user/my-file.ts
And even for this single file it took more than 2 minutes. It is odd that eslint
is reporting each rule took just some milliseconds, whereas Linux says it took 148 seconds (which is accurate, it took more than 2 minutes):
Rule | Time (ms) | Relative
:-------------------------------------------|----------:|--------:
@angular-eslint/no-conflicting-lifecycle | 0.342 | 35.9%
@angular-eslint/no-input-rename | 0.163 | 17.1%
@angular-eslint/template/banana-in-box | 0.161 | 16.9%
@angular-eslint/no-output-rename | 0.103 | 10.9%
@angular-eslint/component-class-suffix | 0.100 | 10.5%
@angular-eslint/contextual-lifecycle | 0.083 | 8.7%
@angular-eslint/directive-class-suffix | 0.000 | 0.0%
@angular-eslint/no-empty-lifecycle-method | 0.000 | 0.0%
@angular-eslint/no-host-metadata-property | 0.000 | 0.0%
@angular-eslint/no-inputs-metadata-property | 0.000 | 0.0%
Rule | Time (ms) | Relative
:----|----------:|--------:
TIMING=1 eslint 148.14s user 4.47s system 190% cpu 1:19.96 total
How can I make eslint go faster?
The cause of the slow ESLint runtime with eslint-plugin-prettier is because that plugin also runs Prettier under the hood to detect and raise issues when the code differs from Prettier's expected output.
Rules specific for Angular 1 or 2We can use a property, defined in the ESLint configuration file, in order to know which version is used : Angular 1 or Angular 2. based on this property, you can create rules for each version.
Since the Angular CLI was released it has included linting using the ng lint command. With the release of Angular v11 it was announced that tslint which ng lint used behind the scenes for the linting was being replaced with eslint.
TSLint also has a dependency on Codelyzer, where ESLint does not.
The underlying issue is still the overhead of the TypeScript compiler generating an AST, and the @typescript-eslint/typescript-estree work of converting this AST to an ESLint compatible AST.
However, there are some minor tweaks:
There is also a whole article on TypeScript performance which recommends:
I suggest carefully reading through this section titled Notes on Performance of the Angular ts-lint to es-lint migration guide.
You can start debugging your problem by running the following command:
DEBUG=typescript-eslint:* ng lint
You will get an enormous amount of output, but there could be some valuable information in there.
Check (in one of the first lines) whether the expected tsconfig
files are loaded.
Check the output for files that are actually not supposed to be part of the linting process (i.e. from node_modules
folder or dist
folder, etc). This might expose some configuration issues for which you have to dig deeper.
Also check whether you get a lot of output as follows:
typescript-eslint:typescript-estree:createProjectProgram Creating project program for: path\to\your\file +0ms
typescript-eslint:typescript-estree:createWatchProgram File did not belong to any existing programs, moving to create/update. path\to\your\file +0ms
typescript-eslint:typescript-estree:createWatchProgram Creating watch program for path\to\your\file +0ms
If that is the case have a good look at the files and path names inside your tsconfig
. Specifically "baseUrl", "include" and "exclude" paths.
Note: I had for example "exclude" paths for spec files, but because of a configuration issue they were actually not excluded correctly and creating project programs for these files individually was slowing down the linting dramatically.
If after resolving all performance issues mentioned above does still not give you the performance you were hoping for you could also consider limiting the linting to changed files only.
This can be done by using the "cache" option in the lint options in your angular.json
file (normally the --cache flag for eslint):
"lint": {
"builder": "@angular-eslint/builder:lint",
"options": {
"cache": true,
...
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With