npm 基础操作:从零开始的依赖管理

说实话,npm 的基础操作,我每天至少要用几十次。刚入行那会儿,我总觉得这些命令太简单了,不就是 installuninstall 嘛。直到有一次,我在生产环境上因为 npm update 搞出了大问题...嗯,从那以后,我对每个命令都多了几分敬畏。

今天咱们就把这四个核心操作——initinstalluninstallupdate——彻底讲透。你想想看,这些命令你每天都在敲,但你真的了解它们背后的门道吗?

1. npm init:项目的起点

每个 Node.js 项目,都是从 npm init 开始的。它会在当前目录生成一个 package.json 文件,这个文件就是项目的「身份证」。

基本用法:

# 交互式创建
npm init

# 快速创建(跳过所有问题)
npm init -y

# 或者
npm init --yes

我个人习惯用 npm init -y,省时间。但要注意,这样生成的 package.json 里,name 字段会直接取当前文件夹的名字。如果文件夹名里有中文或特殊字符,后面发布包时会报错。

我曾经踩过的坑: 有次项目文件夹叫「my-project-v2」,用 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

我在项目中遇到过很多新人分不清 dependenciesdevDependencies。其实很简单:

  • dependencies:项目运行时需要的包。比如 expresslodashaxios。没有它们,你的代码跑不起来。
  • devDependencies:开发时需要的工具。比如 webpackeslintjest。线上环境不需要这些。
重要原则: 不要把开发工具装到 dependencies 里。否则你的线上环境会多出一堆没用的包,拖慢部署速度,还可能引入安全漏洞。

安装后的变化:

执行 npm install lodash 后,会发生三件事:

  1. package.jsondependencies 里多了 "lodash": "^4.17.21"
  2. node_modules 目录下多了 lodash 文件夹
  3. 生成了 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,再小范围测试,最后才更新到生产环境

安全更新建议:

  1. npm outdated 查看哪些包有更新
  2. 逐个更新,不要一次全更新
  3. 更新后跑一遍测试用例
  4. npm ci 代替 npm install 来保证安装一致性
核心总结:
  • npm init 是项目的起点,package.json 是项目的身份证
  • npm install 区分生产依赖和开发依赖,别装错地方
  • npm uninstall 要用命令,别手动删文件夹
  • npm update 要谨慎,版本范围不是闹着玩的

这四个命令,说白了就是依赖管理的「增删改查」。你想想看,每天几十次的操作,如果每个都理解透彻了,能省下多少排查问题的时间?

下一章,咱们聊聊 package-lock.json 的底层原理。为什么我说它比 package.json 还重要?到时候你就知道了。