npm 基础操作:从零开始的依赖管理
说实话,npm 的基础操作,我每天至少要用几十次。刚入行那会儿,我总觉得这些命令太简单了,不就是 install 和 uninstall 嘛。直到有一次,我在生产环境上因为 npm update 搞出了大问题...嗯,从那以后,我对每个命令都多了几分敬畏。
今天咱们就把这四个核心操作——init、install、uninstall、update——彻底讲透。你想想看,这些命令你每天都在敲,但你真的了解它们背后的门道吗?
1. npm init:项目的起点
每个 Node.js 项目,都是从 npm init 开始的。它会在当前目录生成一个 package.json 文件,这个文件就是项目的「身份证」。
基本用法:
# 交互式创建
npm init
# 快速创建(跳过所有问题)
npm init -y
# 或者
npm init --yes
我个人习惯用 npm init -y,省时间。但要注意,这样生成的 package.json 里,name 字段会直接取当前文件夹的名字。如果文件夹名里有中文或特殊字符,后面发布包时会报错。
npm init -y 后,name 字段变成了 my-project-v2。后来想发布到 npm 仓库,发现名字里不能有特殊字符...最后只能手动改 package.json。
package.json 的核心字段:
| 字段 | 说明 | 是否必填 |
|---|---|---|
| name | 项目名称,只能是小写字母、数字、-、_ | 是 |
| version | 版本号,遵循 semver 规范 | 是 |
| description | 项目描述,方便别人理解 | 推荐 |
| main | 入口文件,默认 index.js | 推荐 |
| scripts | 自定义脚本命令 | 推荐 |
| dependencies | 生产环境依赖 | 自动生成 |
| devDependencies | 开发环境依赖 | 自动生成 |
npm init -y 生成后,再手动编辑。或者用 npm config set init.author.name "你的名字" 设置默认值,这样每次 npm init 都会自动填充。
2. npm install:安装依赖的艺术
这是 npm 最核心的命令。说白了,就是把别人写好的代码下载到你的项目里。
安装方式一览:
# 安装到 dependencies(生产依赖)
npm install lodash
npm install lodash --save # 旧版本写法,现在默认就是 --save
# 安装到 devDependencies(开发依赖)
npm install webpack --save-dev
npm install webpack -D # 简写
# 安装全局包
npm install -g nodemon
# 安装指定版本
npm install lodash@4.17.21
# 从 package.json 安装所有依赖
npm install
我在项目中遇到过很多新人分不清 dependencies 和 devDependencies。其实很简单:
- dependencies:项目运行时需要的包。比如
express、lodash、axios。没有它们,你的代码跑不起来。 - devDependencies:开发时需要的工具。比如
webpack、eslint、jest。线上环境不需要这些。
dependencies 里。否则你的线上环境会多出一堆没用的包,拖慢部署速度,还可能引入安全漏洞。
安装后的变化:
执行 npm install lodash 后,会发生三件事:
package.json的dependencies里多了"lodash": "^4.17.21"node_modules目录下多了lodash文件夹- 生成了
package-lock.json文件(锁定版本)
package-lock.json 一定要提交到 Git 仓库!它记录了每个依赖的确切版本,保证团队所有成员和 CI 环境安装的依赖完全一致。我曾经因为没提交这个文件,导致同事安装的版本和我不同,线上出了诡异的 bug...
3. npm uninstall:卸载依赖的正确姿势
卸载看起来简单,但很多人会犯一个低级错误——直接删 node_modules 里的文件夹。千万别这么干!
正确做法:
# 卸载生产依赖
npm uninstall lodash
npm uninstall lodash --save # 旧写法
# 卸载开发依赖
npm uninstall webpack --save-dev
npm uninstall webpack -D
# 卸载全局包
npm uninstall -g nodemon
为什么不能直接删文件夹?因为 npm uninstall 会做三件事:
- 从
node_modules里删除包 - 从
package.json里移除对应的依赖记录 - 更新
package-lock.json
你手动删文件夹,package.json 里还留着记录。下次别人 npm install 时,又会装回来。这不是白忙活吗?
npm ls 包名 查看。比如 npm ls lodash,它会告诉你这个包在依赖树中的位置。
4. npm update:更新依赖的学问
更新依赖,这是最容易出问题的操作。我见过太多人直接 npm update,然后项目就炸了。
基本用法:
# 更新所有依赖(按 package.json 中的版本范围)
npm update
# 更新指定包
npm update lodash
# 更新到最新版本(忽略版本范围)
npm install lodash@latest
版本范围的含义:
假设 package.json 里写的是 "lodash": "^4.17.21",这个 ^ 是什么意思?
| 符号 | 含义 | 示例 | 允许更新的范围 |
|---|---|---|---|
| ^ | 兼容大版本 | ^4.17.21 | 4.x.x(4.17.21 ~ 4.99.99) |
| ~ | 兼容小版本 | ~4.17.21 | 4.17.x(4.17.21 ~ 4.17.99) |
| 无符号 | 锁定版本 | 4.17.21 | 只能 4.17.21 |
| * | 任意版本 | * | 任何版本 |
"express": "^4.16.0",我直接 npm update,结果从 4.16 跳到了 4.18。4.18 里废弃了几个 API,导致线上接口报错。从那以后,我更新依赖都遵循这个原则:先看 changelog,再小范围测试,最后才更新到生产环境。
安全更新建议:
- 用
npm outdated查看哪些包有更新 - 逐个更新,不要一次全更新
- 更新后跑一遍测试用例
- 用
npm ci代替npm install来保证安装一致性
npm init是项目的起点,package.json是项目的身份证npm install区分生产依赖和开发依赖,别装错地方npm uninstall要用命令,别手动删文件夹npm update要谨慎,版本范围不是闹着玩的
这四个命令,说白了就是依赖管理的「增删改查」。你想想看,每天几十次的操作,如果每个都理解透彻了,能省下多少排查问题的时间?
下一章,咱们聊聊 package-lock.json 的底层原理。为什么我说它比 package.json 还重要?到时候你就知道了。