•7 min read

Rust cho nhà phát triển Frontend: Hướng dẫn chuyển đổi thực tế

Rust cho nhà phát triển Frontend: Hướng dẫn chuyển đổi thực tế

Trong nhiều năm, hệ sinh thái frontend bị thống trị bởi một ngôn ngữ duy nhất: JavaScript (và tập hợp con được gõ mạnh của nó, TypeScript). Tuy nhiên, trong vài năm qua, một sự thay đổi đáng kể đã xảy ra. Rust, một ngôn ngữ lập trình hệ thống nổi tiếng về hiệu suất và an toàn bộ nhớ, đã mạnh mẽ gia nhập lĩnh vực frontend. Ban đầu được thúc đẩy bởi nhu cầu về các công cụ xây dựng nhanh hơn, Rust giờ đây là một công dân hạng nhất trong trình duyệt thông qua WebAssembly (Wasm).

Nếu bạn là một nhà phát triển frontend đang đầu tư nhiều vào React, Vue hoặc Angular, viễn cảnh học Rust có vẻ đáng sợ. Hướng dẫn này nhằm mục đích thu hẹp khoảng cách, dịch các khái niệm từ hệ sinh thái JavaScript sang mô hình Rust và chứng minh tại sao sự chuyển đổi này đáng để bạn dành thời gian.

Audio Briefing
0:00 / 0:00

Tại sao lại là Rust?

Trước khi đi sâu vào cú pháp, chúng ta phải giải quyết câu hỏi "tại sao". Tại sao một nhà phát triển web lại phải quan tâm đến một ngôn ngữ hệ thống?

  1. Hiệu suất công cụ: Hệ sinh thái JavaScript đã đạt đến mức giới hạn về hiệu suất khi nói đến công cụ. Các quy trình xây dựng phức tạp được xử lý bởi Webpack hoặc Rollup có thể mất hàng phút. Các công cụ được viết lại bằng Rust—như Turbopack, SWC và Rome (nay là Biome)—cung cấp thời gian biên dịch và đóng gói nhanh hơn nhiều lần.
  2. WebAssembly (Wasm): JavaScript nhanh, nhưng nó không thể đoán trước được do các lần tạm dừng của Garbage Collection (GC) và chi phí biên dịch Just-In-Time (JIT). Rust biên dịch trực tiếp thành mã bytecode Wasm được tối ưu hóa cao, cho phép hiệu suất gần như gốc cho các tác vụ tính toán chuyên sâu trong trình duyệt, chẳng hạn như xử lý hình ảnh, thao tác âm thanh và trực quan hóa dữ liệu phức tạp.
  3. An toàn: Bộ kiểm tra mượn của Rust loại bỏ toàn bộ các loại lỗi (như tham chiếu con trỏ null và tranh chấp dữ liệu) tại thời điểm biên dịch.
Advertisement

Thay đổi mô hình tư duy

Trở ngại lớn nhất khi chuyển từ TypeScript sang Rust không phải là cú pháp, mà là mô hình tư duy liên quan đến quản lý bộ nhớ và quyền sở hữu.

Quyền sở hữu và mượn

Trong JavaScript, Garbage Collector tự động xử lý việc cấp phát và giải phóng bộ nhớ. Bạn tạo một đối tượng, truyền nó đi, và khi không còn tham chiếu nào đến nó, nó sẽ được dọn dẹp.

Trong Rust, không có Garbage Collector. Thay vào đó, Rust sử dụng một tập hợp các quy tắc nghiêm ngặt được gọi là "Quyền sở hữu":

  1. Mỗi giá trị trong Rust có một biến được gọi là chủ sở hữu của nó.
  2. Chỉ có thể có một chủ sở hữu tại một thời điểm.
  3. Khi chủ sở hữu ra khỏi phạm vi, giá trị sẽ bị loại bỏ.

Nếu bạn muốn truyền một giá trị cho một hàm mà không từ bỏ quyền sở hữu, bạn phải "mượn" nó bằng cách sử dụng các tham chiếu (&).

// Rust Example
fn main() {
    let s1 = String::from("hello");
    // We pass a reference to s1. We do not transfer ownership.
    let len = calculate_length(&s1); 
    println!("The length of '{}' is {}.", s1, len);
}

fn calculate_length(s: &String) -> usize {
    s.len()
}

Sự nghiêm ngặt này buộc bạn phải suy nghĩ cẩn thận về vòng đời của dữ liệu, dẫn đến hiệu suất mạnh mẽ và có thể dự đoán được.

null và undefined so với Option

TypeScript sử dụng null và undefined để biểu thị sự vắng mặt của một giá trị. Ngay cả với strictNullChecks, lỗi thời gian chạy vẫn có thể xảy ra.

Rust loại bỏ hoàn toàn null. Thay vào đó, nó cung cấp enum Option. Một Option là Some(value) hoặc None.

// An Option containing an i32
let some_number: Option<i32> = Some(5);
let no_number: Option<i32> = None;

// You MUST handle both cases explicitly
match some_number {
    Some(n) => println!("The number is {}", n),
    None => println!("There is no number"),
}

Lựa chọn thiết kế cơ bản này loại bỏ "TypeError: Cannot read properties of undefined" mãi mãi.

Xử lý lỗi: try/catch so với Result

Trong JavaScript, lỗi thường được ném và bắt bằng các khối try/catch. Điều này có thể làm cho luồng điều khiển trở nên ngầm định và khó theo dõi.

Rust sử dụng enum Result cho các lỗi có thể phục hồi. Một Result là Ok(value) hoặc Err(error). Các hàm có thể thất bại phải trả về một Result, buộc người gọi phải xử lý lỗi tiềm ẩn một cách rõ ràng.

use std::fs::File;

fn open_file() {
    let f = File::open("hello.txt");

    let file = match f {
        Ok(file) => file,
        Err(error) => panic!("Problem opening the file: {:?}", error),
    };
}

Rust cũng cung cấp toán tử ? để truyền lỗi ngắn gọn, làm cho việc xử lý lỗi vừa rõ ràng vừa dễ đọc.

Xây dựng cho trình duyệt bằng WebAssembly

Hãy xem cách bạn thực sự có thể chạy Rust trong trình duyệt. Hệ sinh thái cung cấp các công cụ tuyệt vời như wasm-bindgen để tạo điều kiện giao tiếp liền mạch giữa JavaScript và Rust.

Đầu tiên, bạn định nghĩa một hàm Rust và chú thích nó bằng #[wasm_bindgen]:

use wasm_bindgen::prelude::*;

// This attribute exposes the function to JavaScript
#[wasm_bindgen]
pub fn fibonacci(n: u32) -> u32 {
    match n {
        0 => 0,
        1 => 1,
        _ => fibonacci(n - 1) + fibonacci(n - 2),
    }
}

Sử dụng một công cụ như wasm-pack, bạn có thể biên dịch mã Rust này thành một mô-đun WebAssembly cùng với các ràng buộc JavaScript được tạo. Sau đó, bạn có thể nhập mô-đun này trực tiếp vào ứng dụng frontend của mình giống như bất kỳ mô-đun JavaScript nào khác.

import init, { fibonacci } from './pkg/my_rust_module.js';

async function run() {
    await init(); // Initialize the Wasm module
    const result = fibonacci(40);
    console.log(`Result from Rust: ${result}`);
}

run();

Kết luận

Chuyển đổi sang Rust đòi hỏi một sự thay đổi mô hình. Bạn phải đánh đổi sự linh hoạt của một ngôn ngữ có bộ thu gom rác để lấy sự nghiêm ngặt của bộ kiểm tra mượn. Tuy nhiên, phần thưởng là rất lớn. Bằng cách học Rust, bạn có quyền truy cập vào hiệu suất chưa từng có, độ tin cậy vững chắc và khả năng tận dụng WebAssembly cho các tác vụ frontend đòi hỏi cao. Khi nền tảng web trưởng thành, Rust đang định vị mình không phải là một sự thay thế cho JavaScript, mà là một người bạn đồng hành thiết yếu, hiệu suất cao.

Advertisement

Bạn cũng có thể thích

Share this article:

Stay Updated

Get the latest posts delivered straight to your inbox.

Free Developer Utilities

Free In-Browser Developer Tools

Clean AI CLI logs, build cron expressions, decode JWTs, and calculate chmod permissions offline.

Explore Tools
Advertisement