问题:Lint的过程很慢
在使用 TypeScript 设置我们团队的 ESLint 配置时,我注意到使用 typescript-eslint 运行 ESLint 非常慢。
在GitHub挖掘了很久,我发现根本原因是使用类型信息运行 typescript-eslint 会导致意外的性能成本。
typescript-eslint 将 TypeScript AST 转换为 ESLint AST
文档:typescript-eslint: How does typescript-eslint work.
ESLint 通过使用由 ESLint JavaScript 解析器 Espree 生成的 AST 运行规则来工作。
但是,TypeScript 有额外的语法,因此 TypeScript 编译器创建的 TypeScript AST 需要转换为 ESLint 兼容的 AST。
此过程由@typescript-eslint/parser 提供的自定义解析器处理,该解析器利用@typescript-eslint/typescript-estree 包中的ESTree。
因此,@typescript-eslint/typescript-estree 需要在每个 .{ts,tsx} 文件上调用 TypeScript 编译器来生成 TypeScript AST,然后将 TypeScript AST 转换为与 ESLint 兼容的 AST。
创建此 AST 后,@typescript-eslint/eslint-plugin 使用 ESLint 可以针对其运行规则的 TypeScript 特定功能扩展规则。
.eslintrc指导typescript-eslint 的的运行过程。 个人参考以下代码可以实现从30s的lint到15s的优化
// .eslintrc.js
module.exports = {
root: true,
parser: "@typescript-eslint/parser",
parserOptions: {
tsconfigRootDir: __dirname,
project: ["./tsconfig.json"]
},
plugins: ["@typescript-eslint"],
extends: [
"eslint:recommended",
"plugin:@typescript-eslint/eslint-recommended",
"plugin:@typescript-eslint/recommended",
"plugin:@typescript-eslint/recommended-requiring-type-checking"
]
};
总之,高级 typescript-eslint 解析过程包括:
- @typescript-eslint/parser
- @typescript-eslint/parser 读取 .eslintrc 配置以确定包含和排除的文件
- @typescript-eslint/parser 调用 @typescript-eslint/typescript-estree
- @typescript-eslint/typescript-estree
- @typescript-eslint/typescript-estree 调用 TypeScript 编译器并将每个包含的 .{ts,tsx} 文件解析到 TypeScript AST
- @typescript-eslint/typescript-estree 将 TypeScript AST 转换为与 ESLint 兼容的 AST
- @typescript-eslint/eslint-plugin
- @typescript-eslint/eslint-plugin 扩展了 ESLint 规则与 TypeScript 特定的功能
TypeScript 基本上是在执行我们项目的构建,并在 ESLint 进行 linting 之前将每个 AST 节点复制并转换为 ESLint 兼容节点。
ESLint 还单独运行每个文件,因此在每个文件中初始化类型检查器都会产生重复的开销工作。
不幸的是,这意味着运行时间随着项目的大小而增加。
当有更多文件时,TypeScript 编译时间和 AST 转换时间会增加。
后续步骤:较小的性能改进调整
我无法发现许多大型优化来提高运行时性能。
根本问题仍然是 TypeScript 编译器生成 AST 的开销,以及将这个 AST 转换为 ESLint 兼容 AST 的 @typescript-eslint/typescript-estree 的工作。
但是,有一些小的调整:
- 设置 .eslintignore 以忽略不相关的目录,例如 node_modules 和非typescript文件。
- 运行 eslint 时使用 --cache 标志:eslint --cache **/_.ts。 存储有关已处理文件的信息,以便仅对更改的文件进行操作。
还有一篇关于 TypeScript 性能的整篇文章建议:
- 使用 include 属性设置 tsconfig.json ,指定项目中应编译的 TypeScript 文件的输入文件夹。
- 避免添加过多的 exclude 和 include 文件夹,因为 TypeScript 文件必须通过遍历包含的目录来发现,因此运行多个文件夹实际上会减慢编译速度。
// tsconfig.json
module.exports = {
compilerOptions: {
// ...
},
include: ["src"],
exclude: ["**/node_modules", "**/.*/"]
};
最后
文章翻译自: