一、模块化:让代码像搭积木一样灵活

想象一下,写代码就像搭积木:把一个大项目拆成多个小文件(模块),每个模块负责一件事,用的时候拼起来。这就是模块化。

1. 为什么要用模块化?

  • 方便复用:比如写一个 “时间格式化” 的功能,拆成模块后,所有项目都能直接用。
  • 避免混乱:每个模块里的变量、函数只在自己内部有效(模块作用域),不会污染全局。
  • 好维护:改一个功能只需要改对应的模块,不用动整个项目。

2. Node.js 的模块分类

Node.js 里有 3 种模块,用require()命令就能加载:

模块类型 来源 例子 加载方式
内置模块 Node.js 官方提供 fs(操作文件)、path(处理路径) require(‘fs’)
自定义模块 自己写的.js 文件 myModule.js require(‘./myModule’)(必须加./或…/)
第三方模块 别人写的工具包 moment(格式化时间) 先下载,再require(‘moment’)

在这里插入图片描述
注意

  • 使用require()方法加载其它模块时,会执行被加载模块中的代码。
  • 使用require()方法加载自定义模块时,可省略文件的后缀名

1. 什么是模块作用域?

和函数作用域类似,在自定义模块中定义的变量、方法等成员,只能在当前模块内被访问,这种模块级别的访问限制,叫做模块作用域。
好处:
防止了全局变量污染的问题

2. 如何共享模块里的内容?

模块里的东西默认 “私有”,想给其他模块用,需要主动 “暴露” 出去。

方法 1:用module.exports暴露

// 新建一个自定义模块:tools.js
const sayHello = () => {
  return "Hello from tools!";
};

// 暴露成员(可以是变量、函数、对象)
module.exports = {
  sayHello,
  version: "1.0.0"
};

方法 2:用exports简化(和module.exports默认指向同一个对象)

// tools.js
exports.add = (a, b) => a + b;
exports.sub = (a, b) => a - b;

加载并使用模块

// 加载自定义模块tools.js
const tools = require('./tools');

console.log(tools.sayHello()); // 输出:Hello from tools!
console.log(tools.add(2, 3)); // 输出:5

注意:require()加载模块时,得到的是module.exports指向的对象(exports只是它的快捷方式)。

4. Node.js中的模块化规范

Node.js遵循了CommonJS模块化规范,CommonJS 规定了模块的特性和各模块之间如何相互依赖。
CommonJS规定:

  1. 每个模块内部,module 变量代表当前模块。
  2. module变量是一个对象, 它的exports属性(即module.exports)是对外的接口。
  3. 加载某个模块,实是加载该模块的module.exports属性。require()方法用于加载模块。

二、npm:Node.js 的 “应用商店”

当你需要现成的功能(比如格式化时间、处理 Excel),不用自己写,直接用别人做好的 “包”(第三方模块)。npm就是管理这些包的工具(Node.js 自带,不用额外安装),是全球最大的开源库生态系统,包含超过200万个可重用代码包。

1. 常用 npm 命令

命令 作用
npm init 初始化项目
npm i 包名 安装包(记录到dependencies,开发和上线都用)
npm i 包名 -D 安装开发依赖(只在开发时用,记录到devDependencies)
npm uninstall 包名 卸载包
npm i 从package.json恢复所有依赖(比如拿到别人的项目时)
npm i 包名@版本号 安装指定版本 (比如npm i moment@2.22.2)
npm list 查看已安装包

2. 基本用法:安装和使用包

步骤 1:初始化项目(生成package.json)
package.json是项目的 “说明书”,记录项目的名称、版本号、描述等以及用了哪些包。新建项目文件夹,打开终端执行:

npm init -y  # 快速生成package.json(-y表示默认配置)

包管理文件package.json

{
  "name": "my-project",
  "version": "1.0.0",
  "description": "示例项目",
  "main": "index.js",
  "dependencies": {
    "express": "^4.18.2"
  },
  "devDependencies": {
    "nodemon": "^3.0.1"
  }
}
  • dependencies:生产环境依赖(项目运行时需要)
  • devDependencies:开发环境依赖(仅开发时需要)

注意package.json文件相当于mavenpom.xml

步骤 2:安装包(以格式化时间的moment为例)

npm install moment  # 安装最新版
# 简写:npm i moment

安装开发依赖

npm install eslint --save-dev
# 或简写
npm i eslint -D

安装后会多两个东西:

  • node_modules:存放下载的包(不用手动改)。
  • package-lock.json:记录包的详细信息(版本、下载地址等)。

注意:程序员不要手动修改node_modulespackage-lock.json文件中的任何代码,npm包管理工具会自动维护它们。

步骤 3:使用包

// 导入moment包
const moment = require('moment');

// 格式化当前时间
const now = moment().format('YYYY-MM-DD HH:mm:ss');
console.log(now); // 输出:2024-08-07 15:30:00

3. 解决下包慢的问题

默认从国外服务器下载,速度慢?切换到淘宝镜像

# 查看当前镜像源
npm config get registry

# 切换到淘宝镜像
npm config set registry=https://registry.npm.taobao.org/

也可以安装nrm工具快速切换镜像:

npm i nrm -g  # 全局安装nrm
nrm ls  # 查看所有镜像源
nrm use taobao  # 切换到淘宝镜像

4. 包的分类

  • 项目包:安装在当前项目的node_modules里,只给当前项目用。
    • 核心依赖(dependencies):上线后还需要(比如moment)。
    • 开发依赖(devDependencies):只开发时用(比如代码检查工具eslint)。
  • 全局包:安装在电脑全局目录,所有项目都能用(一般是工具类,比如nrm)。
    npm i 包名 -g  # 全局安装
    npm uninstall 包名 -g  # 全局卸载
    
    
    

三、模块加载机制:Node.js 怎么找模块?

当你用require('xxx')时,Node.js 会按以下规则找模块,优先级从高到低:

  1. 先查缓存:模块加载过一次后会缓存,下次直接用(提高速度)。
  2. 再找内置模块:比如require(‘fs’),直接加载 Node.js 自带的fs。
  3. 然后找自定义模块
    • 必须带./../(比如require(‘./tools’))。
    • 没写扩展名时,会依次尝试.js.json.node
  4. 最后找第三方模块
    当前项目的node_modules里找,找不到就去上层目录的node_modules找,直到根目录。

四、实战:创建和使用自定义模块

1. 创建工具模块

// stringUtils.js
module.exports = {
  // 首字母大写
  capitalize: str => str.charAt(0).toUpperCase() + str.slice(1),
  
  // 反转字符串
  reverse: str => [...str].reverse().join('')
};

2. 使用工具模块

// main.js
const { capitalize, reverse } = require('./stringUtils');

console.log(capitalize('hello')); // "Hello"
console.log(reverse('world')); // "dlrow"

3. 安装并使用第三方包

npm install lodash

// 使用lodash
const _ = require('lodash');

const numbers = [1, 2, 3, 4, 5];
console.log(_.shuffle(numbers)); // 随机打乱数组

五、最佳实践

1. 模块拆分原则:

  • 一个模块只做一件事
  • 保持模块小而专一
  • 避免循环依赖

2. 包管理技巧:

  • 使用语义化版本:主版本.次版本.补丁版本

  • 定期更新依赖:npm outdated + npm update

  • 添加.gitignore文件:

    node_modules/
    .env
    

3. 项目结构示例:

my-project/
├── node_modules/    # 第三方依赖
├── src/             # 源代码
│   ├── utils/       # 工具模块
│   ├── services/    # 服务模块
│   └── index.js     # 入口文件
├── package.json     # 项目配置
└── README.md        # 项目说明

总结:核心要点

  • 模块化:拆分成小文件,用module.exports暴露,require()加载,避免全局污染。
  • npm:管理第三方包的工具,npm i安装,package.json记录依赖,淘宝镜像加速下载。
  • 加载机制:缓存→内置模块→自定义模块→第三方模块,按这个顺序找模块。
Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐