第一章:npm 基础入门
1.1 npm 简介与安装
| 概念名称 | 说明 | 注意事项 |
|---|---|---|
| npm(Node Package Manager) | Node.js 自带的包管理工具,用于安装、共享和分发 JavaScript 代码包 | 需先安装 Node.js,npm 会随 Node.js 一并安装 |
| 安装方式 | 通过安装 Node.js 自动获得 npm;也可单独升级 npm | 推荐从 https://nodejs.org 下载 LTS 版本 |
| 验证安装 | 在终端运行 node -v 和 npm -v 查看版本 | 若提示”command not found”,需检查环境变量 PATH 是否包含 Node 安装路径 |
| 升级 npm | 运行 npm install -g npm@latest | Windows 用户可能需要以管理员身份运行终端 |
1.2 npm 基本命令概览
| 方法名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
| npm -v | npm -v | 查看当前 npm 版本 | npm -v → 输出如 9.6.7 | 无需项目上下文,全局可用 |
| npm init | npm init | 初始化新项目,生成 package.json | npm init -y(跳过交互,使用默认值) | -y 参数适用于快速初始化 |
| npm install | npm install <package>npm i <package> | 安装指定包到 node_modules 并记录依赖 | npm install lodash | 默认添加到 dependencies;若加 -D 或 --save-dev 则为 devDependencies |
| npm list | npm listnpm list --depth=0 | 列出已安装的包及其版本 | npm list --depth=0(仅顶层依赖) | 深度过大会输出冗长树状结构 |
| npm help | npm help <command> | 查看某命令的帮助文档 | npm help install | 可替代查阅在线文档 |
| npm config | npm config listnpm config get registry | 查看或设置 npm 配置 | npm config set registry https://registry.npmmirror.com | 常用于切换镜像源(如淘宝镜像) |
1.3 package.json 文件详解
| 字段名称 | 说明 | 示例值 | 注意事项 |
|---|---|---|---|
| name | 包/项目的名称 | "my-app" | 必须小写,不能含空格或特殊字符(除 - _) |
| version | 项目版本号,遵循语义化版本(SemVer) | "1.0.0" | 格式必须为 x.y.z,否则部分工具报错 |
| description | 项目描述 | "A simple todo app" | 可选,但建议填写以便他人理解 |
| main | 入口文件路径 | "index.js" | 若未指定,默认为 index.js |
| scripts | 自定义脚本命令集合 | { "start": "node server.js" } | 可通过 npm run <script-name> 执行 |
| dependencies | 生产环境依赖列表 | { "express": "^4.18.0" } | 安装时不加 -D 会自动写入此字段 |
| devDependencies | 开发环境依赖(如测试、构建工具) | { "jest": "^29.0.0" } | 不会被生产环境安装(除非显式指定) |
| keywords | 关键词数组,用于 npm 搜索 | ["cli", "tool"] | 可选,提升包在 registry 中的可发现性 |
| author | 作者信息 | "Alice <alice@example.com>" | 可为字符串或对象格式 |
| license | 开源许可证类型 | "MIT" | 建议明确指定,避免法律风险 |
| repository | 项目代码仓库地址 | { "type": "git", "url": "https://github.com/user/repo" } | 支持 git、svn 等类型 |
| engines | 指定 Node.js/NPM 版本要求 | { "node": ">=18.0.0", "npm": ">=9.0.0" } | 仅作提示,不会强制阻止安装 |
注:
package.json是纯 JSON 格式,不支持注释,且所有字段必须用双引号包裹。
第二章:包的安装与管理
2.1 安装本地依赖(dependencies)
| 方法名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
| npm install | npm install <package>npm i <package> | 安装包并添加到 dependencies | npm install express | 默认行为;适用于运行时必需的依赖 |
| npm install with version | npm install <package>@<version> | 安装指定版本的包 | npm install lodash@4.17.21 | 版本可为具体号、范围(如 ^4.0.0)或标签(如 latest) |
| npm install from git | npm install <git-url> | 从 Git 仓库安装包 | npm install git+https://github.com/user/repo.git | 需仓库根目录含 package.json |
| npm install from local path | npm install ../my-local-pkg | 从本地路径安装包 | npm install ./utils | 会创建符号链接(symlink),便于本地开发调试 |
| npm install —save | npm install --save <package> | 显式将包写入 dependencies(旧版习惯) | npm install --save axios | npm v5+ 默认自动保存,此参数可省略 |
注意:dependencies 中的包会被递归安装到生产环境,应仅包含运行时必需模块。
2.2 安装开发依赖(devDependencies)
| 方法名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
| npm install —save-dev | npm install --save-dev <package>npm i -D <package> | 安装包并添加到 devDependencies | npm install -D jest | 适用于测试、构建、格式化等开发阶段工具 |
| npm install with scope | npm install -D @types/node | 安装带作用域的开发依赖 | npm install -D typescript | 常用于 TypeScript 类型定义、ESLint 插件等 |
| npm install multiple | npm install -D <pkg1> <pkg2> | 一次性安装多个开发依赖 | npm install -D eslint prettier | 所有包均写入 devDependencies |
| npm install from tarball | npm install -D file:./my-tool.tgz | 从本地压缩包安装开发工具 | npm install -D file:./build/tool.tgz | 适用于 CI 中分发内部工具 |
注意:devDependencies 在生产环境执行 npm install --production 时不会被安装。
2.3 全局安装与卸载
| 方法名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
| npm install -g | npm install -g <package> | 全局安装命令行工具 | npm install -g http-server | 安装后可在任意目录使用该命令 |
| npm list -g | npm list -g --depth=0 | 列出全局安装的包 | npm list -g --depth=0 | 查看已安装的 CLI 工具 |
| npm uninstall -g | npm uninstall -g <package>npm remove -g <package> | 卸载全局包 | npm uninstall -g nodemon | 卸载后命令将不可用 |
| npm root -g | npm root -g | 查看全局 node_modules 路径 | npm root -g → /usr/local/lib/node_modules | 可用于排查权限或路径问题 |
注意:全局安装需谨慎,不同项目可能依赖不同版本;推荐优先使用 npx 或本地安装。
2.4 查看与更新已安装包
| 方法名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
| npm outdated | npm outdated | 检查可更新的依赖 | npm outdated | 显示当前版本、期望版本、最新版本 |
| npm update | npm updatenpm update <package> | 更新依赖至 package.json 允许的最高版本 | npm update lodash | 遵循版本前缀规则(如 ^、~) |
| npm update —save | npm update --save | 更新并写入新版本到 package.json | npm update --save | npm v8+ 默认自动保存,旧版需显式加 --save |
| npm view | npm view <package> versionnpm view <package> versions --json | 查看包的版本信息 | npm view react versions --json | 可用于确认是否存在安全版本 |
| npm ls | npm ls <package> | 查看某包是否安装及版本 | npm ls webpack | 若未安装则返回 empty |
注意:npm update 不会突破 package.json 中的版本范围限制;如需升级大版本,需手动修改或使用 npm install <package>@latest。
2.5 删除依赖
| 方法名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
| npm uninstall | npm uninstall <package>npm remove <package>npm rm <package> | 从项目中移除依赖并更新 package.json | npm uninstall moment | 自动从 dependencies 或 devDependencies 中删除 |
| npm uninstall -D | npm uninstall -D <package> | 从 devDependencies 移除包 | npm uninstall -D husky | 若包同时存在于两个字段,需分别处理 |
| npm uninstall —no-save | npm uninstall --no-save <package> | 仅删除 node_modules 中的包,不修改 package.json | npm uninstall --no-save debug | 极少使用,通常不推荐 |
| npm prune | npm prune | 删除 node_modules 中未在 package.json 声明的包 | npm prune | 用于清理残留依赖,尤其在手动编辑 package.json 后 |
注意:删除依赖后建议运行 npm ls 确认无残留,避免”幽灵依赖”问题。
第三章:项目初始化与配置
3.1 初始化项目(npm init)
| 方法名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
| npm init | npm init | 交互式创建 package.json | 执行后依次输入 name、version 等字段 | 每个字段均有默认值,可直接回车跳过 |
| npm init -y | npm init -ynpm init --yes | 跳过交互,使用默认值生成 package.json | npm init -y | 默认 name 为当前目录名,version 为 1.0.0 |
| npm init | npm init <package> | 使用第三方脚手架初始化(如 create-react-app) | npm init react-app my-app | 实际调用 npx create-react-app my-app |
| npm init —scope | npm init --scope=@myorg | 初始化作用域包(scoped package) | npm init --scope=@myorg → name: @myorg/my-project | 需在 .npmrc 中配置或已登录 npm 账号 |
注意:package.json 必须包含 name 和 version 字段才能被发布;初始化后可手动编辑补充其他字段。
3.2 自定义 npm init 模板
| 操作步骤名称 | 操作细节 | 注意事项 |
|---|---|---|
| 设置 init-author-name | npm config set init-author-name "Your Name" | 用于自动填充 author 字段 |
| 设置 init-author-email | npm config set init-author-email "you@example.com" | 建议设置,便于协作和发布 |
| 设置 init-author-url | npm config set init-author-url "https://your-site.com" | 可选,但有助于建立开发者身份 |
| 设置 init-license | npm config set init-license "MIT" | 默认为 ISC,可改为 MIT、Apache-2.0 等 |
| 设置 init-version | npm config set init-version "0.1.0" | 控制默认版本号,适合内部项目规范 |
| 创建自定义 init 脚本 | 在全局配置目录下创建 ~/.npm-init.js(或 .npm-init.json) | 脚本需导出一个对象,如 module.exports = { name: 'custom', version: '1.0.0' } |
| 使用自定义模板 | 运行 npm init 时自动加载 ~/.npm-init.js | 若存在该文件,优先级高于 config 设置 |
示例 ~/.npm-init.js 内容:
module.exports = {
name: prompt('name', basename || process.cwd().split('/').pop()),
version: '0.0.1',
description: prompt('description', ''),
main: 'index.js',
author: 'Your Name <you@example.com>',
license: 'MIT',
private: true
};
注意:prompt() 是 npm init 内置函数,仅在 .npm-init.js 中可用;若需复杂逻辑,建议使用 Yeoman 或 plop 等专用脚手架工具。
3.3 npm 配置文件(.npmrc)
| 配置项名称 | 说明 | 示例值 | 注意事项 |
|---|---|---|---|
| registry | 指定 npm 包仓库地址 | registry=https://registry.npmmirror.com | 常用于切换淘宝镜像加速安装 |
| @myorg:registry | 为作用域包指定私有 registry | @myorg:registry=https://npm.pkg.github.com | 支持多 registry 并存 |
| always-auth | 是否始终发送认证信息 | always-auth=true | 与私有仓库配合使用 |
| 用户邮箱(旧版兼容) | email=you@example.com | 新版推荐通过 npm login 管理凭证 | |
| save-exact | 安装时是否锁定精确版本 | save-exact=true | 默认 false(使用 ^),设为 true 则写入如 "lodash": "4.17.21" |
| package-lock | 是否生成 package-lock.json | package-lock=false | 不推荐关闭,会破坏依赖一致性 |
| scripts-prepend-node-path | 是否将 node 加入脚本 PATH | scripts-prepend-node-path=true | 解决某些系统下 node 命令找不到的问题 |
| cache | 自定义缓存目录 | cache=~/.npm-cache | 可用于 CI 环境缓存复用 |
配置优先级(从高到低):
- 命令行参数(如
--registry) - 项目级
.npmrc(位于项目根目录) - 用户级
.npmrc(位于~/.npmrc) - 全局配置(
npm config list -g) - npm 内置默认值
注意:.npmrc 文件支持注释(以 # 开头),但不能包含 JSON 格式;敏感信息(如 token)应避免明文存储,可使用环境变量(如 //registry.npmjs.org/:_authToken=${NPM_TOKEN})。
第四章:脚本与生命周期
4.1 自定义 npm scripts
| 脚本字段名 | 语法(在 package.json 中) | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
| scripts | "scripts": { "<name>": "<command>" } | 定义可运行的自定义命令 | "scripts": { "start": "node server.js" } | 脚本名不能含空格或特殊字符(除 - _) |
| 执行脚本 | npm run <script-name> | 运行自定义脚本 | npm run build | 内置脚本(如 start、test)可省略 run,直接 npm start |
| 使用环境变量 | 在脚本中引用 $npm_package_name 等 | 获取 package.json 中的字段值 | "echo-name": "echo $npm_package_name"(Linux/macOS)"echo-name": "echo %npm_package_name%"(Windows) | 跨平台需注意变量语法差异;推荐使用 cross-env 统一 |
| 调用其他脚本 | "build:js": "rollup -c", "build": "npm run build:js" | 组合多个子任务 | "prepublishOnly": "npm run test && npm run build" | 可通过 npm run 嵌套调用 |
| 忽略错误继续 | \”lint”: “eslint . | echo ‘Lint failed but continuing’“` | 允许脚本失败但不中断流程 |
注意:所有脚本均在项目根目录执行;node_modules/.bin 中的可执行文件会自动加入 PATH,无需写完整路径(如直接写 jest 而非 ./node_modules/.bin/jest)。
4.2 预定义生命周期脚本(pre/post hooks)
| 生命周期钩子 | 触发时机 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
| preinstall | 安装包前(作为依赖被安装时) | 准备构建环境 | "preinstall": "node ./scripts/check-node-version.js" | 仅当本包被他人 npm install 时触发 |
| install | 安装完成后(作为依赖) | 编译原生模块等 | "install": "node-gyp rebuild" | 常用于 C++ 插件项目 |
| postinstall | install 后立即执行 | 显示欢迎信息、打补丁 | "postinstall": "echo 'Thanks for installing!'" | 用户安装后可见,但避免耗时操作 |
| prepublishOnly | npm publish 前执行 | 构建生产产物 | "prepublishOnly": "npm run build" | 仅在 publish 时运行,比旧版 prepublish 更安全 |
| prepack / postpack | 打包前/后(publish 或 pack 时) | 生成额外文件 | "prepack": "npm run docs" | 适用于 npm pack 和 npm publish |
| pretest / posttest | npm test 前/后 | 设置/清理测试环境 | "pretest": "npm run lint" | 自动关联 test 脚本 |
| prestart / poststart | npm start 前/后 | 启动前检查配置 | "prestart": "node ./scripts/validate-config.js" | 仅当显式运行 npm start 时触发 |
| stop / restart | npm stop / npm restart 时 | 控制服务启停 | "stop": "killall my-server" | 较少使用,需自行实现逻辑 |
注意:
pre<name>和post<name>会自动在运行<name>脚本前后执行(如prebuild → build → postbuild)。- 若 pre 脚本失败(退出码非 0),主脚本不会执行。
- 避免在
postinstall中执行重型任务,会影响用户安装体验。
4.3 并行与串行执行脚本
| 执行方式 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
| 串行执行 | npm run a && npm run b | 按顺序执行,前一个成功才执行下一个 | "build": "npm run clean && npm run compile" | 标准 shell 行为;任一失败则中断 |
| 并行执行(原生) | npm run a & npm run b | 同时启动多个进程(Unix/Linux/macOS) | "dev": "npm run watch-js & npm run watch-css" | Windows 不支持 &,需跨平台方案 |
| 使用 npm-run-all(推荐) | npm install -D npm-run-all | 跨平台并行/串行执行 | "watch:js": "webpack --watch", "watch:css": "sass --watch", "dev": "run-p watch:*" | run-p = 并行,run-s = 串行 |
| 使用 concurrently | npm install -D concurrently | 另一种流行并行工具 | "dev": "concurrently \"npm run serve\" \"npm run client\"" | 支持日志着色、命名等高级功能 |
| 通配符匹配 | run-p build:* | 批量执行匹配脚本 | "build:js": "...", "build:css": "...", "build": "run-p build:*" | 需配合 npm-run-all 使用 |
注意:
- 原生
&&和&在不同操作系统行为不一致,生产项目推荐使用npm-run-all或concurrently。 - 并行脚本的日志会交错输出,建议使用
--names(concurrently)或--print-label(npm-run-all)标识来源。 - 避免在并行任务中写入同一文件,可能导致竞争条件。
第五章:npm 仓库与发布
5.1 发布包到 npm registry
| 操作步骤名称 | 操作细节 | 注意事项 |
|---|---|---|
| 注册 npm 账号 | 访问 https://www.npmjs.com/signup 完成注册 | 邮箱需验证;建议使用公司或个人长期有效邮箱 |
| 登录 CLI | npm login 或 npm adduser | 输入用户名、密码、邮箱;凭证保存在 ~/.npmrc |
| 初始化 package.json | 确保含 name、version、main(可选)等字段 | 名称不能与现有包冲突(除非是你的作用域包) |
| 设置包为公开(默认) | 无需额外配置 | 公开包对所有人可见和可安装 |
| 设置包为私有 | 在 package.json 中添加 "private": true | 仅用于防止误发布,不影响本地开发 |
| 发布包 | npm publish | 首次发布会创建包;后续需先更新版本 |
| 发布带标签版本 | npm publish --tag <tag> | 如 npm publish --tag beta,默认标签为 latest |
| 查看已发布版本 | npm view <package> versions --json | 验证是否发布成功 |
注意:
- 包名全局唯一,一旦被占用无法抢注(除非联系原作者转让)。
- 发布前确保
.npmignore或files字段正确控制上传内容(避免泄露敏感文件)。 - 若使用双因素认证(2FA),需通过
npm profile enable-2fa启用,并在发布时提供 OTP。
5.2 版本管理与语义化版本(SemVer)
| 概念名称 | 说明 | 示例 | 注意事项 |
|---|---|---|---|
| 语义化版本格式 | MAJOR.MINOR.PATCH | 2.4.1 | 所有版本必须符合此格式,否则发布失败 |
| MAJOR 版本 | 不兼容的 API 变更 | 从 1.x.x → 2.0.0 | 表示破坏性更新 |
| MINOR 版本 | 向后兼容的功能新增 | 2.4.0 → 2.5.0 | 新增功能但不破坏现有用法 |
| PATCH 版本 | 向后兼容的问题修正 | 2.4.1 → 2.4.2 | 仅修复 bug,无新功能 |
| 版本前缀符号 | ^(兼容)、~(补丁)、=(精确) | "lodash": "^4.17.0" | ^4.17.0 允许 4.x.x,但不升级到 5.0.0 |
| npm version 命令 | 自动更新 version 并打 Git 标签 | npm version patchnpm version minornpm version major | 需 Git 仓库 clean;可加 -m "v%s" 自定义提交信息 |
| 预发布版本 | 使用 - 分隔符 | 1.0.0-alpha.1 | 不会被 latest 标签自动安装 |
| 查看版本规则 | https://semver.org | 官方规范 | 建议团队统一遵循 |
注意:
npm publish要求每次版本号必须严格递增,不可重复发布相同版本。- 使用
npm version可自动更新 package.json 和 package-lock.json,并创建 Git commit + tag。
5.3 私有包与作用域包(scoped packages)
| 概念/操作名称 | 说明 | 示例 | 注意事项 |
|---|---|---|---|
| 作用域包命名 | @<scope>/<package-name> | @myorg/utils | scope 通常为组织名或用户名 |
| 初始化作用域包 | npm init --scope=@myorg | 生成 "name": "@myorg/my-pkg" | 需已登录 npm 账号 |
| 默认发布为私有 | 作用域包默认私有(需付费) | npm publish → 提示需订阅 | 开源项目可显式设为公开 |
| 发布为公开作用域包 | npm publish --access public | npm publish --access public | 首次发布必须指定,否则失败 |
| 安装作用域包 | npm install @myorg/utils | 正常安装 | 无特殊语法 |
| 配置私有 registry | 在 .npmrc 中设置 @myorg:registry=... | @myorg:registry=https://npm.pkg.github.com | 用于企业内网或 GitHub Packages |
| 查看作用域包权限 | npm access ls-packages | 列出你有权管理的包 | 需登录 |
注意:
- 免费 npm 账号不能发布私有包(包括私有作用域包),但可发布公开作用域包。
- 若使用 GitHub Packages,需在
.npmrc中配置_authToken和 registry。
5.4 撤回或废弃包
| 方法名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
| npm deprecate | npm deprecate <pkg>[@<version>] "<message>" | 废弃指定版本或全部版本 | npm deprecate my-pkg@1.0.0 "Critical security issue"npm deprecate my-pkg "*" "Use @neworg/core instead" | 用户安装时会看到警告信息 |
| 撤回已发布版本(24小时内) | npm unpublish <pkg>@<version> | 彻底删除某版本(限 24 小时内) | npm unpublish my-pkg@1.0.1 | 超过 24 小时或包被大量下载则禁止撤回 |
| 撤回整个包(极特殊情况) | 联系 npm 支持 | 仅限法律或安全紧急情况 | 需提供充分理由 | 不保证成功;社区强烈反对随意 unpublish |
| 替代方案:发布新版本 | 发布修复版并废弃旧版 | npm version patch && npm publishnpm deprecate my-pkg@1.0.0 "Use v1.0.1+" | 推荐做法,保障生态稳定 | |
| 查看废弃状态 | npm view <pkg> deprecated | 检查是否已废弃 | npm view lodash deprecated | 返回废弃消息或 undefined |
注意:
- npm 官方政策:为保护开源生态,unpublish 权限极其受限。一旦包被其他项目依赖,几乎无法撤回。
- 废弃(deprecate)是安全且推荐的方式,不影响现有用户安装,但会提示迁移。
- 永远不要在公共 registry 中发布含敏感信息(如密钥)的包;应立即 rotate 密钥而非试图撤回。
第六章:高级功能与最佳实践
6.1 使用 npx 执行包
| 方法名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
| npx 执行本地或远程包 | npx <package> | 临时安装并运行包,无需全局安装 | npx create-react-app my-app | 若本地 node_modules 有该包,则优先使用本地版本 |
| npx 指定版本 | npx <package>@<version> | 运行特定版本的包 | npx eslint@8.0.0 --init | 避免因版本差异导致行为不一致 |
| npx 执行 Git 仓库 | npx <git-url> | 直接从 Git 仓库运行脚本 | npx https://github.com/user/tool.git | 仓库需包含可执行入口(如 bin 字段) |
| npx 忽略本地包 | npx --ignore-existing <package> | 强制使用远程最新版,忽略本地 | npx --ignore-existing typescript --version | 用于调试或验证新版本行为 |
| npx 设置缓存时间 | npx --cache-timeout <ms> | 控制临时包缓存有效期 | npx --cache-timeout 60000 jest | 默认缓存 5 分钟(300000ms) |
| npx 传递参数 | npx <package> [args...] | 向目标包传递命令行参数 | npx serve -s build -l 3000 | 参数直接透传给包的 CLI |
注意:
- npx 自 npm v5.2 起内置,无需单独安装。
- 临时安装的包默认缓存在
~/.npm/_npx/,不会污染全局或项目依赖。 - 在 CI 环境中使用 npx 可避免预装全局工具,提升环境一致性。
6.2 npm audit 安全审计
| 方法名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
| npm audit | npm audit | 扫描项目依赖中的已知安全漏洞 | npm audit | 基于 npm 官方安全数据库(https://github.com/nodejs/security-wg) |
| npm audit —audit-level | npm audit --audit-level <level> | 设置报告最低严重级别 | npm audit --audit-level high | 可选值:low, moderate, high, critical |
| npm audit fix | npm audit fix | 自动修复可无损升级的漏洞 | npm audit fix | 仅升级 patch/minor 版本,不破坏 SemVer |
| npm audit fix —force | npm audit fix --force | 允许 major 版本升级以修复漏洞 | npm audit fix --force | 可能引入 breaking change,需充分测试 |
| npm audit fix —dry-run | npm audit fix --dry-run | 预览将要执行的修复操作 | npm audit fix --dry-run | 不实际修改文件,仅输出计划 |
| npm audit signatures | npm audit signatures | 验证包签名(实验性) | npm audit signatures | 需 registry 支持,目前 npm 官方 registry 尚未全面启用 |
注意:
npm audit依赖package-lock.json或npm-shrinkwrap.json中的精确版本。- 某些漏洞无法自动修复(如无新版发布),需手动处理或添加 resolutions(配合其他工具)。
- 在 CI 中可结合
npm audit --audit-level critical实现安全门禁。
6.3 npm ci 用于 CI/CD
| 方法名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
| npm ci | npm ci | 在 CI/CD 环境中快速、干净地安装依赖 | npm ci | 必须存在 package-lock.json 或 npm-shrinkwrap.json |
| npm ci vs npm install | — | npm ci 删除 node_modules 并严格按 lock 文件安装 | npm ci(CI 推荐)npm install(开发推荐) | npm ci 不读取 package.json 的版本范围,只认 lock 文件 |
| npm ci —only=prod | npm ci --only=production | 仅安装生产依赖 | npm ci --only=production | 等效于 npm ci --production |
| npm ci —no-audit | npm ci --no-audit | 跳过安全审计(加速 CI) | npm ci --no-audit | 若已在其他阶段审计,可关闭以提速 |
| npm ci —no-fund | npm ci --no-fund | 禁用资金支持提示 | npm ci --no-fund | 减少日志噪音 |
| 错误处理 | 若 lock 文件与 package.json 不匹配,npm ci 会失败 | npm ci → 报错 “lockfile does not match” | 强制保证依赖一致性,防止”在我机器上能跑”问题 |
注意:
npm ci比npm install更快且更可靠,适用于自动化构建环境。- 本地开发仍应使用
npm install以支持动态添加依赖。 - 若项目无 lock 文件,
npm ci会报错退出,确保流程严谨。
6.4 工作区(Workspaces)支持(npm v7+)
| 概念/操作名称 | 说明 | 示例 | 注意事项 |
|---|---|---|---|
| 启用工作区 | 在根目录 package.json 中添加 "workspaces": [...] | "workspaces": ["packages/*"] | 支持 glob 模式,如 ["libs/**", "apps/*"] |
| 工作区结构 | 子项目为独立 package,含自己的 package.json | 项目根目录下 packages/a/package.json | 每个子包必须有 name 和 version |
| 安装所有工作区依赖 | npm install(在根目录) | 自动 hoist 公共依赖到根 node_modules | 依赖提升(hoisting)减少重复安装 |
| 在工作区运行脚本 | npm run <script> --workspace=<name> | npm run build --workspace=app-web | 可简写为 -w app-web |
| 为多个工作区运行 | npm run test -w a -w b | npm run build --workspaces(全部)npm run lint --workspaces | --workspaces 作用于所有工作区 |
| 链接本地依赖 | 工作区间通过 name 直接引用,自动 symlink | "dependencies": { "my-utils": "1.0.0" }(若 my-utils 是工作区) | 无需 npm link,自动建立软链接 |
| 发布工作区包 | 进入子目录后 npm publish | cd packages/utils && npm publish | 需确保版本号唯一且符合 SemVer |
| 查看工作区图谱 | npm ls --workspaces | 显示所有工作区及其依赖关系 | 用于调试依赖冲突 |
注意:
- 工作区要求 npm v7 或更高版本(Node.js 15+ 默认满足)。
- 根 package.json 的 name 不能与任何工作区包名冲突。
- 不支持嵌套工作区(即工作区内部不能再定义 workspaces)。
- 与 Lerna、Yarn Workspaces 功能类似,但原生集成,无需额外工具。
第七章:常见问题与调试
7.1 清除缓存与修复依赖
| 操作步骤名称 | 操作细节 | 注意事项 |
|---|---|---|
| 查看缓存位置 | npm config get cache | 默认路径:Linux/macOS 为 ~/.npm,Windows 为 %AppData%/npm-cache |
| 清除 npm 缓存 | npm cache clean --force | 必须加 --force,否则报错;清除后下次安装会重新下载 |
| 验证缓存完整性 | npm cache verify | 检查并移除损坏的缓存项,比 clean 更安全 |
| 重新安装所有依赖 | 删除 node_modules 和 package-lock.json,再运行 npm install | 彻底解决依赖不一致问题;适用于升级 Node.js 或 npm 后 |
| 使用 npm ci 重装 | npm ci | 基于 lock 文件干净安装,适合 CI 或本地重置 |
| 修复损坏的包 | npm install <package> --force | 强制重新下载指定包,绕过缓存 |
| 检查磁盘空间 | 确保有足够空间用于缓存和 node_modules | 缓存过大可能导致安装失败 |
注意:频繁清除缓存会影响安装速度;建议优先使用 npm ci 或删除 node_modules 重装,而非盲目清缓存。
7.2 解决”无法找到模块”错误
| 错误现象 | 可能原因 | 解决方案 | 注意事项 |
|---|---|---|---|
Error: Cannot find module 'xxx' | 包未安装 | 运行 npm install xxx | 检查是否拼写错误或大小写问题(Linux 区分大小写) |
Cannot find module(已安装) | 依赖未正确写入 package.json | 手动添加到 dependencies 或重新安装 | 避免直接修改 node_modules |
| 模块在 devDependencies 中但生产环境报错 | 生产环境未安装 dev 依赖 | 将必需包移至 dependencies,或确保不在生产代码中引用 dev 包 | npm install --production 不会安装 devDependencies |
| 全局安装的包在代码中 require 失败 | 全局包不能被 require | 改为本地安装:npm install xxx | 全局包仅用于 CLI 命令,不可作为模块导入 |
| 模块路径错误 | require 路径书写错误 | 检查相对路径(如 ./utils)或是否遗漏扩展名 | Node.js 默认不解析 .js 以外的扩展(除非 ES Modules) |
| 工作区或 symlink 问题 | 本地链接包未正确解析 | 在根目录运行 npm install 重建链接 | 使用工作区时,确保引用包是工作区成员 |
| NODE_PATH 环境变量干扰 | 自定义模块搜索路径冲突 | 避免设置 NODE_PATH,使用标准 node_modules 结构 | 现代项目应依赖标准模块解析机制 |
注意:若使用 TypeScript,还需检查 tsconfig.json 的 paths 或 typeRoots 是否配置正确。
7.3 权限与全局安装问题
| 问题类型 | 原因 | 解决方案 | 注意事项 |
|---|---|---|---|
| EACCES: permission denied(全局安装) | npm 尝试写入系统目录(如 /usr/local/lib/node_modules) | 1. 重新配置 npm 全局目录 2. 使用 npx 替代全局安装 3. 用 sudo(不推荐) | 避免使用 sudo,存在安全风险 |
| 重新配置全局目录 | — | mkdir ~/.npm-globalnpm config set prefix '~/.npm-global'将 ~/.npm-global/bin 加入 PATH | 永久解决权限问题 |
| 全局命令找不到 | PATH 未包含 npm 全局 bin 目录 | 检查 echo $PATH 是否含 $(npm config get prefix)/bin | Windows 用户检查系统环境变量 |
| Windows 权限错误 | 防病毒软件或用户账户控制(UAC)拦截 | 以管理员身份运行终端(临时),或改用用户目录安装 | 推荐配置用户级 prefix |
| nvm 用户权限正常 | nvm 将 Node 安装在用户目录,无权限问题 | 推荐使用 nvm/nvm-windows 管理 Node 版本 | 避免系统包管理器(如 apt、brew)安装 Node 导致权限混乱 |
| CI/CD 中权限错误 | 容器用户非 root | 在 Dockerfile 中创建非 root 用户并设置 npm prefix | 示例:RUN npm config set prefix /home/app/.npm-global |
注意:
- 全局安装应仅用于命令行工具(如 http-server、typescript 编译器),而非项目依赖。
- 推荐优先使用 npx 或本地安装(
npm install -D typescript+npx tsc)替代全局安装。