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,享受更好的开发体验和工具支持!

相关推荐
Flynt1 天前
npm v12 来了:allowScripts 默认关闭,我的项目差点跑不起来
安全·npm·node.js
叫我Paul就好2 天前
尝试 Node 搭建后端-开发框架
node.js
风止何安啊4 天前
网课倍速痛点解决:一套前端代码实现自由控速播放器
前端·javascript·node.js
糖拌西瓜皮4 天前
Node.js核心模块实战:文件、路径、HTTP与流处理
javascript·node.js
糖拌西瓜皮4 天前
Node.js工程化实践:包管理、TypeScript配置与代码质量
typescript·node.js
糖拌西瓜皮4 天前
NestJS入门指南:Java开发者的Spring Boot体验
javascript·node.js
糖拌西瓜皮4 天前
Express框架快速上手:中间件、路由与错误处理
javascript·node.js
半个落月4 天前
从 Tokenization 到 Embedding:用 Node.js 搞懂大模型为什么先“分词”再“向量化”
人工智能·node.js
叁两5 天前
前端转型AI Agent该如何学习?(前置篇)
前端·人工智能·node.js
糖拌西瓜皮5 天前
TypeScript 进阶:泛型、条件类型、类型守卫与装饰器
javascript·node.js