注册
web

2025年,前端开发为什么一定要学习Rust?

引言

Rust语言是一门现代系统编程语言,由Mozilla Research于2009年开始开发,Mozilla Research 是 Mozilla 基金会旗下的一个研究部门,专注于推动开放网络和创新技术的发展,Rust语言正是在 Mozilla Research 中孕育并发展的。

Rust 最早是 Mozilla 雇员 Graydon Hoare 的个人项目,在2006年开始了Rust语言的初步设计,Mozilla 随后投入资源,支持Rust的发展,并最终于2010年公开这个项目,2015年发布1.0版本。

以下引用自Rust 语言圣经

大家可能疑惑 Rust 为啥用了这么久才到 1.0 版本?与之相比,Go 语言 2009 年发布,却在 2012 年仅用 3 年就发布了 1.0 版本[^1]。

● 首先,Rust 语言特性较为复杂,所以需要全盘考虑的问题非常多;

● 其次,Rust 当时的参与者太多,七嘴八舌的声音很多,众口难调,而 Rust 开发团队又非常重视社区的意见;

● 最后,一旦 1.0 快速发布,那绝大部分语言特性就无法再被修改,对于有完美强迫症的 Rust 开发者团队来说,某种程度上的不完美是不可接受的。

因此,Rust 语言用了足足 6 年时间,才发布了尽善尽美的 1.0 版本。

大家知道 Rust 的作者到底因为何事才痛下决心开发一门新的语言吗?

说来挺有趣,在 2006 年的某天,作者工作到精疲力尽后,本想回公寓享受下生活,结果发现电梯的程序出 Bug 崩溃了,要知道在国外,修理工可不像在中国那样随时待岗,还要知道,他家在 20 多楼!

最后,他选择了妥协,去酒店待几天等待电梯的修理。

当然,一般人可能就这样算了,毕竟忍几天就过去了嘛。但是这名伟大的程序员显然也不是一般人,他面对害他流离失所的电梯拿起了屠龙宝刀 - Rust。

自此,劈开一个全新的编程世界。

深入了解Rust

为什么要创建Rust这门语言?

在 Rust 出现之前,系统级编程领域主要由 C 和 C++ 统治。虽然这两种语言在性能方面表现出色,但它们也存在一些固有的缺陷,促使了 Rust 的诞生。

什么是系统级编程语言?

简单来说,系统级编程语言用于开发操作系统、驱动程序、嵌入式系统、游戏引擎、数据库等对性能和硬件控制要求极高的软件。

有以下特性:

  • 硬件访问: 系统级语言需要能够直接访问硬件资源,直接操作硬件
  • 高性能: 系统级程序通常需要直接操作硬件,对性能要求非常高。因此,系统级语言通常具有高效的内存管理机制和优化的编译器,以生成高效的机器码。
  • 较强的类型系统和编译时检查:为了尽早发现潜在的错误,系统级语言通常具有较强的类型系统和编译时检查机制,以提高代码的可靠性和安全性。
  • 并发和并行: 现代计算机系统通常具有多核处理器,系统级程序需要能够有效地利用多核资源,实现并发和并行执行,以提高性能。
  • 内存控制: 系统级编程需要对内存进行精细的控制,包括内存分配、释放、布局等。一些系统级语言允许开发者直接操作内存地址,以实现更高的灵活性和效率

有哪些系统级编程语言?

  • C/C++

    无GC,性能高,内存不安全

  • Rust

    无GC,性能高,内存安全

  • Go

    有GC,性能不如Rust,安全性不如Rust。

  • Assembly Language(汇编语言)

    性能高,开发效率低

  • zig

    无GC,性能高,安全性不如Rust,发展初期

C/C++ 的缺陷

  • 内存安全问题: C/C++ 允许开发者手动管理内存,这虽然提供了灵活性,但也容易导致各种内存安全问题,如:
    • 空指针(Null Pointers): 访问未初始化的指针或空指针会导致程序崩溃。
    • 野指针(Wild Pointers): 指针变量没有被初始化。任何指针变量刚被创建时不会自动成为NULL指针,它的缺省值是随机的,它会乱指一气。所以,指针变量在创建的同时应当被初始化,要么将指针设置为NULL,要么让它指向合法的内存。。
    • 悬垂指针(Dangling Pointers): 指针指向曾经存在的对象,但该对象已经被释放,再次访问该指针会导致未定义行为,悬垂指针是野指针的一种。
    • 双重释放(Double Free): 释放同一块内存两次,导致崩溃或不可预测的行为。
    • 内存泄漏(Memory Leaks): 分配的内存没有被及时释放,导致内存占用不断增加,最终可能导致系统崩溃。
    • 缓冲区溢出(Buffer Overflows): 向缓冲区写入超出其容量的数据,可能覆盖相邻的内存区域,导致程序崩溃或安全漏洞。
  • 并发安全问题: C/C++ 的并发编程容易引入数据竞争(Data Races)等问题,导致程序行为不确定,难以调试和维护。
  • 缺乏现代化的语言特性: C/C++ 的语法相对陈旧,缺乏一些现代化的语言特性,如模式匹配、类型推断等,使得代码编写和维护相对繁琐。

Rust 的创建正是为了解决 C/C++ 等语言的这些不足,同时保留其高性能的优点。具体来说,Rust 的设计目标是:

  • 解决内存安全问题: Rust 通过所有权系统、借用检查器等机制,在编译时就杜绝了空指针、野指针、数据竞争等内存安全问题。
  • 提供安全的并发编程: Rust 的所有权系统和类型系统也对并发安全提供了保障,使得开发者可以更容易地编写安全的并发程序。
  • 提供现代化的语言特性: Rust 引入了模式匹配、类型推断、trait 等现代化的语言特性,提高了代码的简洁性、可读性和可维护性。
  • 保持高性能: Rust 的设计理念是“零成本抽象”,即提供高级的抽象能力,但不会带来额外的运行时开销,且无需垃圾回收器等运行时机制,从而避免了额外的性能开销,媲美 C/C++。

简而言之,因为还缺一门无 GC 且无需手动内存管理、性能高、工程性强、语言级安全性、广泛适用性的语言,而 Rust 就是这样的语言。

为什么选择Rust语言?

  • 保证安全、内存占用小的同时能提供和C/C++ 一样的性能
  • 广泛的适用性,系统编程、网络服务、命令行工具、WebAssembly等场景都能应用
  • 生态渐渐完善,有大量的库和框架,完整的工程化开发工具链,强大的包管理
  • 社区非常活跃和友好,文档全面

Rust不是闭门造车的语言,能看出来设计者是做过大量不同语言的项目的人,Rust从解决实际问题出发,借鉴和融合其他语言的优点,又能够创新地提出所有权和生命周期,这个强大的能力带来了0开销的内存安全和线程安全。

凡事有利必有弊,Rust是站在前人的肩膀上,它集百家之长,借鉴了其他语言的许多优秀特性,如npm的包管理、go的channel来进行并发通信、Haskell的trait(类似java的接口),还有元组、泛型、枚举,闭包、智能指针这些特性并非rust原创,但Rust确实把这些优点全部吸收了进来,而没有做过度的设计和发散,让有一些其他语言基础的人还能够减轻一些上手成本。

即使这样,Rust依然是在一众语言里学习曲线最陡峭的语言之一,此外,Rust为了提高运行时性能必然是会牺牲一些编译时的效率的。

但是,这丝毫不会影响Rust成为一门伟大的语言,如果有一门语言可以改变你的编程思维方式,倒逼你进行更好的代码设计,让你在初学过程中连连发出“原来是这样啊”的感叹,那么它一定是Rust。

Rust 核心设计理念对前端有哪些启示

Rust的很多设计理念都可以在前端领域中或多或少地找到影子,让你明白前端某些技术为什么要这么设计,以及为什么不那么设计。

安全性设计

1. 类型安全

  • 静态类型检查:

    Rust 提供了一个非常强大的类型系统,确保了类型安全。在编译时,Rust 会强制要求所有变量和函数都有明确的类型声明。这使得很多潜在的错误能够在编译时被捕获,避免了运行时出现类型错误。

    反观JavaScript,作为js开发者,那是太有发言权了,由于js是动态类型语言,所以很多错误只能在运行时被发现,跑着跑着可能就出一个线上bug,这是多少前端开发者的痛啊。

    当在写了一段时间Rust后,我们就会明白TypeScript为什么会火了,以及TS为什么是必要的,TS不能解决所有问题,但能解决大部分低级问题。

    如果你不用TS,提高代码健壮性也是有方法的,只不过心智负担更重。参照文章接口一异常你的页面就直接崩溃了?

  • 不可变性和可变性:

    在 Rust 中,变量默认是不可变的,只有显式声明为可变 (mut) 才能修改。这种设计减少了错误发生的概率,因为不可变数据是线程安全的,不会在多个地方被修改。

    在JS中也有类似的设计,联想到ES6的const和let,const 只能保证变量引用不可变,但如果引用的是对象或数组,内容依然可以改变。可谓是相当鸡肋。

2. 内存安全

Rust 提供了一种独特的所有权系统来自动管理内存,避免了许多传统语言中常见的内存错误,如内存泄漏、悬垂指针和双重释放。

Rust 的内存安全设计包括以下几个方面:

  • 所有权系统:Rust 中的所有权系统确保每个资源只有一个所有者,而所有权可以转移。一旦所有权转移,原所有者无法再访问或修改该资源,资源离开作用域时会自动释放,这就避免了双重释放和内存泄漏的问题。
  • 借用检查器:Rust 的借用检查器确保在同一时间只能存在不可变借用或一个可变借用。这避免了并发情况下的内存冲突。
  • 生命周期:Rust 的生命周期系统确保引用的有效性,在编译时检查引用的生命周期与持有它的资源的生命周期是否匹配,从而防止悬空引用和野指针。

反观JavaScript 中的内存问题:

  • 内存泄漏(Memory Leak): 内存泄漏是指程序无法释放不再使用的内存,导致内存资源被浪费。在 JavaScript 中,由于垃圾回收机制,内存泄漏通常发生在以下几种情况:

    • 全局变量:

      全局变量是在全局作用域中声明的,它们在程序执行期间存在,直到程序结束时才会被销毁。因此,无论这些全局变量是否仍在使用,它们都将保持存在,无法被垃圾回收器回收。

        // 全局变量
      var globalVar = { name: 'example' };

      // 该对象即使没有被引用,仍然会存在,直到页面关闭

      在浏览器中,全局变量被视为 window 对象的属性,在 Node.js 中,则是 global 对象。

      垃圾回收器一般不会回收全局变量,原因之一是全局变量的清理通常意味着整个应用程序的关闭或重载。如果要强制回收全局变量,会导致额外的复杂性和性能开销。因此,大多数 JavaScript 引擎(如 V8)选择让全局变量一直存活。

      全局变量不仅会导致内存泄漏还有容易被意外覆盖的风险,尽量使用模块化、闭包等方式来避免将变量暴露到全局作用域中。

      同理,全局变量也会导致无法准确的进行treeshaking优化,因为全局变量是有副作用的。

    • 闭包(Closures)

      闭包可能会保持对外部函数作用域变量的引用,从而防止这些变量被回收。

      function createClosure() {
      let largeObject = new Array(1000000).fill('Memory leak');

      // 返回一个函数,访问 largeObject
      return function() {
      console.log(largeObject[0]);
      };
      }

      const closure = createClosure();

      // 使用完闭包后,显式清除引用
      closure = null; // 删除对闭包的引用,垃圾回收器可以回收 largeObject

      largeObject 是一个占用大量内存的对象。当我们调用 createClosure 时,它返回一个内部函数 closure,这个内部函数会引用 largeObject。尽管 largeObject 的生命周期在 createClosure 执行完之后结束,但由于 closure 仍然持有对 largeObject 的引用,这个对象就无法被垃圾回收器回收,从而导致内存泄漏。

      闭包本身不会引起内存泄漏,但如果闭包捕获了外部函数的引用,且这些引用长时间未清除,就可能导致内存泄漏。

  • 事件监听器

    如果没有正确移除事件监听器,可能导致无法释放关联的内存。

    如果我们为 DOM 元素注册了事件监听器,但没有在适当的时候移除它们,尤其是在元素被删除或不再需要时,事件监听器会一直保持对 DOM 元素的引用,从而防止垃圾回收。

    "my-element">Click me!


    <script>
    let element = document.getElementById('my-element');

    // 给 DOM 元素添加事件监听器
    function handleClick() {
    console.log('Element clicked');
    }

    element.
    addEventListener('click', handleClick);

    // 假设我们从 DOM 中移除了该元素
    document.body.removeChild(element);

    // 但是我们没有移除事件监听器,事件监听器仍然持有对该元素的引用
    // 因此该元素无法被垃圾回收
    script>

    需要手动清除事件监听器

    element.removeEventListener('click', handleClick);  // 移除事件监听器
    element = null; // 清除对 DOM 元素的引用
  • DOM 元素引用

    如果 DOM 元素的引用在不再需要时没有清除,垃圾回收机制也无法回收它们。

    当我们通过 DOM 操作获取并引用一个 DOM 元素时,如果该元素的引用没有及时清除,即使该元素已经被移除或不再需要,它也不会被垃圾回收,从而导致内存泄漏。

    "my-element">Hello, World!


    <script>
    // 获取 DOM 元素并保存引用
    let element = document.getElementById('my-element');

    // 动态移除该元素
    document.body.removeChild(element);

    // 但是我们没有清除 element 引用
    // 这个引用仍然指向已经从 DOM 树中移除的元素
    // 此时垃圾回收器无法回收这个元素,因为引用仍然存在
    script>

    可以使用 element = null 来清除引用,但这个操作需要手动执行,容易忘记。

v8的垃圾回收器

V8 中的GC采用标记清除法进行垃圾回收。主要流程如下:

  • 标记:从根对象开始,遍历所有的对象引用,被引用的对象标记为活动对象,没有被引用的对象(待清理)标记为垃圾数据。
  • 垃圾清理:将所有垃圾数据清理掉

在我们的开发过程中,如果我们想要让垃圾回收器回收某一对象,就将对象的引用直接设置为 null

let a = {}; // {} 可访问,a 是其引用

a = null; // 引用设置为 null
// {} 将会被从内存里清理出去

但如果一个对象被多次引用时,例如作为另一对象的键、值或子元素时,将该对象引用设置为 null 时,该对象是不会被回收的

let a = {};
let arr = [a];

a = null;
console.log(arr)
// [{}]

因为a被arr引用,即使a不被使用了,也不会被释放,除非arr也被设置为null。

JS也考虑到了这一点,在ES6中推出了: WeakMap和WeakSet 。它对于值的引用都是不计入垃圾回收机制的,所以名字里面才会有一个"Weak",表示这是弱引用(对对象的弱引用是指当该对象应该被GC回收时不会阻止GC的回收行为)。

let a = {};
let arr = new WeakSet();
arr.add(a);

a = null;
console.log(arr.has(a))
// false

即 arr 对a的引用是弱引用,如果a不用了,不会阻止垃圾回收。

以上代码可以在控制台自行尝试一下

即便JS给出了可以避免特定场景的内存泄漏的方案,但依然无法避免所有场景的内存泄漏,而且就算你熟谙内存泄漏的各种场景以及对应解决方案,百密也终有一疏,更何况实际开发中代码能跑起来我们就几乎不会考虑啥内存问题,而Rust则强制你一定要考虑内存安全,否则编译都不过。

3. 并发安全

Rust 的并发模型通过其所有权和借用规则确保了并发编程中的安全性。Rust 中的并发安全设计包括:

  • 数据竞争防止:Rust 中,数据竞争在编译时就能被发现。Rust 通过所有权规则确保要么有多个不可变借用,要么有一个可变借用,从而避免了并发时对共享数据的非法访问。
  • 线程安全:Rust 使用 Send 和 Sync 特性来标识哪些类型可以在线程之间传递或共享。Send 允许数据在不同线程之间传递,Sync 允许多个线程共享数据。
  • 锁机制:Rust 提供了 Mutex 和 RwLock 等机制来确保在多线程环境下对共享资源的安全访问。

JS是单线程,但是JS的单线程是基于事件循环的非阻塞的,所以可以通过异步来实现伪并发,竞态条件、数据竞争、数据共享等问题在JS中是很难发现的,甚至别人的代码修改了你的数据你都不知道,没有一定的开发经验积累,去排查由此产生地莫名其妙的bug是相当折磨人的。

当学习了Rust之后,你就会下意识地去考虑你所定义的数据的安全性,有没有不确定的执行顺序引发的问题?有没有可能被非预期的共享和修改?我改了这个对象会不会影响到其他部分的功能表现等等?从而去想办法将可能会发生的问题扼杀在摇篮里。例如在处理组件状态时,采用不可变数据结构和函数式编程模式可以减少出错的机会。实际上对于前端开发者来说,这类bug是相当常见的。

JS其实也是在不断努力解决其本身存在的各种问题的,例如不断升级的ES新特性,使用 use stric 开启严格模式,还有函数式编程范式的流行,以及各类框架都支持的状态管理等等,这些措施都是为了让JS代码能够更加健壮,弥补JS本身的一些不足。

不可变数据结构: 在React中,使用useState和useReducer来管理状态,避免直接修改状态对象。以及redux等状态管理库,还有像Immer这样的库来简化不可变数据的操作。 函数式编程: 在JavaScript中,封装有明确输入和输出的函数,或使用高阶函数(如map、filter、reduce)来处理数据,避免修改原始数据,从而保持代码的清晰性和可测试性。

无论是函数式编程,还是状态管理,都是为了减少每个动作的副作用,有明确的数据流,让代码更安全更加可维护,低耦合高内聚不是一句空话,是业界大佬们真正在不断去实践的。只是我们自己没有感知,而实际上JS这门语言自身的缺陷真的很多,用JS去开发很容易,但是用JS去开发出健壮又高性能的代码是很难的,这可能也是为什么前端框架和库百花齐放而又前仆后继的原因。

4. 错误处理

Rust没有传统意义上的异常机制。在许多编程语言中,错误通常会通过运行时抛出异常来传递,而Rust采用了一种完全不同的方式来处理错误。

Rust通过Result类型和Option类型来明确地处理错误和空值,Rust的错误处理是编译时检查的,必须显式处理Result或Option,如果忽略了错误处理,编译器会报错,确保错误处理不被遗漏。这种做法可以避免程序出现未处理的异常,增强程序的健壮性。

Result 类型:Rust使用Result类型来显式表示一个函数可能返回的两种状态:成功(Ok(T))或失败(Err(E))。这种方式要求函数调用者在编译时就明确考虑到错误的处理,而不是依赖于运行时的异常机制。,>

Result是一个枚举类型,定义如下:

enum Result {
Ok(T),
Err(E),
}
,>

Option 类型:在处理可能的空值时,Rust使用Option类型,它表示一个值可能存在(Some(T))或不存在(),避免了空指针异常的问题。

enum Option {
Some(T),
,
}

在前端开发中,JavaScript和TypeScript也可以借鉴Rust的错误处理机制,明确地处理每一种错误情况,尤其是空值问题,没有一个前端开发能躲过 undefined 的摧残。

高性能设计

1. 零成本抽象

零成本抽象是指使用高级编程语言的抽象(如函数式编程的高阶函数、泛型、闭包等)时,不会引入额外的性能开销或运行时成本。换句话说,编写高抽象层的代码并不会影响程序的性能,编译器能够将抽象代码转化为与低级代码相同的高效机器码。

在 Rust 中,“零成本抽象”特别重要,因为 Rust 旨在提供与 C 和 C++ 等低级语言相似的性能,同时保持高层次的代码抽象和安全性。通过静态分析和优化,Rust 能够在编译时消除大多数抽象层的开销。

零成本抽象的三个原则:

  • 没有全局成本(No global cost): 一个零成本抽象不应该对不使用该功能的程序的性能产生负面影响。

    换句话说,零成本抽象应该只在使用时产生影响,在未使用时不会引入任何额外的开销。

  • 最佳性能(Optimal performance): 一个零成本的抽象应该编译成相当于底层指令编写的最佳实现。意味着它在使用时会以尽可能接近底层代码的方式运行,即它的性能应当与手写的低级实现相当。

    可以理解为,如果你想要用rust抽象某个高级能力,那么抽象完成的性能不能比用更原始写法实现的性能差,如果你想要抽象前端框架,那么就不能比直接操作DOM的JS原生写法性能差。

  • 改善开发者体验(Improves developer experience): 抽象的意义在于提供新的工具,由底层组件组装而成,让开发者更容易写出他们想要的代码,提高开发效率和代码可读性。

举几个例子

  1. Rust 的所有权系统(ownership system)和生命周期(lifetimes)。

当你写一个简单的程序,没有使用所有权系统的特性时,编译器会对这些特性进行优化,使得它们对程序的性能没有任何影响。只有当你使用这些特性时,编译器才会引入相关的检查和优化。

  1. 迭代器(Iterators) Rust 的迭代器是一种高效的抽象
fn main() {
let numbers = vec![1, 2, 3, 4, 5];
let sum: i32 = numbers.iter().map(|x| x * 2).sum();
println!("Sum: {}", sum);
}

在这个例子中,iter 返回一个迭代器,map 是一个高阶函数,它将一个闭包应用到每个元素。尽管你使用了高阶函数和迭代器,Rust 会在编译时优化这段代码,确保它与手写的 for 循环代码在性能上等效。

Rust 的迭代器通过惰性求值来避免不必要的中间计算。当你调用 .map() 和 .sum() 时,Rust 会合并这些操作为一个高效的迭代过程,不会在内存中创建不必要的临时集合,最终生成与手动实现同样高效的机器码。

而在JS中,几种高阶函数的使用则是有成本的,如map、foreach 等,在进行一些极端的数据量测试时,性能差异相比 for 循环就比较明显了,但是js引擎实际上也是做了很多的优化的,这点不用太过于担心,放心用就好了。

  1. 泛型(Generics) Rust 中的泛型是一个典型的零成本抽象。

使用泛型时,Rust 在编译时会根据类型替换(monomorphization单态化)生成具体的代码,在运行时没有任何额外的开销。

fn add(a: T, b: T) -> T
where
T: std::ops::Add,
{
a + b
}

在这个例子中,add 函数是一个泛型函数。Rust 编译器在编译时会为每种特定类型(例如 i32、f64 等)生成专门的机器码。

如果你调用 add(1, 2),Rust 会为 i32 类型生成专门的代码。同样,如果你调用 add(1.5, 2.5),Rust 会为 f64 类型生成专门的代码。泛型不会引入运行时的性能损失。编译后的代码与手写的具体类型版本在性能上是等价的。

  1. 错误处理

包括Rust的错误处理,由于Rust不使用异常机制,程序的控制流更加清晰,避免了异常捕获时的运行时性能开销。

对前端的启示

  • 抽象高级能力提升开发效率和体验: 前端框架(如 React 和 Vue)、TypeScript等都是属于抽象的高级能力。例如,React 的优化算法通过虚拟 DOM 的比对、最小化 DOM 更新,已实现类似的零成本抽象。除此之外还有很多事可以做。
  • 优化代码:减少抽象代码中不必要的计算,必要时惰性引入(前端叫懒加载)或计算,减少对不相关部分的隐形影响(前端叫副作用),利用好模块化开发和treeshaking等。
  • WebAssembly (Wasm): Rust 本身可以编译为 WebAssembly,这为前端性能优化开辟了新天地。借鉴 Rust 的这一特点,前端可以通过将性能瓶颈部分的代码(如图像处理、数据加密等)使用 Rust 编写并编译为 WebAssembly 运行,从而提升性能。

总结

社区很多人并不看好Rust甚至很激进地开喷,人确实是会有自己的舒适区的,当用熟了一样语言后,便不那么容易接受某一个自己不熟悉的语言更好,但是,尝试走出舒适区,真正地去接触Rust,一定会也能够感受到Rust的设计光辉。

要学习Rust,你需要先深入理解内存、堆栈、引用、变量作用域等这些其它高级语言往往不会深入接触的内容,Rust 会通过语法、编译器和 clippy 这些静态检查工具半帮助半强迫的让你成为更优秀的程序员,写出更好的代码。

Rust 程序只要能跑起来,那代码质量其实就是相当不错的,甚至不需要调试,能编译基本就没bug(当然是避免不了逻辑bug的)。正因为较高的质量下限,我们维护别人的代码时心智负担也比较小,能编译通过基本能保证不新增bug,把精力完全放在业务逻辑上就可以了。

而如果用javascript写程序,我们必须一边写一边调试,虽然写出能跑的程序极为简单,但要想没有bug,心智负担极高,js的程序员上限不封顶,但下限极低。而且review代码成本也很高,1000个人有1000种写法,review完改一改可能又不小心改出bug了。

JS对开发者要求较低,也是时代变了,条件好了,搁以前几百兆内存、单核cpu的时候,那时候的JS开发该有多痛苦啊。

社区流传着一个很奇怪的论调,“通过学习Rust,你能写出更好的xx语言的代码”。

学习Rust后,会潜移默化地影响你写其他语言代码时的思维方式,最直观的变化就是,对javascript中各类容易造成不安全不稳定的情况会更加敏感,所以,某种程度来看,Rust的价值可能并不在于用它写出多么优秀的代码,更重要的是它带给你的全面的方法论层面的提升。

我使用Rust做了比较丰富的尝试,包括用Rust写命令行工具、用Rust写 postcss 插件、用Rust写vite 插件、用Rust写WebAssembly在前端页面中使用,整体体验和效果还是非常棒的,WebAssembly的尝试可以查看文章Rust + wasm-pack + WebAssembly 实现Gitlab 代码统计,比JS快太多了,其他实践后面会陆续和大家分享,感兴趣的小伙伴可以关注收藏插个眼~

附:

Rust在前端领域的应用

  • SWC: 基于 Rust 的前端构建工具,可以理解为 Rust 版本的 Babel,但是性能有 10 倍提升。目前被 Next.js、Deno , Rspack等使用。
  • Tauri:Tauri 是目前最流行的 Electron 替代方案,通过使用 Rust 和 Webview2 成功解决了 Electron 的包体积大和内存占用高的问题。Atom 团队也是看到了 Tauri 的成功,才决定基于 Rust 去做 Zed 编辑器。
  • Parcel2:零配置构建工具,特点是快速编译和不需要配置,和 Vite、Webpack等打包比起来更加简单,而且是基于 Rust 开发
  • Biome: 旨在取代许多现有的 JavaScript 工具,集代码检测、打包、编译、测试等功能于一身。
  • Rspack: 基于 Rust 的高性能 Web 构建工具, 对标 Webpack, 兼容大部分Webpack api
  • Rocket: 可以帮助开发人员轻松编写安全的Web应用程序, 对标 Expressjs,性能卓越,具体参考 Web Frameworks Benchmark
  • Yew : 使用 Rust 开发 h5 页面,支持类 jsx 的语法,和 React 类似开发前端网页,打包产物是 wasm,挺有趣。
  • Napi-rs: 用 Rust 和 N-API 开发高性能 Node.js 扩展,可以替代之前用 C++ 开发的 Node.js 扩展,许多基于 Rust 语言开发的前端应用都结合这个库进行使用。
  • Rolldown: 基于 Rust 的 Rollup 的替代品。
  • 美国国防部准备征求一个把所有C代码翻译成Rust的软件。

作者:Pursue_LLL
来源:juejin.cn/post/7450021642377199643

0 个评论

要回复文章请先登录注册