
Chào các Gen Z mê code và thích "hack" mọi thứ! Anh Creyt đây, và hôm nay chúng ta sẽ cùng "đào" một khái niệm mà nghe thì tưởng "cổ lỗ sĩ" nhưng lại là nền tảng vững chắc cho mọi dự án Node.js của các bạn: __dirname. Nghe tên đã thấy "bí ẩn" rồi đúng không? Đừng lo, anh sẽ làm cho nó dễ hiểu hơn cả việc bạn lướt TikTok xem mèo vờn chỉ trong 5 phút.
__dirname: GPS Cá Nhân Của Script Bạn
Tưởng tượng thế này, bạn là một nhà thám hiểm tài ba trong khu rừng code Node.js rộng lớn. Mỗi file script của bạn là một "trạm dừng chân" riêng biệt. Đôi khi, bạn cần tìm đường đến cái "kho báu" (một file cấu hình, một thư mục chứa hình ảnh) mà bạn biết chắc chắn nó nằm ngay bên cạnh trạm dừng chân hiện tại của bạn. Nhưng làm sao để biết "ngay bên cạnh" nghĩa là ở đâu trong cái bản đồ rừng rậm đó?
Đó chính là lúc __dirname xuất hiện, như một chiếc GPS mini tích hợp sẵn trong túi áo của mỗi script Node.js (trong môi trường CommonJS). Nó không làm gì cao siêu cả, chỉ đơn giản là mách cho bạn biết đường dẫn tuyệt đối (absolute path) đến cái thư mục đang chứa file script mà bạn đang chạy.
- Nó là gì? Một biến toàn cục (global variable) tự động có mặt trong mọi module Node.js theo chuẩn CommonJS (cái chuẩn
require()ấy). - Nó để làm gì? Để bạn có thể định vị chính xác "căn cứ" của script hiện tại, từ đó dễ dàng tìm đến các tài nguyên khác nằm cùng hoặc trong các thư mục con của nó, bất kể bạn chạy script đó từ đâu trong hệ thống.
- Ví dụ trực quan: Nếu file
server.jscủa bạn nằm trong/home/user/project/src/server.js, thì__dirnametrongserver.jssẽ là/home/user/project/src. Đơn giản vậy thôi!
Code Ví Dụ Minh Họa: "Dắt Tay Chỉ Việc" Cùng __dirname
Hãy tạo một cấu trúc thư mục nhỏ để dễ hình dung nhé.
my-project/
├── index.js
└── data/
└── config.json
File my-project/data/config.json:
{
"appName": "Awesome App",
"version": "1.0.0"
}
File my-project/index.js:
const path = require('path');
const fs = require('fs');
console.log('1. __dirname của script hiện tại:', __dirname);
// Giả sử bạn muốn đọc file config.json nằm trong thư mục 'data'
// Cách KHÔNG NÊN làm (vì dễ sai trên các OS khác nhau):
// const configPathBad = __dirname + '/data/config.json';
// console.log('Đường dẫn nối chuỗi (Bad):', configPathBad);
// Cách NÊN làm: Dùng path.join() để xây dựng đường dẫn an toàn
const configFilePath = path.join(__dirname, 'data', 'config.json');
console.log('2. Đường dẫn file config chuẩn chỉnh:', configFilePath);
try {
const configFileContent = fs.readFileSync(configFilePath, 'utf8');
console.log('3. Nội dung file config đọc được:\n', JSON.parse(configFileContent));
} catch (error) {
console.error('Lỗi khi đọc file config:', error.message);
}
// So sánh với process.cwd() - "Bạn đang đứng ở đâu khi gõ lệnh?"
console.log('4. process.cwd() (thư mục bạn chạy lệnh Node từ đó):', process.cwd());
// Thử tạo một file mới trong thư mục 'logs' (nếu chưa có)
const logsDir = path.join(__dirname, 'logs');
if (!fs.existsSync(logsDir)) {
fs.mkdirSync(logsDir);
}
const logFilePath = path.join(logsDir, 'app.log');
fs.writeFileSync(logFilePath, `Ứng dụng khởi động lúc: ${new Date().toISOString()}\n`, { flag: 'a' });
console.log('5. Đã ghi log vào:', logFilePath);
Khi bạn chạy node index.js từ thư mục my-project/ hoặc bất kỳ đâu, __dirname sẽ luôn trỏ đến /path/to/my-project. Điều này đảm bảo script của bạn luôn tìm thấy data/config.json một cách chính xác.

Mẹo "Hack" Nhanh & Best Practices Của Dân Pro
- "Không nối chuỗi, hãy
path.join()!": Đây là kinh nghiệm xương máu của anh Creyt. Đừng bao giờ tự nối các phần của đường dẫn bằng dấu/hay\. Hãy luôn dùngpath.join(__dirname, 'thư_mục', 'tên_file.ext'). Modulepathcủa Node.js sẽ tự động xử lý dấu phân cách đường dẫn (slash hay backslash) phù hợp với hệ điều hành đang chạy, tránh các bug "trời ơi đất hỡi" khi deploy lên server Linux trong khi bạn code trên Windows. __dirnamevs.process.cwd(): Hai khái niệm, hai "vị trí" khác nhau:__dirname: Luôn là đường dẫn đến thư mục chứa file script đang chạy. Nó cố định.process.cwd(): Là đường dẫn đến thư mục mà bạn chạy lệnhnodetừ đó. Nó có thể thay đổi tùy thuộc vào vị trí bạn gõ lệnh trong terminal. Hãy nhớ:__dirnamelà "địa chỉ nhà" của script, cònprocess.cwd()là "vị trí hiện tại của bạn trên bản đồ" khi bạn bắt đầu một hành trình.
- Thế hệ mới:
import.meta.urlcho ES Modules (ESM):- Trong tương lai, khi bạn dùng ES Modules (với cú pháp
import/export),__dirnamesẽ không còn tồn tại nữa. - Thay vào đó, bạn sẽ dùng
import.meta.url(trả về đường dẫn URL của module hiện tại) và kết hợp với moduleurlvàpathđể lấy đường dẫn thư mục. - Cách làm:
import path from 'path'; import { fileURLToPath } from 'url'; const __filename = fileURLToPath(import.meta.url); const __dirname_esm = path.dirname(__filename); console.log('__dirname trong ESM:', __dirname_esm); - Hãy làm quen với nó sớm nhé!
- Trong tương lai, khi bạn dùng ES Modules (với cú pháp
Góc Học Thuật "Harvard" (nhưng vẫn dễ hiểu)
Tại sao Node.js lại cung cấp __dirname? Nó không phải là một sự ngẫu nhiên, mà là một thiết kế có chủ đích, gắn liền với nguyên tắc của module system (hệ thống module) trong Node.js.
Trong CommonJS, mỗi file là một module riêng biệt. Khi bạn require() một module, Node.js cần biết chính xác file đó nằm ở đâu để tải nó. __dirname đảm bảo rằng mỗi module có thể tự xác định vị trí của mình một cách độc lập và nhất quán, không phụ thuộc vào "context" bên ngoài (tức là bạn chạy lệnh node từ đâu). Điều này mang lại sự ổn định (stability) và khả năng tái sử dụng (reusability) cao cho các module.
Nó giống như việc mỗi công dân đều có một chứng minh thư ghi rõ địa chỉ thường trú. Dù bạn đi đâu, chứng minh thư vẫn luôn chỉ về đúng địa chỉ nhà của bạn, giúp bạn tìm đường về hoặc chỉ dẫn người khác đến nhà mình một cách đáng tin cậy.
Ứng Dụng Thực Tế: __dirname Ở Khắp Mọi Nơi!
__dirname là một "người hùng thầm lặng" có mặt trong hầu hết các dự án Node.js lớn nhỏ:
- Express.js (Web Servers): Đây là ví dụ kinh điển nhất. Khi bạn muốn phục vụ các file tĩnh (HTML, CSS, JS, hình ảnh) từ một thư mục
public, bạn sẽ dùng:
Nó đảm bảo rằng dù bạn deploy ứng dụng của mình ở đâu, Express vẫn tìm thấy thư mụcapp.use(express.static(path.join(__dirname, 'public')));publicmột cách chính xác. - Load Configuration Files: Các ứng dụng thường có file cấu hình (ví dụ:
config.json,.env) nằm cạnh file khởi động.__dirnamegiúp bạn đọc các file này dễ dàng:const config = require(path.join(__dirname, 'config.json')); - Templating Engines: Các engine như Pug, EJS, Handlebars... thường cần biết đường dẫn đến thư mục chứa các template của bạn.
- Database Migration/Seeding: Các công cụ quản lý database schema thường dùng
__dirnameđể tìm các script migration hoặc seed data. - Logging: Ghi log vào một file trong thư mục
logsnằm cạnh ứng dụng.
Nên Dùng Khi Nào & Những "Cạm Bẫy" Cần Tránh
Nên dùng __dirname khi:
- Bạn cần truy cập các tài nguyên (file, thư mục) mà vị trí của chúng là cố định và tương đối so với file script hiện tại của bạn.
- Bạn muốn đảm bảo ứng dụng của bạn hoạt động ổn định và tìm thấy các tài nguyên cần thiết, bất kể người dùng chạy lệnh
nodetừ thư mục nào. Đây là trường hợp phổ biến nhất cho các ứng dụng server-side, API, hoặc các module thư viện.
Cần cẩn thận (hoặc không nên dùng) khi:
- Bạn cần đường dẫn đến thư mục mà người dùng chạy lệnh từ đó (dùng
process.cwd()thay thế). Ví dụ, bạn đang viết một công cụ CLI mà người dùng muốn nó thao tác trên các file trong thư mục hiện tại của họ. - Bạn đang viết một ES Module và muốn tương thích với chuẩn mới. Hãy chuyển sang dùng
import.meta.urlnhư đã hướng dẫn ở trên.
Cạm bẫy cần tránh:
- Quên
path.join(): Luôn nhớ dùng nó để tránh lỗi đường dẫn trên các hệ điều hành khác nhau. - Nhầm lẫn với
process.cwd(): Hiểu rõ sự khác biệt để chọn đúng "vị trí" bạn cần. - Cố gắng dùng trong ES Modules: Sẽ báo lỗi
__dirname is not defined. Hãy chuyển sangimport.meta.url.
Vậy đó, __dirname không chỉ là một biến đơn thuần, nó là một công cụ mạnh mẽ giúp bạn xây dựng các ứng dụng Node.js vững chắc và đáng tin cậy. Nắm vững nó, và bạn đã có thêm một siêu năng lực để "càn quét" mọi project rồi đấy các Gen Z! Hẹn gặp lại trong bài học tiếp theo!
Thuộc Series: Nodejs
Bài giảng này được tự động xuất bản ngẫu nhiên từ thư viện kiến thức. Đừng quên đón xem các Từ khoá Hướng Dẫn tiếp theo nhé!