作为前端开发者,理解 require
和 import
的区别非常重要。
1. 来源与标准
-
require:
- 来自 CommonJS 规范
- Node.js 原生支持的模块加载方式
- 运行时加载
-
import:
- 来自 ES6 (ES2015) 模块规范
- 现代浏览器原生支持(需 script type="module")
- 编译时静态加载
2. 语法对比
// CommonJS (require)
const fs = require('fs');
const { readFile } = require('fs');
const myModule = require('./myModule');
// ES6 (import)
import fs from 'fs';
import { readFile } from 'fs';
import * as myModule from './myModule';
import myDefault, { namedExport } from './myModule';
3. 加载时机与行为
-
require:
- 运行时执行:模块在代码执行到 require 语句时才加载
- 动态加载:可以在条件语句中使用
- 同步加载:在 Node.js 中是同步操作
-
import:
- 编译时解析:模块依赖在代码执行前就确定
- 静态分析:必须在模块顶层,不能在条件语句中使用(动态 import 除外)
- 异步加载:浏览器中是异步加载的
4. 模块导出方式
// CommonJS 导出
module.exports = myModule;
exports.myFunction = () => {};
// ES6 导出
export default myModule;
export const myFunction = () => {};
5. 性能与优化
-
require:
- 每次 require 都会执行模块代码
- 模块缓存基于文件路径
-
import:
- 静态分析允许更好的 tree-shaking(移除未使用代码)
- 模块只执行一次,多次 import 会引用同一实例
6. 动态加载
// CommonJS 动态加载
const moduleName = condition ? 'moduleA' : 'moduleB';
const module = require(moduleName);
// ES6 动态加载 (import() 函数)
const moduleName = condition ? 'moduleA' : 'moduleB';
import(moduleName).then(module => {
// 使用模块
});
7. 循环依赖处理
-
require:
- 可以处理循环依赖,但可能导致部分导出未初始化
-
import:
- 更好地处理循环依赖,因为导入是静态绑定的
8. 使用场景
-
require:
- Node.js 环境
- 需要动态加载模块
- 旧项目或与 CommonJS 兼容的库
-
import:
- 现代前端项目(React, Vue 等)
- 需要 tree-shaking 优化
- 浏览器原生模块
9. 现代开发实践
- 新项目优先使用 ES6 模块(import/export)
- 在 Node.js 中可以使用 .mjs 扩展名或 package.json 中设置 "type": "module"
- 混合使用时可以通过构建工具(如 webpack、rollup)统一处理