Explore all courses in this category.
Explore all courses in this category.
Nguyễn Đình Cường
0 comment
09 Nov, 2026
Khi dự án lớn dần, nhét tất cả vào một file JavaScript là con đường nhanh nhất đến sự hỗn loạn. ES Modules là cách chuẩn của ngôn ngữ để chia mã thành nhiều file nhỏ, mỗi file có phạm vi riêng và chỉ chia sẻ những gì cần thiết qua export và import.
Có hai kiểu export. Kiểu có tên (named export), một file có thể có nhiều:
// tien-ich.js
export const THUE = 0.1;
export function dinhDangTien(so) {
return so.toLocaleString('vi-VN') + ' đ';
}
export function tinhThue(gia) {
return gia * THUE;
}Và kiểu mặc định (default export), mỗi file chỉ có một:
// gio-hang.js
export default class GioHang {
constructor() { this.items = []; }
them(sp) { this.items.push(sp); }
}// main.js
import GioHang from './gio-hang.js';
import { dinhDangTien, tinhThue } from './tien-ich.js';
import { THUE as THUE_VAT } from './tien-ich.js'; // đổi tên
import * as tienIch from './tien-ich.js'; // lấy tất cả
const gh = new GioHang();
console.log(dinhDangTien(150000));
console.log(tienIch.THUE);Named import đặt trong ngoặc nhọn và phải khớp tên, default import thì tự đặt tên. Đường dẫn tương đối cần bắt đầu bằng ./ hoặc ../, và trong trình duyệt thuần thì phải ghi đủ phần mở rộng .js.
Để trình duyệt hiểu bạn đang dùng module, đặt type='module' cho thẻ script:
<script type='module' src='main.js'></script>Những điều cần biết về script module:
defer, không chặn việc hiển thị trang.file://, trình duyệt thường chặn module vì chính sách bảo mật. Hãy chạy một máy chủ cục bộ, như tiện ích Live Server của VS Code.Đây là chủ đề tranh luận quen thuộc. Một số lý do nhiều nhóm ưu tiên named export:
Default export vẫn hữu ích cho file chỉ có một thành phần chính, như một component. Quan trọng nhất là thống nhất quy ước trong nhóm.
Bạn có thể gom nhiều module vào một điểm vào duy nhất:
// components/index.js
export { Nut } from './nut.js';
export { Modal } from './modal.js';
export * from './the.js';Nhờ vậy nơi khác chỉ cần import { Nut, Modal } from './components/index.js'. Đừng lạm dụng: file index quá lớn có thể làm công cụ đóng gói khó loại bỏ mã không dùng.
nutBieuDo.addEventListener('click', async function () {
const { veBieuDo } = await import('./bieu-do.js');
veBieuDo();
});Hàm import() trả về promise và chỉ tải module khi cần. Đây là nền tảng của kỹ thuật tách mã (code splitting), giúp trang tải ban đầu nhẹ hơn. Các công cụ như Vite hay webpack dùng chính cú pháp này để tạo các gói nhỏ riêng.
Trong Node.js, bạn sẽ gặp cả hai hệ thống: CommonJS với require và module.exports, và ES Modules với import và export. Có thể dùng ES Modules trong Node bằng cách đặt "type": "module" trong package.json hoặc dùng đuôi file .mjs. Dự án mới nên ưu tiên ES Modules vì đó là chuẩn của ngôn ngữ.
Với một dự án nhỏ, cấu trúc đơn giản sau đủ dùng và dễ mở rộng:
src/
main.js // điểm vào, khởi tạo ứng dụng
api.js // các hàm gọi API
state.js // dữ liệu và trạng thái chung
ui/
danh-sach.js // vẽ danh sách
modal.js // hộp thoại
utils/
dinh-dang.js // hàm tiện ích thuầnNguyên tắc là các module tiện ích không phụ thuộc vào giao diện, còn module giao diện được phép import module tiện ích chứ không làm ngược lại. Tránh import vòng tròn, tức A import B còn B lại import A, vì nó dẫn tới giá trị chưa sẵn sàng và lỗi khó hiểu. Nếu gặp tình huống này, hãy tách phần dùng chung ra một module thứ ba.
Hãy chia mã theo trách nhiệm: mỗi module một việc, chỉ export những gì cần, đặt tên nhất quán, và dùng dynamic import khi muốn tải theo nhu cầu. Đó là nền tảng để các dự án với Vite, React hay Vue có cấu trúc sạch sẽ.
Để thực hành tổ chức dự án nhiều file trong những bài tập có hướng dẫn, bạn có thể xem các khóa học của codebem.com.
Nguyễn Đình Cường
0 comment