Dừng việc chờ đợi Linter: Chuyển sang Biome để tăng tốc quy trình TypeScript gấp 25 lần

Programming tutorial - IT technology blog
Programming tutorial - IT technology blog

Sự ức chế của chu kỳ “Lưu và Chờ đợi”

Tất cả chúng ta đều đã từng trải qua: bạn nhấn Command+S và ngồi chờ. Bạn chờ formatter sắp xếp lại code, rồi chờ thêm vài giây để linter phát hiện một lỗi cú pháp đơn giản. Trong một codebase có 100.000 dòng code, những khoảng trễ nhỏ này làm đứt quãng luồng suy nghĩ (flow) của bạn. Khi các công cụ này chạy trong CI/CD pipeline, chúng thường chiếm dụng CPU trong vài phút, làm chậm quá trình triển khai và tăng chi phí hạ tầng cloud.

Quản lý một toolchain rời rạc gây ra gánh nặng về tư duy không cần thiết. Theo truyền thống, chúng ta dùng ESLint cho logic và Prettier cho thẩm mỹ. Vì chúng hoạt động độc lập nên thường xuyên xảy ra xung đột. Tôi không nhớ nổi mình đã phải cài đặt eslint-config-prettier bao nhiêu lần chỉ để ngăn hai công cụ này tranh cãi về việc có nên để dấu phẩy cuối (trailing comma) hay không.

Nợ kỹ thuật của các công cụ dựa trên JavaScript

Stack tiêu chuẩn gồm ESLint và Prettier được xây dựng trên Node.js. Dù JavaScript rất tuyệt để xây dựng ứng dụng, nhưng nó gặp khó khăn với các tác vụ nặng như xử lý Cây cú pháp trừu tượng (AST) khổng lồ. Mỗi khi bạn chạy kiểm tra, ESLint sẽ parse mã nguồn của bạn. Sau đó, Prettier lại parse một lần nữa. Nếu dùng TypeScript, bước parse thứ ba thường xuyên xảy ra. Công việc dư thừa này là lý do tại sao quạt CPU của bạn quay vù vù mỗi khi lưu file.

Sự phình to của dependency (dependency bloat) cũng là một “kẻ sát nhân thầm lặng”. Một dự án React tiêu chuẩn thường yêu cầu từ 15 đến 20 package khác nhau chỉ để xử lý linting cơ bản, hooks và các quy tắc accessibility. Việc bảo trì mạng lưới node_modules này là một cực hình. Nó cũng làm tăng thời gian khởi động (cold-start) của quá trình linting, khiến việc phản hồi “tức thì” trở nên bất khả thi.

Biome và Stack truyền thống

Biome (trước đây là Rome) giải quyết vấn đề này bằng cách hợp nhất các tác vụ vào một công cụ duy nhất được viết bằng Rust. Nó không chỉ làm khác đi; nó làm hiệu quả hơn bằng cách sử dụng một parser duy nhất cho mọi tác vụ.

Sự khác biệt chính về hiệu suất

  • ESLint + Prettier: Các công cụ này thường chạy trên một thread duy nhất và yêu cầu quét qua mã nguồn nhiều lần.
  • Biome: Được xây dựng bằng Rust, nó cực kỳ tối ưu cho việc chạy song song theo mặc định. Nó xử lý linting, formatting và sắp xếp import chỉ trong một lần quét duy nhất trên tất cả các lõi CPU.

Kết quả trong các dự án thực tế rất đáng kinh ngạc. Trong một dự án TypeScript mà tôi quản lý với khoảng 500 file, tổng thời gian cho linting và formatting đã giảm từ 18 giây xuống chỉ còn 0,45 giây. Tốc độ này biến công cụ từ một việc vặt bạn phải làm trước khi commit thành một vòng lặp phản hồi tức thì giúp bạn luôn tập trung.

Ưu và nhược điểm khi chuyển đổi

Ưu điểm

  • Tốc độ cực nhanh: Hiệu suất tăng từ 20 đến 25 lần so với thiết lập hiện tại.
  • Cấu hình gọn gàng: Bạn có thể xóa .eslintrc, .prettierrc, và .eslintignore. Mọi thứ nằm gọn trong một file biome.json.
  • Cấu hình mặc định hợp lý: Biome tuân theo các tiêu chuẩn hiện đại ngay khi cài đặt, vì vậy bạn không cần tốn hàng giờ để tranh luận về các quy tắc cấu hình.
  • Tất cả trong một: Xử lý formatting, linting và sắp xếp import mà không cần plugin bổ sung.

Đánh đổi

  • Hệ sinh thái Plugin: Biome không hỗ trợ hàng ngàn plugin ESLint ngách hiện có. Nếu bạn sử dụng các quy tắc framework đặc thù, hãy kiểm tra khả năng tương thích trước.
  • Độ chín muồi: Đây là một dự án mới hơn. Dù đã sẵn sàng cho môi trường production, nhưng tài nguyên cộng đồng vẫn nhỏ hơn hệ sinh thái ESLint đã có tuổi đời cả thập kỷ.

Thiết lập tinh gọn cho TypeScript

Biome là sự lựa chọn hoàn hảo cho TypeScript. Nó parse cú pháp TypeScript và JSX một cách nguyên bản (natively), nghĩa là cuối cùng bạn có thể gỡ cài đặt @typescript-eslint/parser và các gánh nặng đi kèm. Mục tiêu của tôi cho bất kỳ cuộc di chuyển nào là loại bỏ càng nhiều “code trung gian” (glue code) càng tốt.

Hướng dẫn chuyển đổi từng bước

Thực hiện các bước sau để dọn dẹp dự án và tích hợp Biome.

Bước 1: Cài đặt Biome

Thêm Biome làm development dependency. Sử dụng flag --save-exact để đảm bảo toàn bộ nhóm sử dụng cùng một phiên bản, tránh sai lệch về formatting.

npm install --save-dev --save-exact @biomejs/biome

Bước 2: Khởi tạo cấu hình

Tạo file biome.json bằng một lệnh duy nhất.

npx biome init

Lệnh này tạo ra một cấu hình cơ bản. Dưới đây là một ví dụ đã được kiểm chứng qua thực tế, tương thích với các style chuẩn của Prettier:

{
  "$schema": "https://biomejs.dev/schemas/1.8.3/schema.json",
  "organizeImports": {
    "enabled": true
  },
  "linter": {
    "enabled": true,
    "rules": {
      "recommended": true
    }
  },
  "formatter": {
    "enabled": true,
    "indentStyle": "space",
    "indentWidth": 2,
    "lineWidth": 80
  }
}

Bước 3: Loại bỏ các package cũ

Bây giờ là phần tuyệt nhất: xóa bỏ sự cồng kềnh. Bạn có thể an tâm gỡ các package sau nếu chuyển hẳn sang Biome:

npm uninstall eslint prettier eslint-plugin-react eslint-config-prettier @typescript-eslint/eslint-plugin @typescript-eslint/parser

Sau khi chạy lệnh này, hãy xóa các file cấu hình cũ để giữ cho thư mục gốc luôn sạch sẽ.

Bước 4: Cập nhật Scripts

Thay thế các lệnh linting cũ trong package.json. Lệnh check sẽ là người bạn thân mới của bạn—nó thực hiện linting, formatting và sắp xếp import chỉ trong một lần chạy.

"scripts": {
  "check": "biome check --apply ./src",
  "check:ci": "biome check ./src",
  "format": "biome format ./src --write"
}

Bước 5: Cấu hình VS Code

Cài đặt extension Biome từ marketplace. Để biến nó thành công cụ chính, hãy cập nhật file .vscode/settings.json của bạn:

{
  "[typescript]": {
    "editor.defaultFormatter": "biomejs.biome"
  },
  "editor.codeActionsOnSave": {
    "source.organizeImports.biome": "explicit",
    "quickfix.biome": "explicit"
  }
}

Kết quả thực tế: Tác động đến CI Pipeline

Khi tôi chuyển đổi một dashboard doanh nghiệp lớn sang Biome, kết quả là không thể phủ nhận. Bước “Lint and Format” trong CI pipeline của chúng tôi đã giảm từ 2 phút 45 giây xuống chỉ còn 7 giây. Điều thú vị là phần lớn trong 7 giây đó chỉ dành cho việc khởi tạo môi trường CI. Việc phân tích code thực tế mất chưa đầy một giây.

Ngoài tốc độ thô, chúng tôi không còn thấy các “dấu gạch chân đỏ” xung đột nhau nữa. Vì Biome là một engine thống nhất, nó không đưa ra các cảnh báo mâu thuẫn. Nếu nó báo lỗi, đó là vấn đề thực sự, không phải do sự sai lệch cấu hình giữa hai công cụ khác nhau.

Lời kết

Rời bỏ ESLint và Prettier có vẻ là một bước đi lớn vì sự phổ biến của chúng. Tuy nhiên, ngành công nghiệp đang chuyển hướng sang các công cụ Rust hiệu suất cao như Vite và Biome là có lý do. Bằng cách đơn giản hóa stack của mình, bạn sẽ lấy lại được thời gian lãng phí cho việc bảo trì và chờ đợi các thanh tiến trình tải.

Nếu bạn bắt đầu một dự án mới hôm nay, hãy chọn Biome làm mặc định. Đối với các dự án hiện có, việc chuyển đổi đủ đơn giản để hoàn thành trong giờ nghỉ trưa, và phần thưởng về hiệu suất sẽ xứng đáng mỗi khi bạn nhấn lưu.

Share: