2024 基于 Rust 的 linter 工具速度很快

2024 年 Web 工具的一大趋势是使用 Rust 重写现有工具。Rust 是一种出色的编程语言,能生成运行速度惊人的二进制文件,且与其它 Web 工具的互操作性极佳,这得益于 WebAssembly 的帮助。swc 和 Turbopack 等工具的速度提升为快速开发体验带来了巨大变革。

Biome、deno lint、Oxc 和 RSLint 等项目都有一个用 Rust 编写的 JavaScript/TypeScript 代码检查器。对于那些对开发工具速度缓慢感到不满的开发人员来说,以Rust(本机代码)速度运行代码检查器,而非JavaScript(JIT脚本)速度,无疑是很有吸引力的。Prettier 甚至为 Biome 提供了 20,000 美元的奖金,以表彰其实现了与 Prettier 格式部分的 >95% 兼容性!

然而,基于 Rust 的 linters 是无法完全取代 ESLint 的。虽然性能优势明显,但也存在一个明显的缺陷:类型检查的 linting 功能缺失

回顾:类型检查的 Linting

传统上,像 ESLint 这样的 lint 工具一次只能检查一个源代码文件。这使得它们运行速度较快,理论上可以进行缓存和并行处理。

typescript-eslint 引入了使用类型信息的 linting 概念。通过调用 TypeScript 的类型检查 API,lint 规则可以根据项目中的其他文件提供的类型信息,对代码做出更加明智的决策。

类型检查的 lint 规则可能比传统的 lint 规则功能更强大。例如:

  • @typescript-eslint/await-thenable :禁止在非 Promise 值上使用不必要的 await 调用。

  • @typescript-eslint/no-floating-promises :可以提醒是否创建了一个 Promise 但忘记安全地处理它。

  • @typescript-eslint/no-for-in-array :用于标记对数组的不安全的 for...in 迭代(不是 for...of)。

这些规则只有在能够使用类型信息来确定何时报告问题时才有实际用处。没有类型信息,它们将无法理解从另一个模块导入的值的类型。

类型检查的 Linting 性能

类型检查的 linting 相比传统 linting 存在的主要劣势在于性能。这是因为类型化的 lint 规则需要调用 TypeScript 等 API 来获取类型信息,通常需要读取所有文件以确定哪些文件会影响其他文件的类型。因此,类型检查的 linting 性能通常会低于对整个项目运行 TypeScript 的性能。

TypeScript 本身也在不断优化性能。例如,项目引用可以显著帮助处理更大的项目。TypeScript 即将推出的独立声明模式看起来也可以显著提高处理更大项目的性能。

但即使所有这些加速都完美地工作,类型检查的 linting 设计上仍然比传统的 linting 慢几个数量级。因为从项目中推断类型的过程本质上比传统的 lint 规则一次只查看一个文件要慢得多。

大多数情况下,当看到类型检查的速度慢的项目时,根本原因要么是 typescript-eslint 配置错误,要么是 TypeScript 类型慢。

基于 Rust 的代码检查工具和类型检查

目前还没有基于 Rust 的代码检查器与 TypeScript 的类型检查 API 集成,这意味着基于 Rust 的代码检查器不能完全替代 ESLint + typescript-lint。

如果你不需要任何类型检查的 lint 规则,那么可以切换到基于 Rust 的 linter。但强烈建议你至少查看 typescript-lint 中推荐的类型检查规则,以了解缺少什么。

甚至可以同时运行这两种工具:首先使用原生速度的 linter 快速反馈,然后仅使用 typescript-eslint 查看包含类型信息的规则。这个想法得到了多个原生速度 linter 维护者的支持:

  • Biome 的 Emanuele 认为双重 linting 是一种合理的策略。

  • Oxc 的公告将 oxlint 描述为在 ESLint 过慢时的增强工具,而不是完全替代品。

这种互补而非取代的愿望部分源于这两种 lint 工具在运作方式上的重大结构性差异。原生速度的 lint 工具尚未在其 lint 规则中实现类型检查。下面来深入探讨这一奇怪的功能差距。

集成类型检查的 Linting 和基于 Rust 的 Linting

目前,TypeScript 的核心功能是为 TypeScript 编译器和语言服务提供支持的代码,它是唯一能够为 TypeScript 代码提供可靠类型检查的组件。由于TypeScript是用TypeScript编写的,因此其类型检查以JavaScript的速度运行。

为了实现与 TypeScript 的类型检查的集成,基于Rust的代码检查器面临几个选择:

  1. 承受性能损失,调用TypeScript的JavaScript速度类型检查API。

  2. 使用原生速度语言重新实现TypeScript的API。

  3. 将 TypeScript 的 API 提升到原生速度。

此外,基于 Rust 的 linter 不允许在 JavaScript 中编写自定义 lint 规则。虽然这对大多数 JavaScript 生态系统来说是一个贡献障碍,但这与本文的重点是两个独立的问题。

因此,将基于 Rust 的代码检查器与 TypeScript 的类型检查集成在一起有不同的选项。

降低 JavaScript 速度

选择这种性能影响方案可能会使基于 Rust 的 linter 速度降低到几乎与 ESLint 无明显性能优势的程度。

以原生速度重新实现 TypeScript

对于 TypeScript 用户来说,以原生速度重新实现 TypeScript 是一个极具吸引力的前景,而不仅仅是对于 linter。目前已有三个重要的尝试:

  • Ezno:一种类似于 TypeScript 的新语言,增加了依赖类型等特性。

  • stc:一个可以替代 TypeScript 类型检查的 Rust 编写项目。

  • TypeRunner:一个较早的尝试,使用 C++ 编写,但已不再积极开发。

需要注意的是,以新语言重新实现 TypeScript 是一项艰巨的任务。TypeScript 的类型推理需要处理泛型类型、协变、逆变等复杂边缘情况,这是一项极具挑战性的任务。这些项目目前都处于非常早期的阶段,可能需要很长时间才能准备投产。

那是否可以通过缩小项目的范围,只实现TypeScript的类型推理部分,从而降低这一选项的复杂性呢?对于 linters 来说,一个简化版的TypeScript,跳过源代码转换、类型检查可分配性错误等部分,只专注于编程类型检查API,或许更为实用。例如,Oxc 项目已经成功地实现了一个 TypeScript 类型推理的简化版,仅用几千行Rust代码就完成了这一任务。

然而,我们必须正视TypeScript背后有一个强大的开发团队和社区支持的现实。TypeScript团队由专业的编程语言专家组成,并且持续从社区中获得贡献。对于任何尝试重新实现TypeScript的项目来说,跟上TypeScript的更新步伐是一项几乎不可能完成的任务。尽管Ezno和stc等项目展现了令人印象深刻的成果,但它们作为独立项目的长期可行性仍然充满了不确定性。

将 TypeScript 的 API 提升到原生速度

为了提高TypeScript的性能,一个更具可行性的长期方案是优化其类型检查器的运行速度。目前有几种可能的解决方案:

  • 将TypeScript的类型检查器转换为更高效的编程语言,如Go或Rust。这可以通过编写一个转换工具来实现,将TypeScript源代码转换为这些更快的语言。

  • 对TypeScript进行预编译和优化,类似于将其转换为二进制格式。这种方法可以在编译时对代码进行优化,以提高运行时的性能。

  • 利用Node.js的用户快照技术来优化启动时间。通过在启动时预先优化代码,可以加快冷启动编译器的速度。

  • AssemblyScript和Static TypeScript是另外两个有趣的探索方向,它们通过使用TypeScript的子集或修改版本来关注低级性能。

这些方案都面临一定的挑战,需要投入时间和资源进行开发。然而,通过持续优化和改进,可以逐步提高TypeScript的性能,使其更加适应快速发展的开发需求。

虽然可以通过各种方法来加速TypeScript的运行,但其实TypeScript本身的架构是阻碍性能提升的主要因素。它的代码基于一种假设,即运行时环境将提供内置的垃圾回收、可变对象等功能,而这些功能往往会带来性能上的损耗。

为了真正提高TypeScript的性能,我们可能需要重新设计其架构,使其更加适应高性能场景:

  1. 隔离声明模式:这可能是最直接的方法,通过将类型声明与实际代码隔离,可以减少编译时的计算量,从而提高运行速度。

  2. 优化全局类型扩展:为了更好地支持并行化,我们需要限制全局类型扩展的使用,以减少潜在的性能瓶颈。

  3. 改进检查器运行方式:通过改变TypeScript检查器的运行方式,可以避免一些不必要的性能损耗,进一步提高运行速度。

然而,任何对TypeScript结构的重大更改都可能导致其API的重大变化,并可能引入新的问题。目前看来,除了可能在2024年推出的隔离声明模式外,其他的大规模改动短期内不太可能实现。

TypeScript 集成 Linting

另一个策略是将 linting 集成到现有的 TypeScript 语言服务器基础架构中。TypeScript 语言服务插件允许添加工具作为 TypeScript 编辑体验的一部分运行。

可以看到过两次尝试:

  • Quramy/typescript-🐴-language-service:ESLint 的通用 TypeScript 语言服务插件

  • johnsoncodehk/typescript-linter:基于 TypeScript 语言服务器构建的代码检查器的重新实现

两者似乎都有希望。为了与现有规则兼容,在短期内将 ESLint 作为 TypeScript 语言服务插件运行是更可行的。无论哪种方式,在不落后于其他语言的情况下,如何使 TypeScript 体验变得更好,尤其是考虑到 ESLint 打算拥抱其他 Web 语言,这将是一个关键挑战。

小结

基于 Rust 的 JavaScript/TypeScript 代码检查器,如 Biome、deno lint、Oxc 和 RSLint,都是非常快速的项目。但与 ESLint + typescript-ndrings 的类型检查代码规则相比,这种速度存在严重的功能差距。在决定使用哪个工具时,你应该了解这些权衡。Biome 和 oxlint 都表示在一定程度上建议先运行一个更快的原生速度代码检查器,而不是运行基于类型的 typescript-lint。

基于 Rust 的 linter 最终可能会以原生速度代码获得类型检查 linting 的好处。但要实现这一点还有很长的路要走。

当然也有好处和坏处,按照自己需求使用即可。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/325964.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

麒麟KYLINOS操作系统上使用五种不同方式安装软件

原文链接:麒麟KYLINOS使用五种不同方式安装软件 hello,大家好啊!今天我要给大家介绍的是在麒麟KYLINOS操作系统上使用五种不同方式安装软件的方法。在Linux系统中,有多种方式可以安装软件,每种方式都适用于不同的场景和…

Grind75第11天 | 310.最小高度树、127.单词接龙、230.二叉搜索树中第k小的元素

310.最小高度树 题目链接:https://leetcode.com/problems/minimum-height-trees 解法: 这个题类似最短路径问题,用的BFS。 从题目的例子可以看到,最小高度树的根节点,好像是入度比较大的节点,这是一个大…

MySQL基础笔记(6)函数

函数:是指一段可以直接被另一段程序调用的程序或者代码~(MySQL内置) 一.字符串函数 trim不能去除中间的空格~ select concat(jsl,1325): 执行如上的代码,返回字符串"jsl1325"。 select lower(JSL); 执行如上的代码&…

【健康小贴士】关节炎是不是冻出来的?

大家冬天肯定被父母唠叨过: 「天气这么冷,裤子穿这么短,小心得关节炎!」 ❌这种说法其实是不对的或者并不全面,答案来了👀

【PAT甲级】1175 Professional Ability Test

问题思考: 首先,若所有的计划(plan)中的节点都可达,则输出 Okay,否则输出 Impossible。注意:这里的“plan”判断的是整个图(这里是有向图)上的节点,而不只是那K个queries节点。若存…

基于Java SSM框架实现学生寝室管理系统项目【项目源码+论文说明】计算机毕业设计

基于java的SSM框架实现学生寝室管理系统演示 摘要 寝室管理设计是高校为学生提供第二课堂,而我们所在学院多采用半手工管理学生寝室的方式,所以有必要开发寝室管理系统来对进行数字化管理。既可减轻学院宿舍长工作压力,比较系统地对宿舍通告…

如何将千亿文件放进一个文件系统,EuroSys‘23 CFS 论文背后的故事

1. 引言 本文的主要目的是解读百度沧海存储团队发表于 EuroSys 2023 的论文《CFS: Scaling Metadata Service for Distributed File System via Pruned Scope of Critical Sections》,论文全文可以在 CFS: Scaling Metadata Service for Distributed File System v…

存内计算技术打破常规算力局限性

目录 前言 关于存内计算 1、常规算力局限性 2、存内计算诞生记 3、存内计算核心 存内计算芯片研发历程及商业化 1、存内计算芯片研发历程 2、存内计算先驱出道 3、存内计算商业化落地 基于知存科技存内计算开发板ZT1的降噪验证 (一)任务目标以…

Linux上新部署的项目jar包没有生效

今天公司新安排了一个项目,这里简称项目A,需要新增两个功能,我这边完成之后,跟前端对接好了,调试也没有问题。 然后把项目打包上传到测试服务器上,重新启动项目,发现项目A新增的接口没有生效&a…

QT属性动画

时间记录:2024/1/15 一、介绍 属性动画类为QPropertyAnimation,类似于CSS的keyframes关键帧 二、分类及使用步骤 1.几何动画 (1)创建QPropertyAnimation对象 (2)setPropertyName方法设置属性名称&#…

MetaGPT入门(二)

接着MetaGPT入门(一),在文件里再添加一个role类 class SimpleCoder(Role):def __init__(self,name:str"Alice",profile:str"SimpleCoder",**kwargs):super().__init__(name,profile,**kwargs)self._init_actions([Write…

【设计模式-3.3】结构型——享元模式

说明:说明:本文介绍设计模式中结构型设计模式中的,享元模式; 游戏地图 在一些闯关类的游戏,如超级玛丽、坦克大战里面,游戏的背景每一个关卡都不相同,但仔细观察可以发现,其都是用…

第十五讲_css水平垂直居中的技巧

css水平垂直居中的技巧 1. 水平垂直居中(场景一)2. 水平垂直居中(场景二)3. 水平垂直居中(场景三)4. 水平垂直居中(场景四) 1. 水平垂直居中(场景一) 条件&a…

Python UI框架库之kivy使用详解

概要 Python是一种广泛使用的编程语言,而Kivy是一个用于创建跨平台移动应用和多点触控应用的开源Python框架。Kivy的设计目标是提供一种简单而强大的方式来构建富有创意的用户界面和交互体验。本文将详细介绍Kivy的基本概念、核心特性、布局系统、用户界面设计和实…

【服务器数据恢复】服务器迁移数据时lun数据丢失的数据恢复案例

服务器数据恢复环境&服务器故障: 一台安装Windows操作系统的服务器。工作人员在迁移该服务器中数据时突然无法读取数据,服务器管理界面出现报错。经过检查发现服务器中一个lun的数据丢失。 服务器数据恢复过程: 1、将故障服务器中所有磁盘…

macOS 13(本机)golang程序交叉编译成 ARM架构

## 背景 golang程序(JuiceFS)需要支持ARM64架构,重新编译; 本地环境:macOS:13 ## 操作 安装交叉编译工具: brew install FiloSottile/musl-cross/musl-cross --with-aarch64 可以在 /usr/l…

【MATLAB随笔】遗传算法优化的BP神经网络(随笔,不是很详细)

文章目录 一、算法思想1.1 BP神经网络1.2 遗传算法1.3 遗传算法优化的BP神经网络 二、代码解读2.1 数据预处理2.2 GABP2.3 部分函数说明 一、算法思想 1.1 BP神经网络 BP神经网络(Backpropagation Neural Network,反向传播神经网络)是一种监…

【Unity】【Pico】【VR开发】为何PICO打包后真机运行闪退

【背景】 设置步骤,项目配置都没问题,Build也成功,Unity版本是符合要求的2022LTS版本,但是一在真机上运行就闪退。 【分析】 由于并没有开版权验证,而且闪退后也并没有弹框说版权问题,所以还是怀疑环境有…

如何有效构建进攻性的网络安全防护策略

文章目录 前言一、进攻性安全策略的价值(一)进攻性安全和防御性安全的区别(二)进攻性安全带来一种新的测试和防御的方法(三)进攻性安全策略也比防御性安全策略更具前瞻性 二、进攻性安全策略的类型&#xf…

欠拟合与过拟合

欠拟合: 模型在训练集上表现不好,在测试集上也表现不好。模型过于简单 欠拟合在训练集和测试集上的误差都较大 通过代码展示欠拟合 import numpy as np import matplotlib.pyplot as plt from sklearn.linear_model import LinearRegression from skle…