ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Node.js入门教程(二十):模块导入

Node.js入门教程(二十):模块导入 一、模块系统概述当你开始写 Node.js 项目时最先遇到的问题之一就是——如何导入模块module。在 Node.js 里模块就是可以重复使用的 JavaScript 文件它们之间通过导入import和导出export互相通信。Node.js 生态系统主要支持两种模块系统模块系统规范文件扩展名导入方式导出方式CommonJSNode.js 早期使用.jsrequire()module.exports/exportsES Module (ESM)ECMAScript 标准.mjs或type: moduleimportexport/export default二、CommonJS 模块系统CommonJS 是 Node.js 最早也是最广泛使用的模块系统它采用同步加载的方式这意味着模块在加载时会阻塞程序的执行直到加载完成。导出模块在 CommonJS 中使用module.exports或exports对象来导出模块。// math.js function add(a, b) { return a b; } function subtract(a, b) { return a - b; } // 方式一使用 module.exports 导出对象 module.exports { add, subtract }; // 方式二使用 exports 逐个导出 // exports.add add; // exports.subtract subtract;导入模块使用require()函数来导入模块// app.js const math require(./math.js); console.log(math.add(2, 3)); // 5 console.log(math.subtract(5, 2)); // 3 // 也可以解构导入 const { add, subtract } require(./math.js); console.log(add(2, 3)); // 5module.exports 与 exports 的区别// user.js const name Alice; const age 30; // 方式一使用 module.exports 导出单个对象 module.exports { name: name, age: age, sayHello: () { console.log(Hello, my name is ${name}.); } }; // 方式二使用 exports 导出多个具名变量 // exports 是 module.exports 的一个引用 // exports.name name; // exports.age age; // exports.sayHello () { // console.log(Hello, my name is ${name}.); // };// main.js const user require(./user.js); console.log(user.name); // 输出: Alice user.sayHello(); // 输出: Hello, my name is Alice. // 也可以直接解构 const { name, age } require(./user.js); console.log(name); // 输出: AliceCommonJS 特点特点说明同步加载适合服务器端环境模块通常都在本地文件系统中加载速度快运行时加载require()可以在代码的任何位置调用支持条件动态加载缓存机制require()加载的模块会被缓存第二次导入时直接从缓存中读取避免重复加载三、ES ModuleESM规范ESM 是 JavaScript 官方的模块标准它采用异步加载是浏览器和现代 Node.js 应用的首选。启用 ESM要在 Node.js 中使用 ESM有两种方式方式一在package.json中添加type: module{ type: module }方式二将文件扩展名更改为.mjs导出模块ESM 支持两种导出方式具名导出和默认导出。// math.mjs // 具名导出 export function add(a, b) { return a b; } export function subtract(a, b) { return a - b; } export const PI 3.14159; // 默认导出 export default function multiply(a, b) { return a * b; }导入模块// app.mjs // 导入具名导出 import { add, subtract, PI } from ./math.mjs; // 导入默认导出可以自定义名称 import multiply from ./math.mjs; // 同时导入具名和默认导出 import multiply, { add, subtract } from ./math.mjs; console.log(add(2, 3)); // 5 console.log(subtract(5, 2)); // 3 console.log(PI); // 3.14159 console.log(multiply(2, 3)); // 6 // 导入所有具名导出作为对象的属性 import * as math from ./math.mjs; console.log(math.add(2, 3)); // 5 console.log(math.default(2, 3)); // 6默认导出作为 default 属性ESM 特点特点说明异步加载默认是异步加载不会阻塞主线程更适合浏览器环境静态分析import和export语句在代码执行前就可以确定模块的依赖关系支持 Tree Shaking 等优化严格模式ESM 模块默认在严格模式下运行四、CommonJS 和 ESM 的对比项目CommonJSESM语法require/module.exportsimport/export加载机制运行时同步加载编译时静态加载默认支持Node.js 默认支持需.mjs或type: module适合场景后端脚本、老项目前后端现代项目、Tree-shaking是否可混用不能直接混用需额外配置不能直接混用需额外配置五、混合使用Node.js 在较新版本中支持两种模块系统共存。可以在同一个项目中同时使用 CommonJS 和 ESM但需要注意以下几点ESM 中不能直接使用require()和module.exportsCommonJS 中不能直接使用import和exportESM 中导入 CommonJS 模块ESM 会将 CommonJS 模块视为默认导出// commonjs_module.js module.exports { data: hello };// esm_module.mjs import commonModule from ./commonjs_module.js; console.log(commonModule.data); // 输出: helloCommonJS 中导入 ESM 模块需要使用动态import()函数// esm_module.mjs export const name Bob; export const age 25;// commonjs_module.js async function loadESM() { const { name, age } await import(./esm_module.mjs); console.log(name); // 输出: Bob console.log(age); // 输出: 25 } loadESM();六、路径解析规则相对路径导入使用./或../开头// 导入同目录下的模块 const mod require(./myModule); // 导入父目录下的模块 const mod require(../lib/myModule);绝对路径导入使用/开头指向文件系统根目录const mod require(/path/to/module);核心模块导入直接使用模块名称const fs require(fs); const http require(http);第三方模块导入使用模块名称从node_modules中查找const express require(express); const lodash require(lodash);七、动态导入CommonJS 中的动态导入CommonJS 的require()本身就是动态的可以在任何位置调用// 条件导入 if (condition) { const moduleA require(./moduleA); moduleA.doSomething(); } else { const moduleB require(./moduleB); moduleB.doSomething(); }ESM 中的动态导入ESM 使用import()函数进行动态导入返回一个 Promise// 动态导入 async function loadModule(condition) { if (condition) { const moduleA await import(./moduleA.mjs); moduleA.doSomething(); } else { const moduleB await import(./moduleB.mjs); moduleB.doSomething(); } }八、常见问题1. Cannot find module 错误当 Node.js 找不到模块时会报Cannot find module错误。检查路径是否正确模块是否已安装第三方模块文件是否存在2. 循环依赖问题当两个模块相互引用时可能导致其中一个模块获取到不完整的导出对象。建议避免循环依赖如果无法避免使用module.exports提前导出3. ESM 和 CommonJS 混用问题在 ESM 中导入 CommonJS 模块时CommonJS 的module.exports会被视为默认导出在 CommonJS 中导入 ESM 模块时必须使用动态import()文件扩展名很重要ESM 使用.mjsCommonJS 使用.js九、本章小结知识点说明CommonJSNode.js 默认模块系统使用require()/module.exports同步加载ES ModuleJavaScript 官方标准使用import/export异步加载启用 ESM使用.mjs扩展名或在package.json中设置type: module具名导出export const name ...导入时需用{ name }默认导出export default ...导入时可自定义名称混用规则ESM 中可导入 CommonJSCommonJS 中需用import()导入 ESM路径解析核心模块直接名称、本地模块用./、第三方模块从node_modules查找最佳实践对于新的项目强烈推荐使用 ES Modules (ESM)。它不仅是 JavaScript 的官方标准而且与现代前端工具链如 Vite、Next.js兼容性更好能够充分利用 Tree Shaking 等优化技术减少打包后的代码体积。如果你正在维护一个老旧的 CommonJS 项目并且不需要 ESM 的特性可以继续使用 CommonJS。如果需要引入新的依赖或利用 ESM 的新特性可以考虑逐步迁移或者使用混合模式来过渡。
返回列表