Bài này học các mô-đun lõi dùng hằng ngày: đọc ghi tệp và thư mục với node:fs/promises, xử lý đường dẫn đa nền tảng với node:path, đối tượng process, tham số dòng lệnh và biến môi trường để giữ bí mật cấu hình.
- Đọc, ghi, nối, xóa tệp; làm việc với thư mục
- Ghép đường dẫn an toàn với path, import.meta.dirname
- Dùng process.argv, process.env, process.exit
- Nạp tệp .env bằng --env-file
Một số khái niệm
Luôn dùng phiên bản Promise (node:fs/promises) với async/await thay vì hàm đồng bộ (readFileSync) trong máy chủ, vì hàm đồng bộ chặn mọi yêu cầu khác. Thông tin bí mật (mật khẩu CSDL, khóa API) đặt trong biến môi trường, không ghi vào mã.
Tệp và thư mục
import { readFile, writeFile, appendFile, mkdir, readdir, rm, stat } from 'node:fs/promises';
import path from 'node:path';
const thuMuc = path.join(import.meta.dirname, 'data');
await mkdir(thuMuc, { recursive: true });
const tep = path.join(thuMuc, 'sinhvien.json');
await writeFile(tep, JSON.stringify([{ ma: 'SV001', ten: 'Lò Văn An' }], null, 2));
const ds = JSON.parse(await readFile(tep, 'utf8'));
ds.push({ ma: 'SV002', ten: 'Cầm Thị Bình' });
await writeFile(tep, JSON.stringify(ds, null, 2));
await appendFile(path.join(thuMuc, 'nhat-ky.log'), `${new Date().toISOString()} Đã thêm SV002\n`);
for (const ten of await readdir(thuMuc)) {
const s = await stat(path.join(thuMuc, ten));
console.log(ten, s.size, 'byte');
}path.join tự dùng đúng dấu phân cách (\ trên Windows, / trên macOS/Linux); import.meta.dirname là thư mục chứa tệp hiện tại.
Biến môi trường và .env
# .env (thêm vào .gitignore)
PORT=3000
DB_HOST=localhost
DB_USER=root
DB_PASS=
DB_NAME=qlsv
JWT_SECRET=chuoi-bi-mat-dai-ngau-nhien// server.js
const port = Number(process.env.PORT ?? 3000);
if (!process.env.JWT_SECRET) {
console.error('Thiếu JWT_SECRET'); process.exit(1);
}node --env-file=.env server.js # Node.js nạp .env, không cần gói dotenvprocess và tham số dòng lệnh
// doi-ten.js: node doi-ten.js ./anh .jpg
import { parseArgs } from 'node:util';
const { positionals, values } = parseArgs({ allowPositionals: true, options: { 'thu': { type: 'boolean' } } });
const [thuMuc = '.', duoi = '.jpg'] = positionals;
console.log('Thư mục:', thuMuc, 'đuôi:', duoi, 'chạy thử:', values.thu ?? false);
console.log('Bộ nhớ đang dùng:', Math.round(process.memoryUsage().rss / 1e6), 'MB');
process.on('SIGINT', () => { console.log('Đã dừng'); process.exit(0); });Tạo tệp .env.example liệt kê tên biến (không có giá trị thật) và commit lên Git để đồng đội biết cần cấu hình gì.
Nối đường dẫn từ dữ liệu người dùng (tên tệp tải lên, tham số URL) có thể bị tấn công path traversal (../../etc/passwd); luôn kiểm tra kết quả nằm trong thư mục cho phép.
- Viết công cụ đổi tên hàng loạt ảnh trong thư mục theo ngày.
- Lưu danh sách sinh viên vào tệp JSON, thêm và xóa phần tử.
- Ghi nhật ký mỗi lần chạy chương trình.
- Đọc cấu hình cổng, CSDL từ .env bằng --env-file.
- node:fs/promises + async/await cho tệp, thư mục.
- path.join, import.meta.dirname cho đường dẫn.
- process.env + --env-file cho bí mật; .env vào .gitignore.
- process.argv, util.parseArgs cho công cụ dòng lệnh.