
Chào các Gen Z, hôm nay anh Creyt sẽ giải mã một khái niệm mà nhiều khi các em cứ nghĩ nó là 'phụ tùng' nhưng thực ra nó lại là 'xương sống' cho quá trình phát triển của chúng ta: devDependencies trong Node.js.
Hãy hình dung thế này: Em đang làm một bộ phim bom tấn, đúng không?
dependencies(những gói thư viện nằm trong fielddependencies): Đó là dàn diễn viên chính, đạo diễn, kịch bản, máy quay, ánh sáng... Tóm lại, những thứ BẮT BUỘC phải có mặt trong bản phim cuối cùng để khán giả xem và trầm trồ. Thiếu một trong số đó, phim không ra phim.devDependencies(những gói thư viện nằm trong fielddevDependencies): Còn đây là đội hậu cần siêu đẳng của em: từ anh chị make-up, stylist, đội catering (lo cơm nước), cho đến anh đạo cụ, chuyên gia dựng phông xanh, hay thậm chí là mấy anh chị trợ lý đạo diễn. Họ cực kỳ quan trọng để quá trình quay phim diễn ra suôn sẻ, nhưng khi bộ phim hoàn thành và ra rạp, khán giả có thấy xe chở cơm hay hộp phấn của diễn viên trên màn hình không? KHÔNG! Công việc của họ là hỗ trợ cho quá trình SẢN XUẤT, chứ không phải là một phần của SẢN PHẨM CUỐI CÙNG.
Vậy devDependencies chính là những công cụ, thư viện mà chúng ta chỉ cần dùng trong quá trình phát triển và kiểm thử dự án Node.js của mình. Khi sản phẩm đã "đóng gói" xong xuôi để chạy thật, chúng ta không cần chúng nữa.
devDependencies Là Gì? Tại Sao Lại Quan Trọng?
Từ góc độ học thuật mà nói, devDependencies là một trường (field) trong file package.json của một dự án Node.js, được quản lý bởi npm (Node Package Manager) hoặc yarn. Nó chứa danh sách các gói (packages) mà ứng dụng của bạn cần để:
- Phát triển (Development): Ví dụ như các công cụ biên dịch (transpilers) như Babel để chuyển đổi code ES6+ sang ES5, hoặc các server phát triển (development servers) như
webpack-dev-server. - Kiểm thử (Testing): Các framework kiểm thử như Jest, Mocha, Chai, hay các thư viện hỗ trợ kiểm thử như Supertest.
- Xây dựng (Building/Bundling): Các công cụ đóng gói (bundlers) như Webpack, Rollup, hoặc các task runner như Gulp.
- Linter/Formatter: Các công cụ kiểm tra chất lượng code như ESLint, Prettier.
Mục tiêu chính của việc phân biệt dependencies và devDependencies là để tối ưu hóa kích thước gói ứng dụng khi triển khai (deployment). Khi bạn cài đặt các gói cho môi trường sản phẩm (production environment) bằng lệnh npm install --production (hoặc npm ci --production), npm sẽ chỉ cài đặt các gói trong dependencies, bỏ qua devDependencies. Điều này giúp giảm đáng kể dung lượng của ứng dụng, tăng tốc độ cài đặt và giảm rủi ro bảo mật không cần thiết từ các gói chỉ dùng cho phát triển.

Code Ví Dụ Minh Họa Rõ Ràng
Nói suông thì khó hình dung, mình cùng xem ví dụ thực tế nhé.
Giả sử em có một file package.json như sau:
{
"name": "my-awesome-app",
"version": "1.0.0",
"description": "A simple Node.js application",
"main": "index.js",
"scripts": {
"start": "node index.js",
"test": "jest",
"build": "webpack"
},
"dependencies": {
"express": "^4.17.1",
"mongoose": "^6.0.12"
},
"devDependencies": {
"jest": "^27.3.1",
"webpack": "^5.61.0",
"webpack-cli": "^4.9.1",
"eslint": "^8.0.1",
"prettier": "^2.4.1"
}
}
Ở đây:
expressvàmongooselàdependenciesvì chúng là thư viện cần thiết để ứng dụng chạy khi đã triển khai.jest(để chạy test),webpackvàwebpack-cli(để đóng gói code),eslintvàprettier(để kiểm tra và định dạng code) làdevDependencies. Chúng ta chỉ cần chúng khi đang code, test, hoặc build dự án, chứ không phải khi ứng dụng đã chạy trên server sản phẩm.
Cách cài đặt:
- Để cài đặt một
dependency(ví dụ:axios):
Lệnh này sẽ tự động thêmnpm install axios # hoặc npm i axiosaxiosvào trườngdependenciestrongpackage.json. - Để cài đặt một
devDependency(ví dụ:nodemon- một công cụ giúp tự động khởi động lại server khi code thay đổi):
Lệnh này sẽ thêmnpm install nodemon --save-dev # hoặc npm i nodemon -Dnodemonvào trườngdevDependenciestrongpackage.json.
Mẹo Hay và Best Practices Cho devDependencies
Để nhớ và dùng devDependencies hiệu quả, anh Creyt có vài mẹo nhỏ cho các em:
- Quy tắc 'Deployment Test': Hãy tự hỏi: 'Liệu ứng dụng của mình có chạy được trên server sản phẩm nếu thiếu gói này không?' Nếu câu trả lời là CÓ (vẫn chạy được, chỉ là quá trình phát triển/kiểm thử khó hơn), thì đó là
devDependency. Nếu KHÔNG (ứng dụng lỗi ngay lập tức), thì đó làdependency. - Giảm thiểu 'Gánh nặng': Luôn cố gắng giữ
devDependenciestách biệt. Điều này không chỉ giúp giảm kích thước gói ứng dụng mà còn giảm thiểu rủi ro về lỗ hổng bảo mật từ các thư viện không cần thiết trên môi trường sản phẩm. - Sử dụng
npm cicho CI/CD: Trong các hệ thống Tích hợp Liên tục/Triển khai Liên tục (CI/CD), hãy dùngnpm cithay vìnpm install.npm ciđảm bảo rằng bạn cài đặt chính xác các phiên bản đã được ghi trongpackage-lock.json, giúp quá trình build ổn định và đáng tin cậy hơn, đặc biệt hữu ích khi chỉ cài đặtdependenciestrên môi trường sản xuất. - Đồng bộ team: Đảm bảo toàn bộ team dev hiểu rõ và tuân thủ quy tắc phân loại này. Tránh tình trạng người này cài
-D, người kia quên, dẫn đếnpackage.jsonlộn xộn.
Ứng Dụng Thực Tế và Case Sử Dụng
Hầu hết các dự án Node.js lớn nhỏ, từ các framework web như Express.js, NestJS cho đến các công cụ dựng frontend như Create React App, Next.js, hay các thư viện như Lodash, React, đều sử dụng triệt để devDependencies.
- Create React App (CRA): Khi bạn tạo một dự án React bằng CRA, bạn sẽ thấy rất nhiều
devDependenciesnhưreact-scripts,eslint,babel-jest,webpack(ẩn đi) – tất cả đều là công cụ để giúp bạn phát triển và build ứng dụng React, chứ bản thân chúng không chạy trực tiếp trong ứng dụng cuối cùng của người dùng. - Các dự án mã nguồn mở trên GitHub: Em cứ thử vào bất kỳ dự án Node.js nào có
package.jsontrên GitHub, lướt xuống phầndevDependenciesmà xem. Em sẽ thấy một 'khu vườn' đầy đủ các công cụ test, linter, builder mà họ dùng để duy trì chất lượng code. Ví dụ, dự án Vue.js hay React cũng có một danh sáchdevDependenciesrất dài để phục vụ quá trình phát triển nội bộ.
Anh Creyt đã từng chứng kiến không ít dự án, đặc biệt là các dự án 'mì ăn liền' hoặc của các dev mới, nhét tất cả mọi thứ vào dependencies. Hậu quả là gì?
- Kích thước gói ứng dụng phình to: Một dự án nhỏ chỉ vài chục MB có thể biến thành vài trăm MB chỉ vì kéo theo cả đống công cụ test, linter không cần thiết.
- Thời gian cài đặt lâu hơn: Mỗi lần deploy, server phải tải về và cài đặt cả những gói không dùng đến.
- Rủi ro bảo mật: Càng nhiều gói, càng nhiều 'cửa ngõ' tiềm năng cho các lỗ hổng bảo mật, dù là gói chỉ dùng cho dev.
Vậy nên dùng devDependencies cho các case nào?
- Công cụ kiểm thử: Jest, Mocha, Cypress, Supertest...
- Công cụ biên dịch/chuyển đổi: Babel (cùng với các preset và plugin), TypeScript compiler (
tsc). - Công cụ đóng gói/xây dựng: Webpack, Rollup, Parcel, Gulp, Grunt.
- Công cụ kiểm tra chất lượng code/định dạng: ESLint, Prettier, Stylelint.
- Công cụ server phát triển:
nodemon,webpack-dev-server. - Thư viện hỗ trợ phát triển/debug:
debug(nếu chỉ dùng cho dev),chokidar(nếu chỉ dùng để watch file trong dev).
Tóm lại, devDependencies không phải là 'phụ' mà là 'trợ lý đắc lực' giúp quá trình phát triển của em mượt mà hơn, đồng thời giữ cho sản phẩm cuối cùng của em 'thon gọn' và an toàn hơn. Hãy dùng chúng một cách thông minh, các Gen Z nhé!
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é!