首页/新闻资讯/正文详情

Node.js 导入导出实战:CommonJS 与 ES6 模块配置避坑指南

发布时间:2026/9/27 22:43:51 来源:云帆数科 栏目:资讯中心
Node.js 导入导出实战:CommonJS 与 ES6 模块配置避坑指南
1. 为什么你的 Node.js 项目总在 require 和 import 之间报错刚接触 Node.js 模块化开发时最容易卡住的地方不是写业务逻辑而是文件之间的导入导出。你写了一个工具函数想在其他文件里用结果终端甩出一句Cannot use import statement outside a module或者require is not defined in ES module scope然后你就开始怀疑人生。这个问题的根源在于 Node.js 同时存在两套模块系统CommonJS 和 ES6ECMAScript Modules简称 ESM。CommonJS 是 Node.js 早期的默认方案用require()导入、module.exports导出ES6 模块是 ECMAScript 标准方案用import导入、export导出。两套系统语法不同、加载机制不同甚至同一个.js文件在不同配置下会被当成不同的模块类型来解析。适合阅读这篇文章的人刚学 Node.js 后端开发、对模块化概念还比较模糊、遇到ERR_REQUIRE_ESM或Cannot use import statement outside a module不知道怎么排查的新手。我会用可复制的package.json配置和.mjs/.cjs文件骨架把两种模块规范的导入导出方式讲清楚再给出混用报错的逐步验证动作让你一次跑通两种写法。在开始之前如果你需要调用大模型 API 来做一些模块化的 AI 功能测试可以先用 TaoToken 的模型对话 快速验证接口返回格式确认请求参数和响应结构没问题之后再把它封装成 Node.js 模块集成到项目里。这样调试成本会低很多。2. 先把环境配好TaoToken 前置准备在写模块化代码之前如果你打算在项目里接入大模型能力比如做一个翻译模块、摘要模块需要先拿到 API Key。这一步很快但后面所有请求都依赖它。打开 TaoToken 控制台注册或登录后进入 API Keys 管理页创建一个新的 Key。建议按项目命名比如node-module-demo方便后续区分。拿到 Key 之后你的 Node.js 项目里可以通过环境变量读取不要硬编码在源码里。下面是一个.env文件的示例TAOTOKEN_API_KEYsk-你的实际Key TAOTOKEN_BASE_URLhttps://taotoken.net/api然后在代码里用process.env.TAOTOKEN_API_KEY读取。这样无论你用 CommonJS 还是 ESM都能统一管理配置。如果你后续要做长期编码或者 Agent 类项目可以考虑 Coding Plan它更适合需要持续调用模型的场景。接入细节可以参考 接入文档。3. CommonJS 与 ES6 模块的可复制配置骨架3.1 package.json 里的 type 字段决定一切Node.js 判断一个.js文件用哪种模块系统核心看package.json里的type字段。默认不写type或者写type: commonjs.js文件就按 CommonJS 解析写type: module.js文件就按 ES6 模块解析。下面是一个完整的package.json骨架你可以直接复制{ name: node-module-demo, version: 1.0.0, type: commonjs, scripts: { start:cjs: node src/cjs/app.js, start:mjs: node src/mjs/app.mjs }, dependencies: { dotenv: ^16.4.5 } }这里type: commonjs表示默认走 CommonJS。如果你想整个项目走 ES6 模块把值改成module即可。但更推荐的做法是用文件扩展名来区分.cjs强制 CommonJS.mjs强制 ES6 模块.js则跟随package.json的type字段。这样同一个项目里两种模块可以共存不会互相干扰。3.2 CommonJS 导出与导入写法CommonJS 的导出核心是module.exports。它可以导出字符串、对象、函数也可以挂载多个属性。先看一个导出对象的例子// src/cjs/message.cjs module.exports Hello World!;导入时用require()// src/cjs/app.cjs const msg require(./message.cjs); console.log(msg); // 输出: Hello World!如果导出多个属性可以这样写// src/cjs/person.cjs module.exports.name Sachin; module.exports.age 20; module.exports.greet function (name) { console.log(Welcome, name); };导入后直接访问属性或调用方法// src/cjs/use-person.cjs const person require(./person.cjs); console.log(person.name, ,, person.age); // Sachin , 20 person.greet(Sachin); // Welcome Sachin注意一个容易踩的坑exports和module.exports初始指向同一个对象但如果你直接给exports赋值一个新对象它就不再和module.exports关联了。所以导出单个函数或对象时统一用module.exports ...最稳妥。// src/cjs/area.cjs function area(x) { return x * x; } module.exports { area };// src/cjs/use-area.cjs const square require(./area.cjs); console.log(square.area(5)); // 253.3 ES6 模块导出与导入写法ES6 模块用export导出用import导入。它支持命名导出和默认导出两种方式。命名导出// src/mjs/details.mjs export const FirstName sachin; export const LastName sahara;导入时用花括号解构// src/mjs/app.mjs import { FirstName, LastName } from ./details.mjs; console.log(FirstName); // sachin默认导出// src/mjs/greeting.mjs export default function greet(name) { console.log(Welcome, name); }导入默认导出不需要花括号// src/mjs/use-greeting.mjs import greet from ./greeting.mjs; greet(Sachin); // Welcome SachinES6 模块还支持export { msg1, msg2 }这种集中导出写法适合一个文件里导出多个变量// src/mjs/messages.mjs const msg1 Hello; const msg2 World; export { msg1, msg2 };导入时同样用解构// src/mjs/use-messages.mjs import { msg1, msg2 } from ./messages.mjs; console.log(msg1, msg2); // Hello World3.4 两种模块系统的核心差异对照对比项CommonJSES6 模块导入语法require()import导出语法module.exports/exportsexport/export default文件扩展名.js默认/.cjs.mjs/.jstypemodule加载时机运行时同步加载编译时静态分析顶层 thismodule.exportsundefined是否支持动态导入原生支持用import()动态导入这张表建议收藏遇到报错时先对照检查自己用的是哪套语法、文件扩展名和package.json配置是否匹配。4. 验证请求跑通两种模块并调用 API4.1 先验证 CommonJS 模块能正常导入导出在项目根目录执行node src/cjs/app.cjs如果输出Hello World!说明 CommonJS 模块配置正确。再执行node src/cjs/use-person.cjs输出Sachin , 20和Welcome Sachin说明属性导出和方法导出都没问题。4.2 再验证 ES6 模块能正常导入导出执行node src/mjs/app.mjs输出sachin说明命名导出和导入正常。再执行node src/mjs/use-greeting.mjs输出Welcome Sachin说明默认导出正常。4.3 在模块中调用 TaoToken API 验证下面写一个 CommonJS 版本的 API 调用模块用来验证 Key 和接口是否可用// src/cjs/ai-client.cjs const https require(https); function chatCompletion(prompt) { return new Promise((resolve, reject) { const data JSON.stringify({ model: gpt-4o-mini, messages: [{ role: user, content: prompt }] }); const options { hostname: taotoken.net, path: /api/v1/chat/completions, method: POST, headers: { Content-Type: application/json, Authorization: Bearer ${process.env.TAOTOKEN_API_KEY} } }; const req https.request(options, (res) { let body ; res.on(data, (chunk) body chunk); res.on(end, () resolve(JSON.parse(body))); }); req.on(error, reject); req.write(data); req.end(); }); } module.exports { chatCompletion };调用方式// src/cjs/test-api.cjs require(dotenv).config(); const { chatCompletion } require(./ai-client.cjs); chatCompletion(用一句话解释什么是模块化).then((res) { console.log(res.choices[0].message.content); });执行node src/cjs/test-api.cjs如果返回一段关于模块化的解释说明 API Key 和网络请求都正常。ES6 版本写法类似只是导入导出语法不同// src/mjs/ai-client.mjs export async function chatCompletion(prompt) { const res await fetch(https://taotoken.net/api/v1/chat/completions, { method: POST, headers: { Content-Type: application/json, Authorization: Bearer ${process.env.TAOTOKEN_API_KEY} }, body: JSON.stringify({ model: gpt-4o-mini, messages: [{ role: user, content: prompt }] }) }); return res.json(); }调用// src/mjs/test-api.mjs import dotenv/config; import { chatCompletion } from ./ai-client.mjs; const res await chatCompletion(用一句话解释什么是模块化); console.log(res.choices[0].message.content);注意 ES6 模块里可以直接用顶层await不需要包在 async 函数里。执行node src/mjs/test-api.mjs验证结果。5. 本篇常见报错排查5.1 Cannot use import statement outside a module这个报错的意思是你在一个被 Node.js 当成 CommonJS 的文件里写了import语句。排查步骤第一步检查文件扩展名。如果是.js去看package.json里type字段是不是commonjs或者没写。如果是要么把文件改成.mjs要么把type改成module。第二步检查package.json的位置。Node.js 会从当前文件向上逐级查找最近的package.json如果子目录里有一个package.json覆盖了配置也会导致解析行为不一致。第三步确认没有在 CommonJS 文件里混用import。CommonJS 只能用require()。5.2 require is not defined in ES module scope这个报错反过来你在 ES6 模块里用了require()。ES6 模块没有require、__dirname、__filename这些 CommonJS 特有的变量。解决办法有两种。第一种改用import语法。第二种如果必须用require可以通过createRequire创建// src/mjs/use-require.mjs import { createRequire } from module; const require createRequire(import.meta.url); const pkg require(./package.json); console.log(pkg.name);5.3 ERR_REQUIRE_ESM当你用require()去加载一个 ES6 模块文件时会报这个错。比如require(./details.mjs)就会触发。解决方式要么把被加载的文件改成 CommonJS.cjs要么在 CommonJS 里用动态import()// src/cjs/load-esm.cjs import(./details.mjs).then((mod) { console.log(mod.FirstName); });注意import()返回的是 Promise所以要用.then()或await。5.4 找不到模块路径require(./message)不写扩展名时Node.js 会按.js、.json、.node的顺序查找。但在 ES6 模块里import必须写完整扩展名import ./message会直接报错必须写成import ./message.mjs或import ./message.js。另外导入文件夹时CommonJS 会找index.jsES6 模块不会自动找index.js需要显式写import ./folder/index.mjs。5.5 混用导致的循环依赖问题CommonJS 和 ES6 模块对循环依赖的处理方式不同。CommonJS 在循环依赖时可能拿到不完整的module.exports而 ES6 模块通过静态分析能更好地处理。如果你的项目里两个模块互相导入建议统一用一种模块系统不要混用。6. 继续深入从模块化到实际项目接入模块化配置跑通之后下一步就是把它用到真实项目里。如果你在做 AI 相关的 Node.js 后端建议把 API 调用封装成独立模块CommonJS 和 ES6 各维护一份适配层业务代码只依赖统一的接口。需要长期编码或做 Agent 项目的可以看看 Coding Plan它更适合持续调用模型的场景。接入过程中遇到参数问题可以对照 接入文档 排查。如果你只是想先验证模型返回格式用 模型对话 快速试一下就行。最后提醒一个实际开发中的小技巧在package.json里加一个engines字段锁定 Node.js 版本比如node: 18.0.0因为 ES6 模块的顶层await和fetch在低版本 Node.js 里不可用。这样团队协作时不会因为版本差异导致模块解析行为不一致。

相关推荐

ui界面设计包括哪些内容?保姆级建站教程揭秘
ui界面设计包括哪些内容?保姆级建站教程揭秘

ui界面设计包括哪些内容?保姆级建站教程揭秘 不会写代码也能搞定网站?别被“程序员专属”吓退。这篇保姆级建站教程专治各种“想建站但怕技术”的焦虑。 UI设计到底包含啥?别只盯着颜色… · 2026/9/27 22:43:41

项目文档:基于MediaPipe姿态估计的非接触式人体测量系统设计与实现
项目文档:基于MediaPipe姿态估计的非接触式人体测量系统设计与实现

摘要:针对传统皮尺测量依赖人工操作、三维扫描设备成本较高以及远程场景难以快速获得身体尺寸等问题,本文设计并实现了一种基于MediaPipe姿态估计的非接触式人体测量系统。 内容简介 系统以普通正面与侧面全身图像为输入,采用Google MediaPi… · 2026/9/27 22:43:35

Netflix |开源工程尽调|Netflix HubCommander 静态源码评测:基于Slack的GitHub聊天运维机器人
Netflix |开源工程尽调|Netflix HubCommander 静态源码评测:基于Slack的GitHub聊天运维机器人

Netflix |开源工程尽调|Netflix HubCommander 静态源码评测:基于Slack的GitHub聊天运维机器人 专栏:Valhalla‑Matrix|证据驱动开源静态工程评测 评测快照Commit:35abf3880b48e6059ea811b17d46ea2b1820c4… · 2026/9/27 22:43:35

STM32+HX711称重模块+OLED完整称重项目讲解
STM32+HX711称重模块+OLED完整称重项目讲解

摘要 本篇博文讲解基于STM32F103C8T6、HX711称重采集模块、电阻应变式称重传感器以及OLED显示屏实现的电子秤项目。从硬件接线、传感器原理、HX711芯片工作逻辑、芯片串行读取时序,到STM32程序去皮、标定算法、实物演示、故障现象全部讲解,适合单片机课… · 2026/9/27 23:22:36

国产AGM产品哪家强?揭秘可靠厂家背后的故事
国产AGM产品哪家强?揭秘可靠厂家背后的故事

开篇:定下基调随着国产半导体产业的崛起,可编程逻辑芯片(FPGA)及以其为核心的SoC(片上系统)已成为工业控制、人工智能、消费电子等领域的关键硬件。在众多厂商中,如何选择一家技术扎实、产品可靠… · 2026/9/27 23:22:36

面试官问:为什么用SpringBoot?别只说简化配置
面试官问:为什么用SpringBoot?别只说简化配置

自动配置:不是少写代码,是理解约定SpringBoot的自动配置不是魔法,是条件化装配。ConditionalOnClass、ConditionalOnMissingBean这些注解,让框架根据classpath里有什么、你定义了什么,来决定该创建哪些Bean。面试时你要… · 2026/9/27 23:22:30

Python中mmap模块(处理大文本)
Python中mmap模块(处理大文本)

假如当下的场景里存在一项具体任务, 那就是需要对一个容量达到20G的巨型文件进行一系列处理操作。在此情境之下, 我们究竟应当采取何种方式来妥善完成这一工作,并对其进行深入思考与探讨, 进而构思出实现该功能的具体路径与方案呢?咱们大概会采用这么一种办法来进行… · 2026/9/27 23:22:30

探秘外贸 SEO 优化公司,解锁外贸营销新密码!
探秘外贸 SEO 优化公司,解锁外贸营销新密码!

痛点深度剖析我们团队在实践中发现,外贸企业在 SEO 优化方面面临诸多困境。一方面,流量获取难题突出,SEO 见效慢,很多企业做了半年优化,关键词排名依旧毫无起色;SEM 烧钱快,谷歌广告点击成本持续… · 2026/9/27 23:22:30

Claude Code 命令技巧(二):压缩上下文、历史会话与思考过程的配置骨架
Claude Code 命令技巧(二):压缩上下文、历史会话与思考过程的配置骨架

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/27 23:22:24

MATLAB雷达信号脉冲压缩仿真:LFM线性调频、匹配滤波与距离分辨率实现
MATLAB雷达信号脉冲压缩仿真:LFM线性调频、匹配滤波与距离分辨率实现

简介:这套Matlab仿真工具完整呈现雷达信号脉冲压缩过程,从线性调频(LFM)信号生成、目标回波仿真到匹配滤波压缩处理均有可运行代码支撑,面向电子信息工程、计算机、数学等专业学生,适用于课程设计、期末大作… · 2026/9/27 0:00:01

汕头网站建设制作厂家避坑指南:5大注意事项救急
汕头网站建设制作厂家避坑指南:5大注意事项救急

汕头网站建设制作厂家避坑指南:5大注意事项救急 改个需求建站公司拖一周,这种憋屈事我见得太多了。 很多汕头老板找本地建站团队,签合同前看着方案挺美,一上线就变脸。 今天不聊虚的,直接拆解找 汕头网站建设制作厂家 时的5个核心 注意事项… · 2026/9/27 0:00:01

多模态虚假新闻检测实战:BERT+ResNet双塔与对比学习
多模态虚假新闻检测实战:BERT+ResNet双塔与对比学习

简介:基于PyTorch的多模态虚假新闻检测项目完整代码包,面向自然语言处理与计算机视觉交叉方向的开发者、科研人员及毕业设计选题者,解决社交媒体中文本与图像联合识别虚假新闻的问题。系统以BERT预训练模型提取文本语义特征,以Res… · 2026/9/27 0:00:01

MATLAB雷达信号脉冲压缩仿真:LFM线性调频、匹配滤波与距离分辨率实现
MATLAB雷达信号脉冲压缩仿真:LFM线性调频、匹配滤波与距离分辨率实现

简介:这套Matlab仿真工具完整呈现雷达信号脉冲压缩过程,从线性调频(LFM)信号生成、目标回波仿真到匹配滤波压缩处理均有可运行代码支撑,面向电子信息工程、计算机、数学等专业学生,适用于课程设计、期末大作… · 2026/9/27 0:00:01

汕头网站建设制作厂家避坑指南:5大注意事项救急
汕头网站建设制作厂家避坑指南:5大注意事项救急

汕头网站建设制作厂家避坑指南:5大注意事项救急 改个需求建站公司拖一周,这种憋屈事我见得太多了。 很多汕头老板找本地建站团队,签合同前看着方案挺美,一上线就变脸。 今天不聊虚的,直接拆解找 汕头网站建设制作厂家 时的5个核心 注意事项… · 2026/9/27 0:00:01

多模态虚假新闻检测实战:BERT+ResNet双塔与对比学习
多模态虚假新闻检测实战:BERT+ResNet双塔与对比学习

简介:基于PyTorch的多模态虚假新闻检测项目完整代码包,面向自然语言处理与计算机视觉交叉方向的开发者、科研人员及毕业设计选题者,解决社交媒体中文本与图像联合识别虚假新闻的问题。系统以BERT预训练模型提取文本语义特征,以Res… · 2026/9/27 0:00:01

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码