🙋🏻♀️ 编者按:本文是蚂蚁集团前端工程师云谦关于 Umi 4 新特性系列分享的第五篇 - 稳定白盒性能好的 ESLint,欢迎享用~
第一篇 👉🏻Umi 4 特性 01:MFSU V3,比 Vite 还要快
第二篇 👉🏻 Umi 4 特性 02:React Router 6 和新路由第三篇 👉🏻Umi 4 特性 03:默认最快的请求
ESLint 大家都很熟,通过很多规则,让大家写更好的代码,而且部分规则还能自动修复。Umi 3 也有 Lint 命令,包含 ESLint、Prettier、Stylelint 等。Lint 虽然不是卡点,但大家在这块遇到问题的比较多,同时带来了不少咨询量。
问题主要集中在这些方面,
1、规则开太多,有些规则见仁见智,不同人有不同的想法
2、依赖不稳定,睡一觉醒来规则变了,CI 过不了影响发布节奏
3、太黑盒,不知道开了什么规则,甚至框架(Umi)层自己都不敢更新依赖
4、性能不好,影响提交和 CI 速度
以上问题,Umi 4 的 Lint 方案全解。
规则开太多是因为 Umi 3 对于 ESLint 的定位不清晰。ESLint 的规则分质量类、建议类和风格类。比如使用未定义的变量是质量类,比如语句后加不加逗号则是风格类。在拥有 Prettier 之后,Umi 4 的方案里,风格类的全交给 Prettier,ESLint 则只负责可能导致问题的质量类。经过筛选,Umi 4 开的规则仅 60 多条。
依赖不稳定是 ESLint 的设计缺陷。ESLint 生态包含 Config 和 Plugin,Plugin 实现规则,Config 决定规则的开启或关闭。这理应是不错的设计,但可惜 ESLint 只考虑了项目级如何使用,却没有考虑三方库封装 Config 和 Plugin 的场景。具体的问题是 ESLint 找 Config 和 Plugin 只会从项目根目录去找。而 npm client 都有 Hoist 依赖的特性,导致往上提到根目录的依赖是不是正确有一定运气成分。所以依赖不稳定有两个原因,1)由于 npm client 的原因导致出现错误的 ESLint config 或 plugin,2)Config、Plugin 或其依赖和间接依赖更新导致的 break change。
对于依赖不稳定,Umi 4 有不同的解。短期的现在的解是通过 @rushstack/eslint-patch/modern-module-resolution 进行 hack,修改 Config 里找 Plugin 的规则,改从 Config 所在路径开始找。这可以确保 Plugin 版本找正确,但无法避免 Plugin 及其依赖更新后的功能变更。所以,更长期的未来的解是预打包 Config 和 Plugin 依赖,但由于 ESLint 设计上的问题,还需要调研 hack 的方式。
太黑盒是因为之前有继承其他 Config。Umi 4 的实现里,不再继承任何其他 Config,只使用提供规则功能的 Plugin,然后具体开什么规则是直接一个列表写死,只列我们需要的规则。这样三方或者 ESLint 官方规则启用开启的变更,都不会影响到 Umi 的用户,同时框架层也可以放心地更新依赖。
性能不好和 TypeScript 有关。Umi 3 会根据项目 TypeScript 文件的占比,决定是否开启 TypeScript 相关的 Lint 规则,而这些规则中,有一些是 type-aware linting。type-aware 的规则和类型相关,由于 TypeScript 的语言特性,比如跑一遍完整的项目才能确定类型是否正确,所以每次 lint 就算只改了一个文件,也需要跑整个项目。这里有把雨燕的 commit 时间从 19s 优化到 1-3s 的记录。而 Umi 4 中,压根不会开 type-aware 的规则,因为这些规则更多也是风格类,和质量无关。
参考:
Umi 4 开的 ESLint 规则列表
@rushstack/eslint-patch
https://github.com/microsoft/rushstack/tree/master/eslint/eslint-patch
Linting with Type Information