npm使用手册

摘要

npm简介

  • npm(Node Package Manager)是 Node.js 的包管理工具,也是 JavaScript 编程社区中最常用的管理和分享代码的工具。

  • 它允许开发者轻松地安装、共享、和管理在项目中使用的 JavaScript 包。

  • npm 分为两个主要部分:命令行工具(CLI)和 npm 注册表。

  • 命令行工具(CLI):用于与注册表进行交互,安装和管理项目中的依赖。

  • npm 注册表:一个在线的数据库,存储了数百万个开源的 Node.js 包,开发者可以在自己的项目中使用这些包。

npm 的安装与配置

  • npm 通常与 Node.js 一起安装,因此安装 Node.js 会自动安装 npm。

  • 从 Node.js 官网下载并安装 Node.js。

  • 跟随Node.js 官网–Download的提示完成 Node.js 的安装,

  • 现在官方更推荐使用nvm的方式进行安装,当然你也可以选择对应系统的二进制包进行安装(此种方法要将node的bin目录配置到PATH环境变量),node.js安装完成后,npm 也会一起安装。

  • 打开命令行或终端工具,输入以下命令来验证是否成功安装

1
2
npm -v
node -v

npm 常用命令

npm init:初始化项目

  • npm init命令用于初始化一个新的 Node.js 项目,生成一个package.json文件,其中包含项目的元数据和配置。

1
2
3
mkdir my-project
cd my-project
npm init
  • 执行该命令后,会按照提示输入一些项目相关的信息,如名称、版本、描述等。也可以使用 npm init -y 跳过提示,生成一个默认的package.json文件。

npm create:基于模板创建项目

  • npm create命令用于基于模板创建一个新的 Node.js 项目,比如我们创建一个基于Vue的Web项目,可以执行以下命令:

1
npm create vue@latest

npm install:安装依赖包

  • npm install命令用于安装项目中所需的依赖包,比如在package.json文件中指定了依赖包,可以执行以下命令:

1
npm install
  • 安装完成后,会在node_modules目录下生成依赖包,并更新package-lock.json文件。

  • 安装指定依赖包,默认安装最新版,自动将依赖包添加到 package.json 的 “dependencies” 部分。

1
npm install express
  • 如果需要安装特定的版本,可以执行以下命令:

1
npm install express@4.17.1
  • 安装开发依赖包,安装并写入package.json的"devDependencies"中

1
2
3
npm install express -D
# 等价于
npm install express --save-dev
  • 安装全局依赖包

1
2
3
4
5
6
7
# 全局安装的包会被安装到全局的node_modules目录下,不会被安装到项目目录下,也不会出现在package.json中
npm install express -g
# 等价于
npm install express --global

# 全局node_modules目录路径查看
npm root -g
  • 从本地安装依赖包

1
2
# 从本地安装
npm install ./path/to/local_project
  • 从远程Git仓库安装依赖包

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 安装公共项目:
# npm install https://github.com/user_name/node_project
npm install https://github.com/trentm/json.git
# 缩写,如果是gitlab仓库,则需要使用gitlab前缀,推荐使用上面的完整语义版本
npm install github:trentm/json

# 安装特定提交:
# npm install https://github.com/user_name/node_project#commit
npm install https://github.com/trentm/json.git\#6912b25272312d0f13ad32e98ebc1b4deb6334cc
# 安装特定分支:
# npm install https://github.com/user_name/node_project#branchName
npm install https://github.com/trentm/json.git\#streaming
# 通过标签安装:
# npm install https://github.com/user_name/node_project#tag
npm install https://github.com/trentm/json.git\#10.0.0
# 安装特定版本:
# npm install https://github.com/user_name/node_project#version
npm install https://github.com/trentm/json.git\#10.0.0
# 完整的语义版本:
npm install https://github.com/trentm/json.git\#semver:v10.0.0

# 使用git的ssh repo link 安装私有库:后面同样可以接 commit、branchName、tag、version等
# npm install git+ssh://git@github.com:user_name/node_project.git
npm install git+ssh://git@github.com/trentm/json.git

npm update:更新依赖包

  • npm update命令用于更新项目中的依赖包,比如要更新express依赖包到最新版本,可以执行以下命令:

1
2
3
4
5
6
# 更新生产环境依赖包
npm update express
# 更新开发环境依赖包
npm update express -D
# 全局更新
npm update express -g
  • 修改了package.json文件,并希望更新依赖包,可以执行以下命令:

1
2
# #为了避免不必要的麻烦,可以先删除项目中的node_modules文件夹在执行,此时和 npm install 一样
npm update

npm outdate:检查哪些包可以升级

  • npm outdate命令用于检查哪些包可以升级

1
2
3
4
5
6
7
# 检查当前项目下哪些包可以升级
npm outdate
# 检查指定包
npm outdated express
# 检查全局模块
npm outdate -g
npm outdated -g express

npm-upgrade:判断package.json哪些包需要升级

  • 安装

1
npm install -g npm-upgrade
  • 使用

1
2
3
4
# 判断package.json哪些包需要升级,用户确认后会自动更新package.json文件,此时只是更新文件,并没有真正升级
npm-upgrade
# 基于package.json中的配置进行升级,可以先删除node_modules再执行,此时和 npm install 一样
npm update

npm list:列出依赖包

  • npm list命令用于列出项目中的依赖包,比如要列出当前项目下的依赖包,可以执行以下命令:

1
2
3
4
5
6
7
8
9
# 此时列出的是package.json中的dependencies依赖包
npm list
# 列出开发依赖包,此时会列出package.json中的devDependencies和dependencies依赖包
npm list -D
# 列出指定包
npm list express
# 列出全局模块
npm list -g
npm list -g express

npm uninstall:卸载依赖包

  • npm uninstall命令用于卸载项目中的依赖包,比如要卸载express依赖包,可以执行以下命令:

1
2
3
npm uninstall express
# 删除全局模块
npm uninstall -g express

npm search:搜索依赖包

  • npm search命令用于搜索依赖包,比如要搜索express依赖包,可以执行以下命令:

1
npm search express
  • 可以使用正则表达式搜索依赖包,比如要搜索以express开头的依赖包,可以执行以下命令:

1
npm search /^express/

npm view == npm info:查看包信息

  • npm view命令用于查看包的信息,比如要查看express依赖包的信息,可以执行以下命令:

1
2
3
npm view express
# 或者,view与info命令可以互换使用
npm info express
  • npm view命令还可以查看包的所有版本信息,比如要查看express依赖包的所有版本信息,可以执行以下命令:

1
2
# 此时我们从结果中选择一个版本进行安装即可
npm view express versions

npm home:打开包的主页

  • 打开某个 npm 包的主页(通常是 GitHub 主页或 npm 页面)。

1
npm home express

npx:临时执行包里的命令

npx 用来运行某个 npm 包提供的可执行文件(package.json 的 bin)。包已经在当前项目的依赖里时,直接跑本地的;本地没有时,临时下载到 npm 缓存目录,把该目录加入这次进程的 PATH 再执行。不会把这个包写进当前项目的 package.json,也不等于全局安装到 -g 目录。

从 npm 7 起,npx 与 npm exec(别名 npm x)是同一套能力;日常习惯写 npx,脚本里两者都可以。

找哪个可执行文件

未指定 --package 时,npx 把第一个位置参数当成包名(可带 @版本),再按下面规则选出要跑的命令:

  • 包的 bin 只有一个条目,或所有条目都指向同一命令:用那一个。

  • bin 有多个条目,且其中有一条与包名去掉 scope 后的名字相同:用那一条。

  • 仍无法唯一确定时退出并报错。这时要用 --package 明确指定包,再写出真正要跑的命令名。

包名不带版本说明符时,会优先匹配当前项目依赖里已安装的同名包。带了 @1.2.3 这类说明符时,只有本地依赖的名字和版本完全一致才算命中;否则会去拉远端。

常用写法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 跑当前项目依赖里的本地二进制(等价于调用 node_modules/.bin 下的命令)
npx eslint .
npx tsc --noEmit

# 本地没有该依赖时,临时下载再执行;交互环境可能询问是否安装
# CI 或非 TTY 下默认当作同意安装(相当于 --yes)
npx cowsay "hello"

# 跳过询问,直接同意临时安装(脚本、CI 里常用)
npx --yes cowsay "hello"

# 拒绝临时安装:本地没有就失败
npx --no some-unknown-cli

# 钉死版本,避免每次拉到不同的 latest
npx --yes create-vite@5.2.3 my-app

包名和要执行的命令名不一致、或一个包提供多个 bin 时:

1
2
3
# --package 可写多次;其后的命令在这些包都已进入 PATH 的环境里执行
# npx 的自身选项必须写在位置参数之前
npx --yes --package=typescript --package=ts-node -- ts-node ./script.ts

用 -c / --call 可以把整条命令写成字符串,环境与 npm run 脚本类似(本地 node_modules/.bin 仍在 PATH 里):

1
npx --yes --package=cowsay -c 'cowsay hi && echo done'

和 npm install -g、npm run 的分工

做法 装到哪里 是否改 package.json 适合做什么
npx <pkg> 已有则用项目依赖;否则进 npm 缓存,仅本次 PATH 可用 否 临时脚手架、一次性检查工具、试用 CLI
npm install -g <pkg> 全局 prefix 下的全局 node_modules 否 本机长期使用的 CLI(要自己记得升级)
npm install -D <pkg> 再 npx / npm run 项目 node_modules 是 团队共享的构建、测试、lint 工具

项目里已经固定要用的工具,应写成 devDependencies,用 npm run 或 npx <本地命令> 调用,这样版本进 lock,CI 用 npm ci 后结果一致。只想试一下、或官方文档要求“一条命令生成项目”时,再用临时的 npx / npm create。

和 npm create 的关系

npm create <名字>(也写作 npm init <名字>)会转成执行对应的 create-* 包,底层同样走 npm exec / npx:

你写的命令 实际相当于
npm create vue@latest npx create-vue@latest
npm create vite@latest npx create-vite@latest
npm init @scope npx @scope/create
npm init @scope/foo@2.0.0 npx @scope/create-foo@2.0.0

前文「npm create:基于模板创建项目」里的写法,与这里直接 npx create-... 是同一类操作。

npx 与 npm exec 的参数位置

npx 要求:所有属于 npx 自己的选项,必须写在位置参数(包名 / 命令)之前。包名后面的参数会原样传给被执行的命令。

1
2
3
4
5
# --package 在包名后面:被当成传给 foo 的参数,不会让 npx 去装 @npmcli/foo
npx foo@latest bar --package=@npmcli/foo

# 等价意图用 npm exec 时,常用 -- 切开:左边是 npm 选项,右边交给要执行的命令
npm exec -- foo@latest bar --package=@npmcli/foo

拿不准某个包接受哪些参数时,查该包自己的文档;npx --help 只说明 npx / npm exec 本身。

临时包落在哪里

像 npx @deepseek-ai/dsh web 这类命令,不会把包装进项目的 node_modules,也不会装到 npm install -g 用的全局目录。本地项目依赖里没有该包时,它会下载到 npm 缓存目录下的 _npx 里,只给这次(以及之后复用缓存时的)执行用。

缓存根目录由配置项 cache 决定,可用 npm config get cache 查看。默认大致是:

系统 默认 cache _npx 下包的位置(示意)
macOS / Linux ~/.npm ~/.npm/_npx/<哈希>/node_modules/<包名>/
Windows %LocalAppData%\npm-cache %LocalAppData%\npm-cache\_npx\<哈希>\node_modules\<包名>\

<哈希> 由这次执行的包规格等算出,不同包、不同规格通常对应不同子目录。scoped 包路径里仍带 @scope,例如 @deepseek-ai/dsh 会落在 .../node_modules/@deepseek-ai/dsh/。

这和内容寻址的下载缓存 _cacache 不是同一层:npm cache clean --force 清的是包元数据/tarball 一类缓存;_npx 是 npm exec / npx 展开出的可执行环境。两者都可以占磁盘,清理方式也不同。

下次运行还要不要下载

缓存还在、且规格对得上时,一般不必重新下载,直接复用 _npx 里已有的目录,启动会快一些。

需要留意:

  • 没写版本号(例如只写 @deepseek-ai/dsh)时,npx 仍可能向 registry 查询是否有更新。已有新版本就会再下一份;没有更新则继续用缓存。

  • 写死了版本(例如 @deepseek-ai/dsh@1.2.3)时,同一规格更容易稳定命中已有缓存。

  • 删过 _npx、或整份 npm 缓存被清掉之后,下次必须重新联网下载。

想少触发“查最新版再决定是否下载”,在脚本和 CI 里给包钉版本。

清理 _npx 缓存

_npx 只是临时执行环境。删掉它不影响已用 npm install / -g 装好的软件,也不改任何项目的 package.json。代价是:以前靠 npx 跑过的包,下次要重新下载。

整目录删掉(各平台把路径换成你的 cache):

1
2
3
4
5
# 先确认 cache 根目录
npm config get cache

# macOS / Linux 默认
rm -rf ~/.npm/_npx/

较新的 npm 还提供只针对 npx 缓存的子命令(本文按 10.5.0;本机可用 npm help cache 核对是否支持):

1
2
3
4
5
6
7
8
9
# 列出 _npx 里有哪些条目
npm cache npx ls

# 查看某条详情(key 来自上一行的列表)
npm cache npx info <key>

# 不写 key:清空 npx 缓存;写 key:只删对应条目
npm cache npx rm
npm cache npx rm <key>

磁盘紧、或怀疑某次临时环境损坏时,清 _npx 即可。日常反复跑同一条 npx 时保留缓存,启动更快。

注意点

  • 临时执行会跑 registry 上的代码。不熟悉的包名、未钉版本的 @latest,有供应链风险;生产脚本应钉版本,或改为项目依赖。

  • npx 成功只说明命令启动并退出码为 0;项目依赖是否按 lock 装好,仍要靠 npm ci / npm install 和后续测试确认。“缓存目录里能看到包”也不等于已经装进当前项目。

  • 流水线里的简要用法见下文「npm 在 CI/CD 中的应用」。

npm 镜像源

  • npm 默认使用官方的镜像源,但是官方的镜像源速度很慢,我们可以使用第三方的镜像源来加速下载。

镜像源 当前状态 是否推荐
https://registry.npmjs.org/ 官方源 ✅ 推荐
https://registry.npmmirror.com/ 正常运营,原淘宝 NPM 镜像新域名 ✅ 强烈推荐
https://npm.aliyun.com 阿里云,已基本废弃,不再推荐作为 npm registry ❌ 不推荐
https://mirrors.cloud.tencent.com/npm/ 腾讯云,正常可用 ✅ 推荐
https://mirrors.huaweicloud.com/repository/npm/ 华为云,正常可用 ✅ 推荐
https://mirrors.163.com/npm/ 网易,已多年未维护,实际不可作为 npm registry 使用 ❌ 不推荐
http://mirrors.ustc.edu.cn/ 中科大镜像站仍存在,但不提供 npm registry 服务 ❌ 不推荐
https://mirrors.tuna.tsinghua.edu.cn/ 清华镜像站已停止提供 npm 镜像服务 ❌ 不推荐
  • 可以通过以下命令来查看当前使用的镜像源:

1
npm config get registry
  • 可以通过以下命令来设置镜像源:

1
npm config set registry https://registry.npmmirror.com
  • 可以通过以下命令来删除用户配置的镜像源,删除后恢复为默认镜像源:

1
npm config delete registry

npm 配置

  • 可以通过以下命令来查看npm的配置信息:

1
2
3
4
5
6
# 查看全局配置信息,只显示用户自定义的配置信息
npm config list
# 查看全局配置信息,显示所有配置信息及其默认缺省值
npm config ls -l
# json 格式 显示全部配置信息
npm config list --json
  • 默认全局配置在当前用户HOME目录下的.npmrc文件中,可以通过以下命令来查看全局配置信息:

1
2
cat ~/.npmrc
cat ~/.npmrc | grep registry
  • 在项目根目录创建一个.npmrc 文件可以为该项目单独设置 npm 配置。

  • npm config 允许你控制 npm 的行为,包括 安装目录、代理、日志级别、依赖管理 等。

  • 你可以使用 npm config get <key> 查看值,npm config set <key> <value> 进行修改,npm config delete <key> 删除设置。

  • npm常用配置

配置项 作用 默认值
prefix 设置 npm 全局安装的路径(npm install -g 影响的目录) 环境变量 NODE_HOME 或 /usr/local(系统)
cache npm 的缓存目录 ~/.npm
registry 指定 npm 的包管理仓库地址(如官方、淘宝镜像) https://registry.npmjs.org/
strict-ssl 是否强制使用 HTTPS 进行 npm 操作 true
proxy 配置 HTTP 代理 null
https-proxy 配置 HTTPS 代理 null
init-author-name 设置 package.json 默认作者名称 “”
init-author-email 设置 package.json 默认作者邮箱 “”
init-author-url 设置 package.json 默认作者网站 “”
init-license 设置 package.json 默认许可证 “ISC”
init-version package.json 默认版本号 “1.0.0”
save-exact true 时,安装依赖时不使用 ^ 或 ~,直接锁定版本 false
engine-strict 是否强制匹配 package.json 的 engines 字段 false
loglevel 设置日志输出级别(silent, error, warn, notice, info, verbose, silly) notice
fund 是否显示 package 的资金支持信息 true
audit 是否启用安全审计 true

npm config save-exact

  • 推荐配置为 true,避免因为版本更新导致依赖包版本不匹配

1
npm config set save-exact true

npm config loglevel

  • loglevel 可选值

级别 说明 适用场景
silent 不输出任何日志(除非发生错误) 适用于 CI/CD 需要最少日志的环境
error 仅显示错误信息 只关心 npm 运行是否出错
warn 显示警告和错误 发现潜在问题但不影响使用
notice (默认) 显示关键信息、警告和错误 npm 默认值,适合大多数场景
http 记录 HTTP 请求的详细信息 用于调试 npm 下载速度问题
info 显示一般信息、依赖安装情况等 适用于一般开发者调试
verbose 详细的调试信息 适用于深入分析 npm 运行情况
silly 最详细的日志,包含所有调试信息 适用于 npm 开发者或极端调试需求
  • 设置方法

1
npm config set loglevel verbose
  • 临时使用

1
2
3
4
5
6
7
8
9
10
npm --loglevel verbose install
# 或者
npm -dd install

# 支持快捷方式的值:
# • -s, --silent: --loglevel silent
# • -q, --quiet: --loglevel warn
# • -d: --loglevel info
# • -dd, --verbose: --loglevel verbose
# • -ddd: --loglevel silly

npm config timing

  • timing 是 npm 的一个 日志输出配置项,用于控制是否在命令执行时显示详细的时间信息,默认值为 false。

  • 当 timing 设为 true 时,npm 会在命令执行结束后 打印详细的时间统计信息,包括:

    • 每个子任务的执行时间(如解析 package.json、解析 node_modules、下载依赖等)
    • 网络请求的耗时
    • 依赖解析和安装的耗时
    • 整体执行的时间开销
  • 这对分析 npm 性能、优化依赖安装速度非常有用,特别是在大项目或 CI/CD 环境中。

  • 启用 timing

1
npm config set timing true
  • 临时启用

1
npm --timing install
  • 适用场景

    • 分析 npm 命令执行时间,优化构建速度
    • CI/CD 环境中排查 npm 安装变慢的原因
    • 排查 npm 依赖解析、安装或下载过程的性能瓶颈
  • 一般日常开发:日志会变长,可能影响可读性,所以再没有遇到问题时不建议开启

npm、pnpm、yarn 之间的联系和区别

  • 这三者都是 JavaScript 生态中的包管理工具,主要用于安装、管理和运行 Node.js 项目的依赖。它们的关系如下:

    • npm(Node Package Manager)是 Node.js 官方自带的包管理工具。
    • yarn(Yet Another Resource Negotiator)是 Facebook 开发的替代 npm 的工具,提供更快、更安全的依赖管理。
    • pnpm(Performant npm)是一个更高效的 npm 替代品,使用硬链接和去重机制来减少磁盘占用并加快安装速度。
  • npm、pnpm、yarn 的主要区别

特性 npm yarn pnpm
默认包管理方式 直接安装到 node_modules/ 直接安装到 node_modules/ 使用 硬链接 + 共享依赖,占用更少磁盘
安装速度 5+ 版本后速度较快,但依赖解析仍有性能问题 速度较快,支持并行下载 最快,去重能力强
磁盘占用 较大(每个项目都会存一份完整的依赖) 较大(和 npm 类似) 最小(共享全局缓存,多个项目共用依赖)
锁文件 package-lock.json yarn.lock pnpm-lock.yaml
并发安装 支持(npm 5+ 优化) 支持(更快) 支持(最优化)
全局缓存 支持(但项目仍会存副本) 支持(仍会拷贝到 node_modules/) 强制启用(多个项目共用依赖,节省空间)
monorepo(多包管理) 需要手动配置 支持 Workspaces 原生支持 Workspaces(最强大)
命令兼容性 标准 兼容 npm,部分不同 兼容 npm,大部分命令相同
自动修复 package.json 是 是 是
生态兼容性 官方标准,兼容性最好 兼容 npm,但部分特性不同 兼容 npm,但采用不同的依赖管理方式
  • 常见命令对比

任务 npm yarn pnpm
初始化项目 npm init yarn init pnpm init
安装依赖 npm install yarn install pnpm install
安装特定依赖 npm install lodash yarn add lodash pnpm add lodash
安装开发依赖 npm install lodash -D yarn add lodash -D pnpm add lodash -D
删除依赖 npm uninstall lodash yarn remove lodash pnpm remove lodash
更新依赖 npm update lodash yarn upgrade lodash pnpm update lodash
全局安装 npm install -g serve yarn global add serve pnpm add -g serve
运行脚本 npm run dev yarn dev pnpm dev
  • 什么时候使用 npm、yarn、pnpm?

    • ✅ 使用 pnpm(推荐):
      1.你希望减少磁盘占用、加快安装速度
      2.你正在开发 monorepo(多包)项目
      3.你希望更高效地管理依赖

    • ✅ 使用 yarn:
      1.你希望更快的安装速度,但又不想改变 npm 传统结构
      2.你的团队习惯使用 yarn.lock 文件
      3.你在用 React Native(官方推荐 yarn)

    • ✅ 使用 npm(适合简单项目):
      1.你希望使用 Node.js 官方的默认工具
      2.你不想安装额外的包管理工具
      3.你在开发小型项目,不需要 workspaces

npm 在 CI/CD 中的应用

流水线里依赖安装要可重复:同一提交每次装出的版本必须一致,package-lock.json 不能被安装过程改写。这一节写 CI 里常用的 npm 命令,以及它们和日常开发命令的分工。

npm ci:按 lock 文件干净安装

npm ci(别名 clean-install、ic、install-clean)专门给自动化环境和需要可重复构建的场景用。它只按 package-lock.json(或 npm-shrinkwrap.json)安装,不解析 package.json 里的版本范围去“找最新兼容版”。

对比项 npm ci npm install
依赖来源 只读 lock 文件 以 package.json 为准,必要时改写 lock
lock 与 package.json 不一致 直接报错退出 会更新 lock 去对齐
已有 node_modules 先整目录删除,再全新安装 增量安装,尽量复用已有模块
能否单独加包 不能,一次只装整个项目 可以 npm install <pkg>
是否写回 lock / package.json 从不写 可能写
典型场景 CI/CD、发布构建、要求依赖完全一致 本地开发、增删改依赖

具体行为:

  • 项目里必须有 package-lock.json 或 npm-shrinkwrap.json。没有 lock 时 npm ci 直接失败,不会退化成 npm install。

  • 会校验 package.json 与 lock 是否同步。lock 缺少声明的依赖,或版本对不上,立刻退出。

  • 执行前删除现有 node_modules,再按 lock 全量安装,结果干净、可重复。

  • 若当初生成 lock 时用过会影响依赖树形状的选项(例如 --legacy-peer-deps),npm ci 必须带同样选项,否则容易报错。可把该选项写进项目根目录的 .npmrc 并提交进仓库。

为什么 CI 优先用它:

  • 每次构建装到的版本与 lock 一致,减少“本地能过、流水线挂掉”。

  • 跳过版本范围解析,通常比 npm install 更快。

  • package.json 里的 ^ / ~ 不会在 CI 里悄悄拉到新版本。

  • lock 未提交或与 package.json 不同步时立刻失败,逼着把正确的 lock 提交上去。

使用前提:

  • 必须把 package-lock.json(或 npm-shrinkwrap.json)提交进版本库。两者同时存在时,npm-shrinkwrap.json 优先。

  • CI 可缓存 ~/.npm(对应配置项 cache),加速下载;缓存的是下载缓存,不是项目里的 node_modules。

  • 本地日常加包、升版本仍用 npm install / npm update;装完后把更新过的 lock 一并提交,再让 CI 跑 npm ci。

1
2
3
4
5
6
7
# 本地先保证 lock 与 package.json 同步,并提交 lock
npm install
git add package.json package-lock.json
git commit -m "chore: sync lockfile"

# CI 里只做干净安装,不改 lock
npm ci

GitHub Actions 里常见写法(缓存 npm 下载目录):

1
2
3
4
5
6
7
# 片段:安装步骤用 npm ci,并缓存 ~/.npm
- uses: actions/setup-node@v4
with:
node-version: "20"
cache: npm
- run: npm ci
- run: npm test

流水线里不要用 npm install 代替 npm ci 去做正式构建或发布前的安装。npm install 可能改写 lock,同一提交在不同时间装出的树可能不同。只有尚未提交 lock、或流水线本身就要改依赖版本时,才考虑在 CI 里用 npm install。

npm install-ci-test:干净安装后立刻测

npm install-ci-test(别名 npm cit、clean-install-test)等于先 npm ci,再立刻 npm test。既要严格按 lock 安装、又要跑测试时,一条命令即可。

1
2
3
npm cit
# 等价于
npm ci && npm test

package.json 里需要有可执行的 test 脚本,否则第二步会失败。

流水线里其他常用命令

这些命令并非只给 CI 设计,但在自动化里最常成套出现。

安全审计:npm audit

把当前依赖树提交给 registry,查已知漏洞。默认发现任意级别漏洞都以非 0 退出;CI 里常用 --audit-level 设定失败门槛,报告仍会列出更低级别的项,只是低于门槛时不让流水线失败。

1
2
3
4
5
# 高危及以上才让 CI 失败
npm audit --audit-level=high

# 校验已下载包的 registry 签名与 provenance(支持签名的 registry)
npm audit signatures

跑项目脚本:npm run <script>

执行 package.json 的 scripts,例如 npm run build、npm run lint、npm test。pre* / post* 生命周期钩子在 CI 里同样会触发。

1
2
3
4
npm ci
npm run lint
npm test
npm run build

临时跑工具:npx

只需跑一次某 CLI、又不想写进依赖时用。完整说明见上文「npx:临时执行包里的命令」。

1
2
# 示例:临时跑一次某检查工具(包名按实际替换);CI 里建议加 --yes 并钉版本
npx --yes some-linter@1.2.3 .

发布前预览打包:npm pack

确认即将打进 tarball 的文件列表,避免把本地配置或密钥带进去。以 --dry-run 的预览为准,对照 package.json 的 files 字段。

1
npm pack --dry-run

发布:npm publish

CI 自动发布的最后一步。长期 NPM_TOKEN 可以工作,但更推荐用 GitHub Actions 的 Trusted Publishing(OIDC),不必在仓库里存长期令牌。配置与工作流见 使用 GitHub Actions 和 OIDC 安全发布 npm 包;本地升版本、打标签、推送后交给 Actions 发布,可用 npm -- 用 npm-publish-oidc 发布包。

环境自检:npm doctor

在流水线或本机排查“npm 本身是否正常”时用:检查 Node/npm、registry 连通、权限、缓存等。能打印健康报告,不等于当前项目的 npm ci 或 npm test 已经成功。

1
npm doctor

一条最小 CI 顺序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 1. 严格按 lock 安装
npm ci

# 2. 可选:漏洞门禁
npm audit --audit-level=high

# 3. 检查、测试、构建(脚本名以项目为准)
npm run lint
npm test
npm run build

# 4. 发布前看一眼打包内容
npm pack --dry-run

# 5. 需要发版时再 publish(权限与 OIDC 见同系列文章)
# npm publish --access public

安装失败时先看:项目根是否有已提交的 package-lock.json、npm ci 的报错是否在说 lock 与 package.json 不一致。审计失败先看 npm audit 的报告级别是否被 --audit-level 拦住。脚本失败先在同一环境手动跑对应的 npm run ...,确认是依赖问题还是测试本身失败。

发包到npm仓库

1. 注册与登录

  1. 浏览器打开 npm 官方网站

  2. 没有帐号要先进行注册,比如用户名为 hanqunfeng 对应包名 scope 中的 @hanqunfeng,邮箱也必须真实可用。

2. 创建 Access Token

  1. 登录后,进入Access Tokens

  2. Generate New Token → 创建新的 Access Token → 填写名称(如 claude-trace-publish)

  3. 勾选 Bypass two-factor authentication (2FA)(发布时必须勾选)

  4. Packages and scopes:

    • Permissions → Read and write
    • Select packages → Only select packages and scopes → @hanqunfeng
  5. 设置 Expiration Date,到期后需重新创建 Token

  6. 复制生成的 Token(只显示一次,请妥善保存)

3. 配置本地 Token

  • 将 Token 写入用户级 ~/.npmrc(不要提交到 git):

1
2
3
4
5
# 这里的accessToken,就是上面创建的 Access Token
npm config set //registry.npmjs.org/:_authToken=你的accessToken

# 成功后查看当前用户
npm whoami # 应输出 hanqunfeng

安全提示: 不要将 Token 写入项目目录或提交到 GitHub。若泄露,立即在 npm 网站撤销并重新创建。

4.编辑 package.json,指定包名,版本,以及要发布的文件,等等

字段 作用 是否必须 npm 页面展示
name npm 包名 ✅ 必须 ✅ 显示包名
version 发布版本号 ✅ 必须 ✅ 显示当前版本
main 默认入口文件 ⚠️ 非必须(库项目建议配置) ❌ 不展示
types TypeScript 类型入口 ⚠️ 非必须(TS 项目建议配置) ❌ 不展示
bin 发布 CLI 命令 ⚠️ CLI 项目必须,普通库不需要 ❌ 不展示
files 控制哪些文件被打包上传 ⚠️ 非必须(建议配置) ❌ 不展示
license 开源协议 ⚠️ 非必须(强烈建议配置) ✅ 显示 License
description 包简介 ⚠️ 非必须 ✅ 显示简介
keywords 搜索关键词 ⚠️ 非必须 ✅ 显示 Keywords
author 作者信息 ⚠️ 非必须 ✅ 显示 Author
repository 源码仓库地址 ⚠️ 非必须 ✅ 显示 Repository 链接
homepage 项目主页 ⚠️ 非必须 ✅ 显示 Homepage 链接
bugs Issue / Bug 反馈地址 ⚠️ 非必须 ✅ 显示 Bugs 链接

一个npm发布最小配置示例,完整配置参看 https://github.com/hanqunfeng/claude-trace

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
"name": "@hanqunfeng/claude-trace",
"version": "3.0.6",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"bin": {
"claude-trace": "dist/cli/cli.js",
"opencode-trace": "dist/cli/opencode-cli.js",
"codex-trace": "dist/cli/codex-cli.js"
},
"files": [
"dist/**/*"
],
"license": "MIT"
}

5.检查包名是否可用

1
2
3
# npm view 包名,返回  404 Not Found,说明报名未被占用,也可以直接到 npm 官网搜索包名
# 包名重复需要更换新的包名
npm view @hanqunfeng/claude-trace

6.发布前打包及校验

1
2
3
4
5
6
7
8
# 安装依赖
npm run build

# 类型检查
npm run typecheck

# 预览将要发布的文件,package.json 中的 files 配置项
npm pack --dry-run

7.更新版本号

  • 每次发布都需要一个新的版本号,可以手工修改,也可以通过如下命令进行修改

  • 遵循 语义化版本

变更类型 命令 示例
补丁(bug 修复) npm version patch 2.0.2 → 2.0.3
次版本(新功能,向后兼容) npm version minor 2.0.2 → 2.1.0
主版本(破坏性变更) npm version major 2.0.2 → 3.0.0
  • 它实际上做了三件事:

(1) 修改 package.json 版本

1
"version": "1.0.0" → "1.0.1"

(2) 自动创建 git commit

1
git commit -am "1.0.1"

(3) 自动打 tag

1
git tag v1.0.1

8. 发布

1
2
3
4
# 第一次发布
npm publish --access public
# 之后再次发布时无需带上 --access public
npm publish
  • --access public:作用域包默认为私有,免费账号必须显式公开

  • 使用已配置 Bypass 2FA 的 Access Token

该命令会自动先运行 npm run build。

9. 验证发布

1
2
3
4
5
# 查看 npm 上的版本
npm view @hanqunfeng/claude-trace version

# 全局安装测试
npm install -g @hanqunfeng/claude-trace

10. 推荐一个日常发布流程

1
2
3
4
5
6
7
8
git add .
git commit -m "feat: xxx"

npm version patch -m "chore(release): %s"

git push && git push --tags

npm publish