Giải pháp nhanh
Nếu bạn cần sửa lỗi này ngay lập tức, hãy sử dụng một trong hai phương pháp tiêu chuẩn sau:
- Sửa lỗi cho toàn bộ dự án: Mở
package.jsonvà thêm"type": "module"vào đối tượng gốc. - Sửa lỗi cho từng file riêng lẻ: Thay đổi phần mở rộng của file từ
.jssang.mjs.
// file package.json của bạn sẽ trông như thế này:
{
"name": "my-node-app",
"version": "1.0.0",
"type": "module",
"dependencies": { ... }
}
Nguyên nhân gốc rễ
Node.js được xây dựng vào năm 2009 bằng CommonJS, một hệ thống module sử dụng require(). JavaScript hiện đại ngày nay sử dụng ECMAScript Modules (ESM), dựa trên import và export. Hai hệ thống này xử lý biến và việc tải dữ liệu khác nhau.
Theo mặc định, Node.js coi mọi file .js là một module CommonJS. Khi engine gặp câu lệnh import trong một file mà nó mong đợi là CommonJS, nó sẽ dừng thực thi và đưa ra lỗi này:
SyntaxError: Cannot use import statement outside a module
Để sử dụng cú pháp hiện đại, bạn phải báo hiệu rõ ràng cho Node.js rằng môi trường của bạn hỗ trợ ES Modules.
Cách 1: Sử dụng package.json (Khuyến nghị)
Đây là cách hiệu quả nhất để quản lý các dự án Node.js hiện đại. Việc thiết lập trường type đảm bảo rằng mọi file .js trong thư mục của bạn—và tất cả các thư mục con—đều được xử lý như một ES Module.
- Tìm file
package.jsontrong thư mục gốc của dự án. - Chèn
"type": "module"vào khối cấu hình chính. - Khởi động lại ứng dụng bằng cách chạy
node app.js.
Một lưu ý quan trọng: Thay đổi này sẽ vô hiệu hóa require(). Nếu bạn cố gắng sử dụng const fs = require('fs') trong một module, Node sẽ báo lỗi. Bạn phải chuyển đổi các dòng đó thành import fs from 'fs' hoặc đổi tên các file cũ cụ thể thành .cjs.
Cách 2: Sử dụng phần mở rộng .mjs
Đôi khi bạn không muốn thay đổi cấu hình cho toàn bộ dự án. Trong những trường hợp này, phần mở rộng .mjs là lựa chọn tốt nhất. Node.js luôn coi các file .mjs là ES Modules, bất kể file package.json của bạn quy định điều gì.
- Đổi tên
server.jsthànhserver.mjs. - Thực thi file bằng lệnh
node server.mjs.
Cách tiếp cận này phù hợp cho các script nhỏ hoặc khi bạn đang dần chuyển đổi một codebase lớn sang JavaScript hiện đại.
Cách 3: Chuyển đổi bằng TypeScript
Nếu bạn đang sử dụng TypeScript, bạn có thể gặp lỗi này nếu cấu hình của bạn nhắm mục tiêu đến một phiên bản Node cũ hơn. File tsconfig.json của bạn đóng vai trò như một cầu nối, chuyển đổi các câu lệnh import thành các lệnh gọi require mà các phiên bản Node cũ hơn có thể hiểu được.
// tsconfig.json
{
"compilerOptions": {
"module": "CommonJS",
"target": "ES2020",
"esModuleInterop": true
}
}
Sử dụng ts-node hoặc tsx để chạy các file sẽ xử lý việc chuyển đổi này trong bộ nhớ, giúp ngăn chặn SyntaxError trong quá trình phát triển.
Kiểm tra kết quả
Xác minh thiết lập của bạn bằng cách tạo một file có tên check-version.js với đoạn mã sau:
// check-version.js
import { versions } from 'process';
console.log("Phiên bản Engine Node.js:", versions.node);
Nếu bạn đã kích hoạt "type": "module", hãy chạy node check-version.js. Nếu nó hiển thị phiên bản của bạn (ví dụ: 20.10.0) mà không bị lỗi, môi trường của bạn đã được cấu hình chính xác.
Các trở ngại thường gặp
- Phiên bản Node.js: ESM đã trở nên ổn định từ Node.js v12.17.0. Nếu bạn đang bị kẹt ở phiên bản cũ hơn như v10, bạn phải nâng cấp để sử dụng
importmà không cần các flag thử nghiệm. - Phần mở rộng rõ ràng: Không giống như CommonJS, ESM yêu cầu phần mở rộng file đầy đủ. Bạn không thể viết
import { auth } from './auth'; bạn phải viếtimport { auth } from './auth.js'. - Import thư mục: Việc import một thư mục để tự động tải
index.jskhông còn hoạt động trong ESM. Bạn phải trỏ trực tiếp đến đường dẫn file.
Tài nguyên
- Tài liệu ESM chính thức của Node.js
- Hướng dẫn về tính tương thích với CommonJS

