Tổng quan
ES Modules (ESM) sử dụng export và import để chia sẻ code giữa các file. Cần type="module" trên script tag và chạy qua HTTP server.
Cấu trúc 3 file
1. index.html
<!DOCTYPE html>
<html lang="vi">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ES Modules</title>
<style>
body { font-family: 'Segoe UI', sans-serif; padding: 20px; }
.result { font-size: 18px; font-weight: 500; color: #6a1b9a; margin: 20px 0; padding: 15px; background: #f3e5f5; border-radius: 4px; }
button { padding: 10px 20px; background: #1976d2; color: white; border: none; border-radius: 4px; cursor: pointer; }
</style>
</head>
<body>
<h1>Export & Import trong JavaScript</h1>
<button id="btn">IMPORT MODULE</button>
<div class="result" id="result"></div>
<h3>Nhấn nút để import module</h3>
<script src="script.js" type="module"></script>
</body>
</html>
2. sample.js (Export)
// sample.js
const resultEle = document.querySelector('.result');
// Named exports
export function tellTime() {
return new Date().toLocaleTimeString();
}
export const PI = 3.14159;
// Default export
export default function testImport() {
resultEle.innerHTML = '✅ Module testImport đã được import (default)';
return 'Default export success';
}
3. script.js (Import)
// script.js
import testImport, { tellTime, PI } from './sample.js';
document.getElementById('btn').addEventListener('click', () => {
// Default import
testImport();
// Named imports
document.getElementById('result').innerHTML += `
⏰ Time: ${tellTime()}`;
document.getElementById('result').innerHTML += `
📐 PI: ${PI}`;
});
Các loại Export/Import
| Loại | Export | Import | Số lượng |
|---|---|---|---|
| Default | export default ... | import anyName from './file' | 1/file |
| Named | export const/function ... | import { exactName } from './file' | Nhiều |
| Namespace | - | import * as ns from './file' | - |
| Rename | - | import { old as new } from './file' | - |
| Re-export | export { x } from './other' | - | - |
Dynamic Import (Lazy Loading)
// Trả về Promise
const module = await import('./heavy-module.js');
module.default();
module.namedExport();
// Code splitting với React.lazy, Vue defineAsyncComponent, etc.
Chạy ví dụ
- Tạo 3 file trong cùng thư mục
- Chạy local server:
npx serve,python -m http.server 8000, hoặc VS Code Live Server - Mở
https://localhost:port
⚠️ Không mở file:// trực tiếp - lỗi CORS: "CORS policy: Cross origin requests only supported for protocol schemes: http, https..."
Module vs Script thông thường
| Đặc điểm | Script | Module (type="module") |
|---|---|---|
| Scope | Global | Module scope (riêng) |
| Strict mode | Tùy chọn | Luôn bật |
| Loading | Blocking | Defer mặc định |
| this | window | undefined |
| Import/Export | Không | Có |
Node.js: CommonJS vs ESM
// CommonJS (require) - Mặc định .js
const { func } = require('./module');
module.exports = { func };
// ESM (import/export) - .mjs hoặc "type": "module" trong package.json
import { func } from './module.js';
export { func };