Node.js模块化与npm

news2025/5/19 20:02:17

目录

一、模块化简介

二、CommonJS 规范

1. 基本语法

2. 导出模块

3. 导入模块

三、ECMAScript 标准(ESM)

1. 启用 ESM

一、默认导出与导入

1. 基本语法

2. 默认导出(每个模块仅一个)

3. 默认导入

二、命名导出与导入

1.基本语法

2. 命名导出(支持多个)

3. 命名导入

三、混合导出与导入

四、CommonJS 与 ESM 对比

五、互操作性

六、最佳实践

七、npm详解

1. 包的概念

2. npm软件包管理器

3. npm常用命令

4.npm安装所有依赖

5.npm全局软件包


一、模块化简介

在 Node.js 中每个文件都被当做是一个独立的模块,模块内定义的变量和函数都是独立作用域的,因为 Node.js 在执行模块代码时,将使用如下所示的函数封装器对其进行封装:

而且项目是由多个模块组成的,每个模块之间相互独立,按需加载,独立作用域。

但是因为模块内的属性和函数都是私有的,如果对外使用,需要使用标准语法导出和导入才可以,而这个标准叫 CommonJS 标准。

Node.js 支持的模块化标准:

  1. CommonJS 标准语法(默认)
  2. ECMAScript 标准语法

二、CommonJS 规范

1. 基本语法

  1. 导出语法:

    module.exports = {
      对外属性名: 模块内私有变量
    }
  2. 导入语法:

    const 变量名 = require('模块名或路径')
  • 内置模块:写名字,例如:fs,path,http
  • 自定义模块:写模块文件路径,例如:./utils.js
  • 变量名的值接收的就是目标模块导出的对象

2. 导出模块

  • 方式一:module.exports
    直接赋值一个对象、函数或值,作为模块的唯一导出

    // math.js
    const add = (a, b) => a + b;
    module.exports = { add, subtract: (a, b) => a - b };
  • 方式二:exports 对象
    向 exports 对象添加属性,支持多属性导出(本质是 module.exports 的引用)。

    // math.js
    exports.add = (a, b) => a + b;
    exports.subtract = (a, b) => a - b;

3. 导入模块

使用 require() 函数,返回 module.exports 的值。

  • 方式一:导入整个模块

    const math = require('./math.js');
    console.log(math.add(2, 3)); // 5
    
  • 方式二:解构导入(适用于多属性导出)

    const { add, subtract } = require('./math.js');
    console.log(add(2, 3)); // 5

三、ECMAScript 标准(ESM)

1. 启用 ESM

  • 方式一:文件扩展名为 .mjs

  • 方式二:在 package.json 中设置 "type": "module",所有 .js 文件默认按 ESM 解析。


一、默认导出与导入

1. 基本语法

  1. 导出语法:

    export default {
      对外属性名: 模块内私有变量
    }
  2. 导入语法:

    import 变量名 from '模块名或路径'
  • 变量名的值接收的就是目标模块导出的对象

2. 默认导出(每个模块仅一个)

// utils.js
const log = (message) => console.log(message);
export default { log };  // 导出默认函数

3. 默认导入

import utils from './utils.js';
utils.log('Hello');  // 使用默认导出的内容

二、命名导出与导入

1.基本语法

  1. 导出语法:

    export 修饰定义语句
  2. 导入语法:

    import { 同名变量 } from '模块名或路径'
  • 同名变量指的是模块内导出的变量名

2. 命名导出(支持多个)

  • 方式一:单个导出

    export const PI = 3.14;
    export const MAX_SIZE = 100;
  • 方式二:集中导出

    const PI = 3.14;
    const MAX_SIZE = 100;
    export { PI, MAX_SIZE };

3. 命名导入

  • 方式一:直接导入

    import { PI, MAX_SIZE } from './constants.js';
    console.log(PI); // 3.14
  • 方式二:重命名导入

    import { PI as圆周率 } from './constants.js';
  • 方式三:导入全部命名导出为对象

    import * as constants from './constants.js';
    console.log(constants.MAX_SIZE); // 100

三、混合导出与导入

  • 同时导出默认和命名

    // config.js
    export const API_KEY = '123';
    export default { env: 'production' };
  • 混合导入

    import config, { API_KEY } from './config.js';
    console.log(config.env, API_KEY); // 'production' '123'

四、CommonJS 与 ESM 对比

特性CommonJSECMAScript (ESM)
语法module.exports 和 require()export/import 关键字
加载方式动态加载(运行时解析)静态加载(编译时解析)
文件扩展名.js(默认).mjs 或 .js(需 "type": "module"
顶层 this指向 module.exportsundefined
循环依赖处理支持,但需谨慎设计支持,行为更可预测
浏览器兼容性需打包工具(如 Webpack)原生支持(现代浏览器)

五、互操作性

  • ESM 导入 CommonJS 模块

    // ESM 文件
    import cjsModule from './commonjs-module.js';  
    // 默认导入对应 CommonJS 的 module.exports
  • CommonJS 导入 ESM 模块
    仅支持异步 import() 函数(Node.js 14+):

    // CommonJS 文件
    async function loadESM() {
      const esmModule = await import('./esm-module.mjs');
      console.log(esmModule.default);
    }

六、最佳实践

  1. 统一模块规范

    • 新项目优先使用 ESM(趋势和标准)。

    • 旧项目逐步迁移,避免混用导致复杂性。

  2. 路径与扩展名

    • ESM 中导入路径需写完整(如 './file.js')。

    • CommonJS 可省略 .js

  3. 默认导出命名

    • ESM 默认导出建议使用有意义的名称(如 import axios from 'axios')。

  4. 工具链支持

    • 使用 Babel、Webpack 处理模块兼容性(旧环境或混合项目)。


七、npm详解

npm(Node Package Manager) 是 Node.js 的默认包管理工具,也是全球最大的开源软件注册中心。它用于依赖管理、脚本执行、包发布等,是 Node.js 生态系统的核心工具。


1. 包的概念

  1. :将模块,代码,其他资料整合成一个文件夹,这个文件夹就叫包

  2. 包分类

    1. 项目包:主要用于编写项目和业务逻辑

    2. 软件包:封装工具和方法进行使用

  3. 包要求:根目录中,必须有 package.json 文件(记录包的清单信息)

  4. 包使用:引入一个包文件夹到代码中时,默认引入的是包文件节下的 index.js 模块文件里导出的对象,如果没有 index.js 文件,则会引入 package.json 里 main 属性指定的文件模块导出的对象

小结:

1. 什么是包?

  • 将模块,代码,其他资料聚合成的文件夹

2. 包分为哪 2 类呢?

  • 项目包:编写项目代码的文件夹,软件包:封装工具和方法供开发者使用

3. package.json 文件的作用?

  • 记录软件包的名字,作者,入口文件等信息

4. 导入一个包文件夹的时候,导入的是哪个文件?

  • 默认 index.js 文件,或者 main 属性指定的文件

2. npm软件包管理器

  1. npm 使用步骤:

    1. 初始化清单文件: npm init -y (得到 package.json 文件,有则跳过此命令)

      注意 -y 就是所有选项用默认值,所在文件夹不要有中文/特殊符号,建议英文和数字组成,因为 npm 包名限制建议用英文和数字或者下划线中划线

    2. 下载软件包:npm i 软件包名称

    3. 使用软件包

  2. 下载的包会存放在哪里?

  • 当前项目下的 node_modules 中,并记录在 package.json 中

3. npm常用命令

命令作用
npm init初始化项目并生成 package.json
npm install <package>安装包(默认添加到 dependencies
npm install <package> --save-dev安装包到 devDependencies
npm install -g <package>全局安装(如 CLI 工具)
npm uninstall <package>卸载包
npm update <package>更新指定包
npm audit检查依赖安全漏洞
npm publish发布包到 npm 仓库
npm login登录 npm 账号
npm ci根据 package-lock.json 安装依赖
npm outdated检查过时的依赖

4.npm安装所有依赖

  • 我们拿到了一个别人编写的项目,但是没有 node_modules,项目能否正确运行?

    不能,因为缺少了项目需要的依赖软件包,比如要使用 dayjs 和 lodash,但你项目里没有这个对应的源码,项目会报错

  • 为何没有给我 node_modules?

    因为每个人在自己的本机使用 npm 下载,要比磁盘间传递要快(npm 有缓存在本机)

  • 如何得到需要的所有依赖软件包呢?

    直接在项目目录下,运行终端命令:npm i 即可安装 package.json 里记录的所有包和对应版本到本项目中的 node_modules

小结:

1. 当前项目中只有 package.json 没有 node_modules 怎么办?

  • 当前项目目录下,打开终端,执行 npm i 安装所有依赖软件包

2. 为什么 node_modules 不进行传递?

  • 因为用 npm 下载有缓存在本机,比磁盘之间传递要快

5.npm全局软件包

  1. 软件包区别:

    • 本地软件包:当前项目内使用,封装属性和方法,存在于 node_modules

    • 全局软件包:本机所有项目使用,封装命令和工具,存在于系统设置的位置

  2. nodemon 作用:替代 node 命令,检测代码更改,自动重启程序

  3. 使用:

    1. 安装:npm i nodemon -g (-g 代表安装到全局环境中)

    2. 运行:nodemon 待执行的目标 js 文件


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2337494.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

nginx中的代理缓存

1.缓存存放路径 对key取哈希值之后&#xff0c;设置cache内容&#xff0c;然后得到的哈希值的倒数第一位作为第一个子目录&#xff0c;倒数第三位和倒数第二位组成的字符串作为第二个子目录&#xff0c;如图。 proxy_cache_path /xxxx/ levels1:2 2.文件名哈希值

【前端vue生成二维码和条形码——MQ】

前端vue生成二维码和条形码——MQ 前端vue生成二维码和条形码——MQ一、安装所需要的库1、安装qrcode2、安装jsbarcode 二、使用步骤1、二维码生成2、条形码生成 至此&#xff0c;大功告成&#xff01; 前端vue生成二维码和条形码——MQ 一、安装所需要的库 1、安装qrcode 1…

flutter 桌面应用之窗口自定义

在开发桌面软件的时候我们经常需要配置软件的窗口的大小以及位置 我们有两个框架选择:window_manager和bitsdojo_window 对比bitsdojo_window 特性bitsdojo_windowwindow_manager自定义标题栏✅ 支持❌ 不支持控制窗口行为&#xff08;大小/位置&#xff09;✅&#xff08;基本…

华为OD机试真题——MELON的难题(2025A卷:200分)Java/python/JavaScript/C++/C语言/GO六种最佳实现

2025 A卷 200分 题型 本文涵盖详细的问题分析、解题思路、代码实现、代码详解、测试用例以及综合分析&#xff1b; 并提供Java、python、JavaScript、C、C语言、GO六种语言的最佳实现方式&#xff01; 2025华为OD真题目录全流程解析/备考攻略/经验分享 华为OD机试真题《MELON的…

【C++】深入浅出之继承

目录 继承的概念及定义继承的定义继承方式和访问限定符protected与private的区别 默认继承方式继承类模板基类和派生类对象赋值兼容转换继承中的作⽤域(隐藏关系)相关面试题⭐ 派生类的默认成员函数⭐构造函数拷贝构造赋值重载析构函数 继承与友元继承与静态成员继承的方式菱形…

在 macOS 上切换默认 Java 版本

下载javasdk 打开android studio -> setting -> build.execution,dep -> build tools -> gradle -> Gradle JDK -> download JDK… 点击下载&#xff0c;就下载到了 ~/Library/Java/JavaVirtualMachines/ 安装 jenv brew install jenv将 jenv 集成到 Shell …

【安卓开发】【Android Studio】Menu(菜单栏)的使用及常见问题

一、菜单栏选项 在项目中添加顶部菜单栏的方法&#xff1a; 在res目录下新建menu文件夹&#xff0c;在该文件夹下新建用于菜单栏的xml文件&#xff1a; 举例说明菜单栏的写法&#xff0c;只添加一个选项元素&#xff1a; <?xml version"1.0" encoding"ut…

jenkins凭据管理(配置github密钥)

凭据分类 Jenkins可以保存下面几种凭证&#xff1a; Secret text&#xff1a;例如 API Token&#xff08;例如GitHub的个人access token&#xff09;。Username with password&#xff1a;指的是登录GitHub的用户名和密码&#xff0c;可以作为单独的组件处理&#xff0c;也可以…

数据结构|排序算法(三)选择排序 堆排序 归并排序

一、选择排序 1.算法思想 选择排序&#xff08;Selection Sort&#xff09;是一种简单直观的排序算法&#xff0c;其基本思想是&#xff1a;每次都从待排序部分中选出最小的一个数据和待排序的第一个数据交换。 将待排序序列分为已排序和未排序两部分&#xff0c;初始时已排…

MAC Mini M4 上测试Detectron2 图像识别库

断断续续地做图像识别的应用&#xff0c;使用过各种图像识别算法&#xff0c;一开始使用openCV 做教室学生计数的程序。以后又使用YOLO 做医学伤口检测程序。最近&#xff0c;开始使用meta 公司的Detectron2.打算做OCR 文档结构分析 Detectron2 的开发者是 Meta 的 Facebook AI…

OpenCv高阶(四)——角点检测

一、角点检测 在计算机视觉中&#xff0c;角点检测是识别图像中局部区域&#xff08;角点&#xff09;的关键技术&#xff0c;这些区域通常是两条或多条边缘的交点&#xff0c;具有丰富的结构信息&#xff0c;常用于图像匹配、跟踪、三维重建等任务。 Harris角点检测算法是一…

TOA与AOA联合定位的高精度算法,三维、4个基站的情况,MATLAB例程,附完整代码

本代码实现了三维空间内目标的高精度定位,结合到达角(AOA) 和到达时间(TOA) 两种测量方法,通过4个基站的协同观测,利用最小二乘法解算目标位置。代码支持噪声模拟、误差分析及三维可视化,适用于无人机导航、室内定位等场景。订阅专栏后可获得完整代码 文章目录 运行结果…

揭秘大数据 | 23、软件定义网络

软件定义网络将网络的边缘从硬件交换机推进到了服务器里面&#xff0c;将服务器和虚拟机的所有部署、管理的职能从原来的系统管理员网络管理员的模式变成了纯系统管理员的模式&#xff0c;让服务器的业务部署变得简单&#xff0c;不再依赖于形态和功能各异的硬件交换机&#xf…

Elastic 9.0/8.18:BBQ、EDOT 和 LLM 可观察性、攻击发现、自动导入以及 ES|QL JOIN

作者&#xff1a;来自 Elastic Brian Bergholm 今天&#xff0c;我们很高兴地宣布 Elastic 9.0 和 8.18 的正式发布&#xff01; 如果你觉得 8.x 版本系列已经很令人印象深刻&#xff0c;包含了 ANN、TSDB、ELSER、ES|QL、LTR、BBQ、logsdb 索引模式等功能&#xff0c;那你一定…

当 AI 有了 “万能插头” 和 “通用语言”:MCP 与 A2A 如何重构智能体生态

目录 一、MCP&#xff1a;让 AI 拥有 “万能工具插头” 1.1 从 “手工对接” 到 “即插即用” 1.2 架构解密&#xff1a;AI 如何 “指挥” 工具干活 1.3 安全优势&#xff1a;数据不出门&#xff0c;操作可追溯 二、A2A&#xff1a;让智能体学会 “跨语言协作” 2.1 从 “…

中间件--ClickHouse-3--列式存储和行式存储理解

在数据库存储中&#xff0c;列式存储&#xff08;Columnar Storage&#xff09;与行式存储&#xff08;Row-based Storage&#xff09;是两种不同的数据组织方式&#xff0c;它们各自适用于不同类型的应用场景。 1、行式存储&#xff08;MySQL&#xff09; 存储方式&#xff…

逻辑回归 (Logistic Regression)

文章目录 逻辑回归 (Logistic Regression)问题的引出Sigmoid function逻辑回归的解释决策边界 (Decision boundary)逻辑回归的代价函数机器学习中代价函数的设计1. 代价函数的来源&#xff08;1&#xff09;从概率模型推导而来&#xff08;统计学习视角&#xff09;&#xff08…

燕山大学计算机网络之Java实现TCP数据包结构设计与收发

觉得博主写的好&#xff0c;给博主点点免费的关注吧&#xff01; 目录 摘要.................................................................................................................... 4 前言.............................................................…

JavaEE——线程安全

目录 前言1.线程安全的定义2.线程安全问题产生的原因2.1 多个线程修改一个变量2.2 修改操作不是原子的2.3 内存可见性引起的线程安全问题 3.解决线程安全问题的方法3.1 通过synchronized关键字加锁3.2 使用volatile关键字 总结 前言 在使用多线程的时候&#xff0c;难免会出现…

[redis进阶一]redis的持久化(2)AOF篇章

目录 一 为什么有了RDB持久化机制还要有AOF呢 板书介绍具体原因: ​编辑二 详细讲解AOF机制 (1)AOF的基本使用 1)板书如下 2)开启AOF机制: 3) AOF工作流程 (2)AOF是否会影响到redis性能 ​编辑 (3)AOF缓冲区刷新策略 (4)AOF的重写机制 板书如下: 为什么要有这个重写机…