CommonJS和ESM的区别,require和import的区别
问:
nodejs中,require和import有什么区别?
答:
在 Node.js 中,require 和 import 是两种不同的模块导入机制,它们分别属于 CommonJS 和 ES Modules (ESM) 规范。以下是它们的主要区别:
1. 规范来源
require- 属于 CommonJS 规范,是 Node.js 原生支持的模块系统(从早期版本开始)。
import- 属于 ES Modules (ESM) 规范,是 JavaScript 的官方标准(ES6+),Node.js 从 v12+ 开始原生支持,需要启用特定条件(如
"type": "module"或.mjs后缀)。
- 属于 ES Modules (ESM) 规范,是 JavaScript 的官方标准(ES6+),Node.js 从 v12+ 开始原生支持,需要启用特定条件(如
2. 语法差异
-
requireconst fs = require('fs'); const { readFile } = require('fs').promises;- 动态导入,可以在代码的任何位置调用(包括条件判断中)。
- 导入的是整个模块对象,需通过解构或属性访问获取具体成员。
-
importimport fs from 'fs'; import { readFile } from 'fs/promises'; import * as fs from 'fs';- 静态导入,必须在模块顶层作用域使用(不能嵌套在条件语句中)。
- 支持命名导入、默认导入和命名空间导入。
3. 加载时机
-
require- 同步加载:模块在运行时同步加载并执行。
- 适合服务端(Node.js)的阻塞式加载场景。
-
import- 异步加载(理论上是异步的,尽管 Node.js 目前是同步实现)。
- 更适合浏览器端的异步加载,但 Node.js 中通常表现为静态解析。
4. 缓存机制
- 两者都会缓存已加载的模块,但缓存管理方式不同:
- CommonJS (
require) 通过require.cache暴露缓存对象。 - ES Modules 的缓存由运行时内部管理,不可直接访问。
- CommonJS (
5. 文件扩展名与配置
-
require- 默认支持
.js、.json、.node文件,按顺序解析。 - 行为由
require.extensions和require.resolve控制。
- 默认支持
-
import- 必须显式指定文件扩展名(如
'./file.js'),或通过package.json的"type": "module"配置。 - 支持
.mjs(强制 ESM)和.cjs(强制 CommonJS)扩展名。
- 必须显式指定文件扩展名(如
6. 互操作性
-
在 CommonJS 中引入 ESM
- 不能直接使用
require加载 ESM 模块(会报错)。 - 可通过动态
import()(返回 Promise)异步加载:const fs = await import('fs');
- 不能直接使用
-
在 ESM 中引入 CommonJS
- 可以直接使用
import导入 CommonJS 模块:import package from 'commonjs-package'; // 默认导出 import { method } from 'commonjs-package'; // 命名导出(需兼容) - CommonJS 模块的
module.exports会被转换为 ESM 的默认导出。
- 可以直接使用
7. 顶层 this 指向
require- 模块顶层
this指向module.exports。
- 模块顶层
import- 模块顶层
this为undefined(严格模式)。
- 模块顶层
8. 循环依赖处理
require- 循环依赖时,可能返回未完全初始化的模块。
import- 通过静态分析解决循环依赖,引用指向预解析的绑定。
何时使用?
-
用
require- 旧版 Node.js 项目(< v12)。
- 需要动态导入或条件加载模块时。
-
用
import- 新项目或支持 ESM 的 Node.js 版本(>= v12)。
- 需要静态分析、Tree Shaking(前端打包工具优化)时。
- 代码需要与浏览器端 ESM 兼容。
示例配置
在 package.json 中启用 ESM:
{
"type": "module" // 默认以 ESM 解析 .js 文件
}
或强制 CommonJS:
{
"type": "commonjs" // 默认以 CommonJS 解析 .js 文件
}
总结
| 特性 | require (CommonJS) |
import (ES Modules) |
|---|---|---|
| 规范 | Node.js 传统 | ES6 标准 |
| 加载方式 | 同步 | 静态/异步 |
| 语法灵活性 | 动态导入 | 静态导入(顶层) |
| 文件扩展名 | 自动解析 | 需显式指定 |
| 互操作性 | 不能直接加载 ESM | 可导入 CommonJS |
| 适用场景 | 旧项目、动态加载 | 新项目、浏览器兼容 |
根据项目环境和需求选择合适的模块系统!
问:
CommonJS和ES Modules(ESM)有什么区别?
答:
在 Node.js 中,require 和 import 是两种不同的模块导入机制,它们分别属于 CommonJS 和 ES Modules (ESM) 规范。以下是它们的主要区别:
1. 规范来源
require- 属于 CommonJS 规范,是 Node.js 原生支持的模块系统(从早期版本开始)。
import- 属于 ES Modules (ESM) 规范,是 JavaScript 的官方标准(ES6+),Node.js 从 v12+ 开始原生支持,需要启用特定条件(如
"type": "module"或.mjs后缀)。
- 属于 ES Modules (ESM) 规范,是 JavaScript 的官方标准(ES6+),Node.js 从 v12+ 开始原生支持,需要启用特定条件(如
2. 语法差异
-
requireconst fs = require('fs'); const { readFile } = require('fs').promises;- 动态导入,可以在代码的任何位置调用(包括条件判断中)。
- 导入的是整个模块对象,需通过解构或属性访问获取具体成员。
-
importimport fs from 'fs'; import { readFile } from 'fs/promises'; import * as fs from 'fs';- 静态导入,必须在模块顶层作用域使用(不能嵌套在条件语句中)。
- 支持命名导入、默认导入和命名空间导入。
3. 加载时机
-
require- 同步加载:模块在运行时同步加载并执行。
- 适合服务端(Node.js)的阻塞式加载场景。
-
import- 异步加载(理论上是异步的,尽管 Node.js 目前是同步实现)。
- 更适合浏览器端的异步加载,但 Node.js 中通常表现为静态解析。
4. 缓存机制
- 两者都会缓存已加载的模块,但缓存管理方式不同:
- CommonJS (
require) 通过require.cache暴露缓存对象。 - ES Modules 的缓存由运行时内部管理,不可直接访问。
- CommonJS (
5. 文件扩展名与配置
-
require- 默认支持
.js、.json、.node文件,按顺序解析。 - 行为由
require.extensions和require.resolve控制。
- 默认支持
-
import- 必须显式指定文件扩展名(如
'./file.js'),或通过package.json的"type": "module"配置。 - 支持
.mjs(强制 ESM)和.cjs(强制 CommonJS)扩展名。
- 必须显式指定文件扩展名(如
6. 互操作性
-
在 CommonJS 中引入 ESM
- 不能直接使用
require加载 ESM 模块(会报错)。 - 可通过动态
import()(返回 Promise)异步加载:const fs = await import('fs');
- 不能直接使用
-
在 ESM 中引入 CommonJS
- 可以直接使用
import导入 CommonJS 模块:import package from 'commonjs-package'; // 默认导出 import { method } from 'commonjs-package'; // 命名导出(需兼容) - CommonJS 模块的
module.exports会被转换为 ESM 的默认导出。
- 可以直接使用
7. 顶层 this 指向
require- 模块顶层
this指向module.exports。
- 模块顶层
import- 模块顶层
this为undefined(严格模式)。
- 模块顶层
8. 循环依赖处理
require- 循环依赖时,可能返回未完全初始化的模块。
import- 通过静态分析解决循环依赖,引用指向预解析的绑定。
何时使用?
-
用
require- 旧版 Node.js 项目(< v12)。
- 需要动态导入或条件加载模块时。
-
用
import- 新项目或支持 ESM 的 Node.js 版本(>= v12)。
- 需要静态分析、Tree Shaking(前端打包工具优化)时。
- 代码需要与浏览器端 ESM 兼容。
示例配置
在 package.json 中启用 ESM:
{
"type": "module" // 默认以 ESM 解析 .js 文件
}
或强制 CommonJS:
{
"type": "commonjs" // 默认以 CommonJS 解析 .js 文件
}
总结
| 特性 | require (CommonJS) |
import (ES Modules) |
|---|---|---|
| 规范 | Node.js 传统 | ES6 标准 |
| 加载方式 | 同步 | 静态/异步 |
| 语法灵活性 | 动态导入 | 静态导入(顶层) |
| 文件扩展名 | 自动解析 | 需显式指定 |
| 互操作性 | 不能直接加载 ESM | 可导入 CommonJS |
| 适用场景 | 旧项目、动态加载 | 新项目、浏览器兼容 |
根据项目环境和需求选择合适的模块系统!

浙公网安备 33010602011771号