简单理解下requiret和import的区别

147 阅读2分钟

作为前端开发者,理解 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. 现代开发实践

  1. 新项目优先使用 ES6 模块(import/export)
  2. 在 Node.js 中可以使用 .mjs 扩展名或 package.json 中设置 "type": "module"
  3. 混合使用时可以通过构建工具(如 webpack、rollup)统一处理