[Series yargs - Bài 1] Giới thiệu và Cẩm nang "Nhập Môn" yargs cho Node.js
Chào các bạn! Là một lập trình viên, chắc hẳn bạn đã không ít lần gõ những dòng lệnh như git commit -m "update", npm install react hay docker-compose up. Đã bao giờ bạn tự hỏi: "Làm sao để tự tay viết ra một công cụ dòng lệnh xịn sò như vậy bằng Node.js chưa?"
Theo mặc định, Node.js cung cấp cho chúng ta mảng process.argv để đọc các tham số truyền vào từ terminal. Nhưng tin mình đi, việc tự parse (phân tích) cái mảng đó bằng tay để tìm ra đâu là tham số, đâu là cờ (flags), đâu là giá trị... là một cơn ác mộng.
Đó là lý do yargs ra đời. Trong series này, chúng ta sẽ cùng nhau học cách sử dụng yargs để xây dựng những CLI tools chuyên nghiệp, có cấu trúc rõ ràng và tự động sinh ra menu hướng dẫn (Help menu) cực kỳ đẹp mắt.
1. Tại sao lại chọn yargs?
Trong giới làm CLI với Node.js, có 2 thư viện nổi tiếng nhất là commander và yargs. Điểm khiến mình "mê mẩn" yargs hơn nằm ở:
- Cú pháp cực kỳ tự nhiên: Việc định nghĩa các lệnh (commands) và tham số (options) có thể được xâu chuỗi (chaining) rất gọn gàng.
- Tự động tạo Document: Bạn không cần phải viết file README quá dài. Cứ gõ --help, yargs sẽ tự động in ra màn hình hướng dẫn sử dụng chi tiết dựa trên code của bạn.
- Parse thông minh: Tự động nhận diện kiểu dữ liệu (boolean, number, array) chỉ qua cách người dùng gõ trên terminal.
2. Khởi tạo dự án và Cài đặt
Hãy tạo một thư mục mới cho series này và cài đặt yargs:
mkdir yargs-series
cd yargs-series
npm init -y
npm install yargs
3. "Hello World" với yargs
Hãy tạo một file tên là app.js. Chúng ta sẽ viết một script đơn giản: Yêu cầu người dùng nhập tên, và CLI sẽ gửi lời chào.
// file: app.js
const yargs = require('yargs');
const { hideBin } = require('yargs/helpers');
// hideBin dùng để ẩn 2 phần tử đầu tiên của process.argv (đường dẫn tới node và file script)
const argv = yargs(hideBin(process.argv))
.option('name', {
alias: 'n', // Tên viết tắt (ví dụ: -n thay vì --name)
type: 'string', // Kiểu dữ liệu
description: 'Tên của bạn để chương trình gửi lời chào', // Mô tả hiện trong phần --help
demandOption: true, // Bắt buộc phải nhập tham số này
})
.parse(); // Bắt đầu phân tích cú pháp
console.log(`👋 Chào mừng ${argv.name} đến với thế giới CLI!`);
Cách chạy thử trên Terminal:
- Chạy đúng: ```bash node app.js --name "Hoàng"
Hoặc dùng alias: node app.js -n "Hoàng"
Kết quả: 👋 Chào mừng Hoàng đến với thế giới CLI!
- Chạy sai (quên truyền tham số):
node app.js
Ngay lập tức, yargs sẽ báo lỗi cực kỳ chuyên nghiệp:
Missing required argument: name
- Gọi Menu hướng dẫn (--help): Điều tuyệt vời nhất đây rồi! Gõ:
node app.js --help
Kết quả:
Options:
--help Show help [boolean]
--version Show version number [boolean]
-n, --name Tên của bạn để chương trình gửi lời chào [string] [required]
4. Thiết lập lệnh (Command) cơ bản
CLI xịn không bao giờ chỉ có các tham số (options). Nó phải có các lệnh (commands) cụ thể, giống như cách git có git add, git commit.
Hãy nâng cấp app.js lên một chút:
const yargs = require('yargs');
const { hideBin } = require('yargs/helpers');
yargs(hideBin(process.argv))
// Lệnh thứ nhất: hello
.command({
command: 'hello',
describe: 'Gửi lời chào tới một người',
builder: {
name: {
describe: 'Tên người cần chào',
demandOption: true,
type: 'string'
}
},
handler: (argv) => {
console.log(`🚀 Xin chào ${argv.name}! Chúc một ngày tốt lành.`);
}
})
// Lệnh thứ hai: add
.command({
command: 'add',
describe: 'Cộng hai số',
builder: {
a: { type: 'number', demandOption: true },
b: { type: 'number', demandOption: true }
},
handler: (argv) => {
console.log(`🧮 Kết quả: ${argv.a} + ${argv.b} = ${argv.a + argv.b}`);
}
})
.strict() // Báo lỗi nếu người dùng gõ sai tên lệnh
.help()
.parse();
Chạy thử:
node app.js add --a 10 --b 15
# Kết quả: 🧮 Kết quả: 10 + 15 = 25
Tổng kết Bài 1
Vậy là chỉ với vài dòng code, chúng ta đã có một công cụ dòng lệnh thực thụ, có phân chia Command rõ ràng, có validate kiểu dữ liệu và tự động sinh Document. yargs đã làm hộ chúng ta 90% công việc nhàm chán nhất.
Ở Bài 2, chúng ta sẽ đi sâu hơn vào việc tổ chức source code sao cho sạch đẹp khi số lượng command tăng lên (không ai viết dồn hết vào app.js cả), và cách tùy biến giao diện của menu --help cho thật "ngầu".
Hẹn gặp lại các bạn trong bài viết tiếp theo!
All rights reserved