ES module là hệ thống module chuẩn của JavaScript, chạy được cả trên browser lẫn Node.
// math.js
export const PI = 3.14 // named export
export function add(a, b) { return a + b }
export default class Calc { } // default export — mỗi file một cái
// app.js
import Calc, { PI, add } from './math.js'
import * as math from './math.js'
import { add as sum } from './math.js'
const mod = await import('./heavy.js') // dynamic import — tách bundleBốn đặc điểm cần nhớ:
1. Phân tích tĩnh — import/export được xác định lúc phân tích cú pháp, không phải lúc chạy. Đây là điều kiện để bundler làm được tree-shaking.
2. Scope riêng theo file và luôn ở strict mode.
3. Chỉ chạy một lần dù được import ở nhiều nơi — nền tảng của mẫu singleton.
4. Live binding — điểm khác biệt lớn nhất so với CommonJS:
// counter.js
export let count = 0
export const inc = () => count++
// app.js
import { count, inc } from './counter.js'
inc()
console.log(count) // 1 — thấy giá trị MỚI
// CommonJS thì ngược lại: require() sao chép giá trị tại thời điểm gọiLưu ý: không gán lại được biến đã import (count = 5 → TypeError) — binding là chỉ đọc ở phía module import nó.
Ghi chú Node: .mjs, hoặc "type": "module" trong package.json, thì file là ES module; ngược lại là CommonJS. Trộn hai loại là nguồn gốc của phần lớn lỗi Cannot use import statement outside a module.