+2

Nghệ Thuật Viết Tool CLI: Tạm Biệt Mớ Hỗn Độn process.argv Cùng yargs

Chuyện kể rằng, có một ngày đẹp trời, Tech Lead giao cho mình viết một cái script Node.js để dọn dẹp data rác trong Database. Yêu cầu là script phải nhận vào các tham số để biết nên dọn dẹp ở môi trường nào, và có bật chế độ "xóa thật" hay không.

Mình hồn nhiên gõ lệnh chạy:

node cleanup.js --env=production --force

Sau đó, ở trong code, mình viết một đoạn logic đầy "mồ hôi nước mắt" như thế này để hứng tham số:

// Tư duy "thợ gõ" - Khổ dâm với process.argv
const args = process.argv.slice(2);
let env = 'development'; // default
let isForce = false;

args.forEach(arg => {
    if (arg.startsWith('--env=')) {
        env = arg.split('=')[1];
    }
    if (arg === '--force') {
        isForce = true;
    }
});

console.log(`Đang chạy dọn dẹp ở môi trường: ${env}, force: ${isForce}`);

Đoạn code chạy được. Nhưng cái "vibe" của nó thực sự rất... phèn! Lỡ người dùng nhập thiếu dấu =, hay họ nhập -e prod thay vì --env=production, hoặc họ nhập sai tên biến thì sao? Code của mình sẽ lủng lỗ chỗ ngay lập tức. Chưa kể, nếu sau này tool có thêm 10 tham số nữa, đoạn if...else trên sẽ biến thành một bãi rác thực sự.

Đó là lúc một Vibe Coder phải tìm đến "chân ái": Thư viện yargs.

1. yargs là gì? Kẻ gom rác siêu việt

Trong Node.js, process.argv chỉ trả về cho bạn một mảng chuỗi (Array of Strings) thô kệch. yargs là một thư viện sinh ra chỉ để làm một việc duy nhất: Nuốt trọn cái mảng chuỗi đó, phân tích ngữ nghĩa (Parse) và trả ra cho bạn một Object Javascript thơm tho, sạch sẽ.

Cài đặt cực kỳ nhanh gọn:

npm i yargs

Hãy xem yargs thổi bay đoạn code cực nhọc phía trên như thế nào:

// Tư duy Vibe Coder - Giao việc cho yargs
const yargs = require('yargs/yargs');
const { hideBin } = require('yargs/helpers');

// hideBin sẽ tự động cắt bỏ 2 phần tử thừa đầu tiên của process.argv (là đường dẫn node và tên file)
const argv = yargs(hideBin(process.argv)).argv;

console.log(argv);

Giờ thử chạy lại lệnh: node cleanup.js --env=production --force --retries 3 Kết quả argv in ra sẽ là một object hoàn hảo:

{
  _: [],
  env: 'production',
  force: true,
  retries: 3,
  '$0': 'cleanup.js'
}

Bạn không cần phải tự split('='), không cần tự ép kiểu sang số cho --retries 3, và --force tự động hiểu là biến Boolean mang giá trị true. Mọi thứ mượt mà như một phép màu!

2. Sức mạnh thực sự: Tạo tài liệu (Documentation) tự động

Một Tool CLI "chuẩn chỉ" không chỉ nhận biến đúng, mà còn phải biết Hướng dẫn sử dụng cho người khác (hoặc cho chính bạn 6 tháng sau đọc lại). Bạn đã bao giờ gõ git --help chưa? yargs cho phép bạn làm điều y hệt chỉ với vài dòng cấu hình:

const yargs = require('yargs/yargs');
const { hideBin } = require('yargs/helpers');

const argv = yargs(hideBin(process.argv))
  .usage('Sử dụng: $0 <command> [options]')
  .option('e', {
    alias: 'env',
    describe: 'Môi trường cần chạy (dev, staging, production)',
    type: 'string',
    choices: ['dev', 'staging', 'production'], // Chỉ cho phép nhập 3 chữ này
    default: 'dev' // Không nhập thì mặc định là dev
  })
  .option('f', {
    alias: 'force',
    describe: 'Bật chế độ xóa thật khỏi Database',
    type: 'boolean',
    default: false
  })
  .demandOption(['env'], 'Bạn bắt buộc phải cung cấp môi trường để chạy script!') // Ép buộc phải có
  .help('h')
  .alias('h', 'help')
  .epilog('Copyright 2026 - Vibe Coder Series')
  .argv;

console.log(`Tiến hành dọn dẹp tại: ${argv.env}`);

Bây giờ, nếu có ai đó ngơ ngác không biết dùng tool của bạn và gõ node cleanup.js --help, yargs sẽ tự động in ra màn hình terminal một bảng hướng dẫn siêu ngầu:

Sử dụng: cleanup.js <command> [options]

Options:
  --version       Hiển thị phiên bản                              [boolean]
  -e, --env       Môi trường cần chạy (dev, staging, production)  
                  [string] [choices: "dev", "staging", "production"] [default: "dev"]
  -f, --force     Bật chế độ xóa thật khỏi Database              
                  [boolean] [default: false]
  -h, --help      Hiển thị hướng dẫn sử dụng                      [boolean]

Copyright 2026 - Vibe Coder Series

3. Chia để trị với .command()

Nếu tool của bạn quá to, ví dụ một tool vừa có thể migrate (chạy script DB) vừa có thể seed (tạo data giả). Việc dồn hết tham số vào một file là sai lầm. yargs hỗ trợ thiết kế theo Command y như các công cụ chuyên nghiệp (Docker, AWS CLI...).

yargs(hideBin(process.argv))
  .command(
    'migrate [table]', // Tên lệnh
    'Chạy migration cho database', // Mô tả
    (yargs) => { // Cấu hình tham số riêng cho lệnh này
      yargs.positional('table', {
        describe: 'Tên bảng cần migrate',
        default: 'all'
      });
    }, 
    (argv) => { // Logic thực thi khi gọi lệnh
      console.log(`Đang chạy migrate cho bảng: ${argv.table}`);
    }
  )
  .demandCommand(1, 'Bạn phải cung cấp ít nhất 1 lệnh để chạy')
  .parse();

Chạy node tool.js migrate users, luồng logic sẽ tự động chui đúng vào hàm của command migrate. Kiến trúc vô cùng gọn gàng!

Lời kết

Viết code logic thì dễ, nhưng viết một cái tool để những người anh em Dev khác tải về, gõ gõ vài phím trên Terminal là chạy mượt mà, có báo lỗi khi nhập sai, có hướng dẫn chi tiết... đó mới là đẳng cấp của sự tinh tế. Lần tới, hãy quăng process.argv vào sọt rác và đưa yargs vào bộ đồ nghề mặc định của bạn nhé!

Chủ đề tiếp theo: Cơn Ác Mộng Của Node.js - Xử Lý File CSV 10GB Mà Không Bị OOM (Out Of Memory)

CLI tool của bạn đã ngon lành, bạn viết một cái script để đọc file báo cáo doanh thu (.csv) và insert vào Database. Chạy test với file 10MB, mượt. Mai khách hàng gửi cho một file data thô nặng... 10GB.

Bạn dùng fs.readFileSync('data.csv'). BÙM! Terminal hiện dòng chữ đỏ chót kinh điển: JavaScript heap out of memory. Cả cái tool vỡ vụn vì Node.js không thể nhét 10GB data vào 1.5GB RAM mặc định của nó được.

Vậy một Vibe Coder sẽ làm gì để xử lý cục data khổng lồ này mà RAM vẫn chỉ nhịp nhàng ở mức 50MB? Ở bài viết tới, mình sẽ khai mở một "ma thuật" được ẩn giấu sâu bên trong Node.js: Node.js Streams. Anh em nhớ follow để đón xem cách làm dòng chảy dữ liệu (Data Flow) mượt mà như nước cất nhé!


All Rights Reserved

Viblo
Let's register a Viblo Account to get more interesting posts.