Node.js npm 入门
上一篇 Node.js 模块系统 讲了怎么用自己写的模块,这篇解决怎么用别人写好的模块。npm 是 Node.js 自带的包管理器,全世界的开发者都在往它上面传代码。你会学到初始化项目、安装依赖、理解版本号规则,以及用 scripts 命令管理运行方式。
npm 是什么
npm 是 Node.js 随附安装的包管理器,安装 Node.js 时自动装好。它连接着 npm registry,全球最大的开源包仓库,目前有超过两百万个包,任何功能几乎都能搜到现成的。
它的工作原理很简单,npm install xxx 从 registry 下载包到本地,你再用模块系统引入使用。package.json 记录项目装了什么,别人拿到你的项目跑一遍 npm install 就能恢复全部依赖。想系统了解 npm,先看 NPM 介绍。
日常高频的命令就这几个,先混个脸熟。
| 命令 | 作用 |
|---|---|
npm init |
初始化项目,生成 package.json |
npm install xxx |
安装依赖并写入 package.json |
npm uninstall xxx |
卸载依赖,同步移除记录 |
npm update |
按版本规则升级依赖 |
npm list |
查看已安装的依赖树 |
npm run xxx |
执行 scripts 里定义的命令 |
npm init 初始化项目
进入项目目录执行 npm init,按提示输入信息,最后生成 package.json。嫌麻烦直接 npm init -y,跳过提问全部用默认值。
mkdir my-project
cd my-project
npm init -y
生成的 package.json 长这样。
{
"name": "my-project",
"version": "1.0.0",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
}
}
| 字段 | 作用 |
|---|---|
| name | 项目名称,发布到 registry 时必须是唯一包名 |
| version | 项目版本号,遵循语义化版本规则 |
| main | 入口文件,别人 require 你的包时加载它 |
| scripts | 自定义命令,用 npm run 执行 |
各字段的详细含义见 NPM package.json,这里先知道每个字段是干什么的即可。
安装依赖
npm install chalk@4 # 生产依赖,会写进 dependencies
npm install -D nodemon # 开发依赖,写进 devDependencies
| 命令 | 写入位置 | 用途 | 举例 |
|---|---|---|---|
npm install xxx |
dependencies | 运行时必须的依赖 | 服务器框架、请求库 |
npm install -D xxx |
devDependencies | 只开发时用的依赖 | 打包工具、代码检查、测试框架 |
开发依赖不会出现在线上环境,因为部署时 npm install --production 会跳过它们。具体机制看 NPM install命令。
装错了想卸载用 npm uninstall xxx,它会从 node_modules 和 package.json 里一起移除。想升级依赖用 npm update,按版本号规则升到允许的最新版,不会跨过 ^ 或 ~ 的限制范围。
node_modules 与 package-lock.json
依赖装在项目根目录的 node_modules 文件夹里,而且依赖的依赖也会一并装进来,一个项目几十 MB 很正常。
首次 npm install 会生成 package-lock.json,它记录每个依赖的精确版本和依赖关系树。这个文件必须提交到 git,这样团队所有人装出来的依赖完全一致,避免”我这能跑你那不能跑”。node_modules 则相反,体积大又随时能重建,要写进 .gitignore 不提交。
语义化版本 SemVer
版本号 1.2.3 三段分别是主版本、次版本、补丁版本。npm 安装时默认写 ^1.2.3,加不同前缀允许升级的范围不同。
| 写法 | 含义 | 允许范围 | 升级粒度 |
|---|---|---|---|
^1.2.3 |
允许次版本升级 | >= 1.2.3 且 < 2.0.0 | 默认写法,小升级 |
~1.2.3 |
只允许补丁升级 | >= 1.2.3 且 < 1.3.0 | 更保守,只修 bug |
1.2.3 |
精确锁定 | 只能 1.2.3 | 完全不动 |
主版本号变更是破坏性升级,^ 不会自动升过去。哪天依赖升级把项目弄坏了,方向都查不到,这种情况可以看 NPM 版本管理 和 NPM 依赖解析。
npm scripts 自定义命令
package.json 的 scripts 字段可以定义快捷命令。
{
"scripts": {
"start": "node index.js",
"dev": "node --watch index.js",
"color": "node colorful.js",
"precolor": "node check.js"
}
}
npm run color # 执行 node colorful.js
npm start # start 和 test 可以省略 run,直接 npm start
npm run dev # --watch 是 Node 20 内置的热更新,文件改动自动重启
pre 和 post 前缀有特殊效果,precolor 会在 color 之前自动执行,postcolor 在之后执行,适合做启动前的检查。完整用法见 NPM scripts脚本。
实践
建一个彩色文字小工具,体验完整的 npm 工作流。
mkdir color-cli
cd color-cli
npm init -y
npm install chalk@4
先运行一个最简单的验证。
// index.js
const chalk = require("chalk");
console.log(chalk.green("npm 安装成功!"));
node index.js
# 终端里出现一行绿色文字
再加一条 scripts 命令。
{
"scripts": {
"color": "node colorful.js"
}
}
// colorful.js
const chalk = require("chalk");
console.log(chalk.red("这是红色文字"));
console.log(chalk.green("这是绿色文字"));
console.log(chalk.blue("这是蓝色文字"));
console.log(chalk.bgYellow.black("黄底黑字"));
npm run color
终端里会依次出现红、绿、蓝三行彩色文字和一行黄底黑字,彩色的输出就是 chalk 包干的事。最后用 npm list 确认一下装了什么。
npm list
# color-cli@1.0.0
# └── chalk@4.1.2
整个流程就是 npm 日常的完整闭环,初始化项目、装依赖、写代码、用命令运行。
常见坑
- chalk 装成最新版(5.x)后
require("chalk")报错。chalk 5 只支持 ES Modules,教程里用npm install chalk@4就是绕开这个问题,之后学 ESM 再升级。 - 改了代码运行没变化,多半是没重新执行
node,Node 没有热更新,每次改完都要重跑。 node_modules提交到 git。这个目录随时可以重新生成,提交了只会让仓库臃肿,记得写进.gitignore。- package-lock.json 不提交,团队里每个人依赖版本对不上。
- 依赖装坏了想重装。删掉 node_modules 和 package-lock.json 后重新
npm install,比手动改文件靠谱。 - 国内网络下载慢,可以配置镜像源,方法见 Node.js 环境搭建 里的 npm 镜像一节。
依赖管理跑通了,接下来学读写文件,用 fs 模块真正操作磁盘,见 Node.js fs 模块。