require() vs import:Node.js 模块导入对比

require() vs import:Node.js 模块导入对比

理解两种导入方式的核心区别

快速对比

特性 require() import
加载方式 运行时、同步 编译时、静态
模块系统 CommonJS ES Modules
提升行为 可在任意位置调用 自动提升到顶部
条件导入 支持 不支持
文件扩展名 可省略 必须写 .js

基本语法

require()

javascript 复制代码
// 导入整个模块
const fs = require('fs');

// 解构导入
const { readFile } = require('fs');

// 条件导入
if (needFeature) {
  const feature = require('./feature');
  feature.init();
}

// 任意位置调用
function loadModule() {
  const math = require('./math');
  return math.add(1, 2);
}

import

javascript 复制代码
// 导入整个模块
import * as fs from 'fs';

// 解构导入
import { readFile } from 'fs';

// 默认导入
import express from 'express';

// 必须在文件顶部
import { add } from './math.js';  // 注意要写 .js

// ❌ 不支持条件导入
// if (needFeature) {
//   import { feature } from './feature';  // 错误
// }

// ✅ 动态导入(返回 Promise)
if (needFeature) {
  const { feature } = await import('./feature.js');
  feature.init();
}

核心区别

1. 加载时机

javascript 复制代码
// require - 运行时加载
console.log('before require');
const math = require('./math');  // 执行到这里才加载
console.log('after require');

// import - 编译时加载(代码执行前已完成)
console.log('before import');
import { add } from './math.js';  // 代码执行前已加载
console.log('after import');

2. 值拷贝 vs 动态引用

javascript 复制代码
// counter.js (CommonJS)
let count = 0;
module.exports = { count };
count = 1;  // 导出的值仍是 0

// test.js
const { count } = require('./counter');
console.log(count);  // 0

// counter.js (ES Modules)
let count = 0;
export { count };
count = 1;  // 导出的值同步更新为 1

// test.js
import { count } from './counter.js';
console.log(count);  // 1

3. 提升行为

javascript 复制代码
// require - 没有提升
console.log(add);  // ReferenceError
const { add } = require('./math');

// import - 自动提升
console.log(add);  // ✅ 正常工作
import { add } from './math.js';  // 实际在文件顶部执行

4. 条件导入

javascript 复制代码
// require - ✅ 支持条件导入
let config;
if (process.env.NODE_ENV === 'production') {
  config = require('./config.prod');
} else {
  config = require('./config.dev');
}

// import - ❌ 不支持静态条件导入
// ✅ 使用动态导入替代
let config;
if (process.env.NODE_ENV === 'production') {
  config = await import('./config.prod.js');
} else {
  config = await import('./config.dev.js');
}

性能对比

javascript 复制代码
// require - 每次调用都执行模块代码
const math1 = require('./math');  // 执行模块代码
const math2 = require('./math');  // 使用缓存,不重复执行

// import - 只执行一次,自动缓存
import { add } from './math.js';  // 执行并缓存
import { subtract } from './math.js';  // 使用缓存

使用场景

使用 require() 当:

  • 需要条件导入
  • 动态加载模块
  • 兼容老项目
  • 编写简单脚本

使用 import 当:

  • 新项目开发
  • 需要 tree-shaking 优化
  • 使用现代框架(React、Vue)
  • 跨平台代码(浏览器 + Node.js)

迁移指南

CommonJS → ES Modules

javascript 复制代码
// 之前 (CJS)
const express = require('express');
const { join } = require('path');
const app = express();

module.exports = app;

// 之后 (ESM)
import express from 'express';
import { join } from 'path';
const app = express();

export default app;

实用技巧

动态导入(替代条件 require)

javascript 复制代码
// 根据环境动态加载
const isDev = process.env.NODE_ENV !== 'production';

if (isDev) {
  const { hot } = await import('./hot.js');
  hot.enable();
}

两者互操作

javascript 复制代码
// 在 ESM 中导入 CJS
import express from 'express';  // ✅ 支持良好

// 在 CJS 中导入 ESM(需要动态导入)
async function loadESM() {
  const { add } = await import('./math.mjs');
  return add(1, 2);
}

快速参考

javascript 复制代码
// CommonJS
const { add } = require('./math');
module.exports = { value: 1 };

// ES Modules
import { add } from './math.js';
export const value = 1;

总结

  • require():灵活、动态,适合复杂场景
  • import:现代、静态,性能更好

新项目优先使用 import,享受更好的开发体验和工具支持!

相关推荐
lzp07911 天前
如何在Windows系统上安装和配置Node.js及Node版本管理器(nvm)
windows·node.js
weiwx831 天前
【前端】Node.js使用教程
前端·node.js·vim
i建模1 天前
Ubuntu Node.js 升级方案
linux·运维·ubuntu·node.js
结网的兔子1 天前
前端学习笔记(实战准备篇)——用vite构建一个项目【吐血整理】
前端·学习·elementui·npm·node.js·vue
i建模1 天前
npm国内镜像源加速
前端·npm·node.js
热爱生活的五柒2 天前
解决 npm install 一直在转圈的问题
前端·npm·node.js
跟着珅聪学java2 天前
Electron 中实现“字符串转图片”功能教程
node.js
tryCbest2 天前
Git与Node.js安装及常用命令详解
git·node.js
_DoubleL2 天前
Volta启动项目自动切换Node版本
前端·node.js
小杨勇敢飞2 天前
npm 安装 @openai/codex 后无法调用 codex 命令的完整解决过程:‘codex‘ 不是内部或外部命令,也不是可运行的程序或批处理文件。
前端·npm·node.js