Node.js 模块系统 -- ESM
ECMAScript 模块(也称为 ES 模块或 ESM)作为 ECMAScript 2015 规范的一部分被引入,目的是为 JavaScript 提供一个适合不同执行环境的官方模块系统。
ESM 和 CommonJS 的最大不同是前者是静态的。每个模块的导入是在顶部,不能在任何控制流中;同时,导入模块的名称不能在运行时使用表达式生成。
在 Node.js 中使用 ESM
Node.js 默认 .js
文件是使用 CommonJS
语法编写的。因此,如果直接在 .js
文件中使用 ESM
,解释器会报错。
下面的方法可以告诉 Node.js 解释器,给定的模块文件使用的是 ESM
。
- 直接使用
.mjs
后缀; - 或将
package.json
文件的type
字段修改为module
;此时,使用.js
文件可使用ESM
。
导出和导入
使用 export
关键字进行导出。
// logger.js
export function log(message) {
console.log(message)
}
export const DEFAULT_LEVEL = 'info'
export const LEVEL = {
error: 0,
debug: 1,
warn: 2,
data: 3,
info: 4,
verbose: 5
}
export class Logger {
constructor(name) {
this.name = name
}
log(message) {
console.log(`[${this.name}] ${message}`)
}
}
从模块中导入需要使用 import
关键字。可以方便的导入一个或多个实体,甚至进行重命名。例如:
import * as loggerModule from './logger.js'
*
会导入模块的所有成员,并使用 as
命名为 loggerModule
。此时可以通过 loggerModule
访问所有的导出成员。
如果只想导入一个或某几个成员,使用 {}
。
import { log } from './logger.js'
import { log, Logger } from './logger.js'
使用这种方式导入的实体,可能存在命名冲突的问题。此时可使用 as
关键字进行重命名。
默认导出 - export default
默认导出使用 export default
关键字。
// logger.js
export default class Logger {
constructor(name) {
this.name = name
}
log(message) {
console.log(`[${this.name}] ${message}`)
}
}
这种情况下 Logger
名称被忽略,导出的实体被注册在 default
名称下。可使用如下方式导入:
// main.js
import MyLogger from './logger.js'
const logger = new MyLogger('info')
logger.log('Hello World')