NPM-Basic
NPM(Node Package Manager) 是随同 NodeJS 一起安装的包管理工具。
package.json
package.json 中最重要的属性是 name 和 version 两个属性,这两个属性是必须要有的,否则模块就无法被安装,这两个属性一起形成了一个 npm 模块的唯一标识符。
package.json 开发者声明的依赖蓝图
package.json 是由开发者手动维护的,通过 npm install <package> --save / --save-dev
命令写入或更新,或者直接编辑
package.json 声明了需要哪些包以及愿意接受的大致版本范围,但并不锁定确切的版本。
package.json 主要关注顶级依赖(直接依赖)。
package.json 的目的:
- 列出项目直接依赖的包(在 dependencies、devDependencies、optionalDependencies 或 peerDependencies 中)。
- 定义项目元数据: 包含项目名称、版本、描述、入口点、脚本命令(scripts)、作者信息、仓库地址等。
- 指定兼容版本范围: 使用 语义化版本 SemVer 范围(如 ^1.2.3, ~1.2.0, >2.0.0, 2.x)来定义你的项目能接受的依赖包版本。
例如:
{
"name": "my-project",
"version": "1.0.0",
"scripts": {
"start": "node app.js"
},
"dependencies": {
"express": "^4.18.0", // 声明需要 express,兼容 4.18.0 到 5.0.0(不含)之间
"lodash": "~4.17.21" // 声明需要 lodash,兼容 4.17.21 到 4.18.0(不含)之间
},
"devDependencies": {
"eslint": "^8.0.0"
}
}
在 package.json 中,dependencies
和 devDependencies
都是标准的 JSON 对象,格式相同。
dependencies 是一个对象,配置模块依赖的模块列表,key是模块名称,value是版本范围,版本范围是一个字符,可以被一个或多个空格分割。
{
"dependencies": {
"包名": "版本描述符",
// 更多生产依赖...
},
"devDependencies": {
"包名": "版本描述符",
// 更多开发依赖...
}
}
package-lock.json 精确依赖树的权威快照
package-lock.json 用于描述整个依赖树:精确到每一个直接依赖和所有层级的间接依赖。
package-lock.json 是由 npm 自动生成和维护的,永远不要手动编辑 package-lock.json 它由 npm 在运行 npm install
或 npm install <package>
安装更新依赖时自动生成或更新。
package-lock.json 精确描述了当前 node_modules 文件夹中所有内容的确切状态,像一个时间点的详细快照。
package-lock.json 只包含确切的版本号(如 “version”: “4.18.2”),没有任何语义化范围符号(^, ~)。
package-lock.json 的目的:
- 锁定依赖树: 精确描述 node_modules 目录中实际安装的每一个包的确切版本(包括所有的直接依赖和嵌套的间接依赖/传递依赖)。
- 确保一致性: 是 npm 实现确定性安装和依赖一致性的核心。它保证在任何时候(不同的机器、不同的时间点)、任何人运行
npm install
时,只要存在有效的package-lock.json
就会安装完全相同的依赖树。 - 描述依赖关系结构: 不仅仅记录版本,还记录包从哪里下载(resolved URL)、包的完整性校验和(integrity hash),以及包之间的依赖关系结构。
package-lock.json 对依赖安装/更新的影响
当 package-lock.json 存在时
npm install
会忽略 package.json 中的语义化版本范围,完全按照 package-lock.json 中描述的精确版本和依赖结构去安装依赖。这是保证一致性的关键!npm install <package>@<version>
手动安装指定版本依赖时,会自动更新 package-lock.json 来反映这个新确切的依赖树状态。这通常也会更新 package.json 中该依赖的版本范围。npm update
会根据 package.json 中定义的语义化版本范围,查找并安装满足范围的最新版本(可能是次要版本或补丁版本),并自动更新 package-lock.json 到新的精确状态。
当 package-lock.json 不存在时:
npm install
会根据 package.json 中的依赖声明,解析出最新的、符合语义化版本范围的依赖树来安装。安装完成后,npm 会自动生成一个新的 package-lock.json 文件,记录下这次安装的精确快照。此时安装的结果可能会在不同时间或不同环境中因新版本的发布而略有差异。
dependencies 运行时依赖
dependencies 描述项目在生产环境运行所必需的依赖包
执行 npm install pkg
时会自动下载和安装 dependencies
中的依赖
核心依赖通过 dependencies 描述,例如:
框架/库:react, vue, express, lodash
UI 组件:antd, material-ui
工具库:axios, moment
devDependencies 开发依赖
devDependencies 描述仅在开发、测试和构建过程中需要的依赖包
生产环境部署时自动排除(通过 NODE_ENV=production)
执行 npm install pkg
时不会安装 devDependencies
中的依赖,因为用户需要的是应用运行需要的包,而不是开发需要的包。
常用于安装一些本地构建、调试、测试框架,例如:
构建工具:webpack, vite, babel
测试框架:jest, mocha, cypress
代码质量:eslint, prettier
类型检查:typescript, @types/* (TS 类型定义)
安装
npm install <package-name> --save-dev
# 或简写
npm i <package-name> -D
peerDependencies 宿主依赖
peerDependencies 并不是告诉 npm “请帮我安装这个包”,而是告诉使用你包的开发者(或者项目):“我的包需要运行在某个宿主环境中,而这个宿主环境必须已经提供安装了这些特定版本的包。” 常用于插件、库的扩展、主题等场景。
peerDependencies 是需要宿主环境提供的包(如 react 插件要求宿主安装指定版本 react),相当于 maven 的 provided 作用域。
peerDependencies 的目的是避免重复安装和版本冲突。如果你的插件指定了它所兼容的宿主库(如 React, Vue, Webpack)的版本,而宿主项目也已经安装了这个版本的宿主库,则插件就会共享使用项目中已安装的那个版本。
当安装一个包A(如一个插件)时,npm 会检查当前项目(宿主项目)是否已经安装了 A 在 peerDependencies 中声明的包B(如 Vue ),并且安装的 B 的版本是否满足 A 声明的版本范围
- 如果项目中没有安装B,或者安装的B版本与A的要求不兼容,npm 会打印一个警告 UNMET PEER DEPENDENCY(npm 版本小于 7.x 会显示错误)
- npm 7+ 中,会自动所有 peerDependencies,除非能检测到项目中已经存在兼容的版本。如果存在不可解决的冲突,npm 会失败并报错。
假设当前 npm 包是 React 的一个组件,可以在 peerDependencies 中要求 React 的宿主版本:
// 假设这是一个 React UI 组件库的 package.json
"peerDependencies": {
"react": ">=16.8.0 <18.0.0", // 声明这个组件库只能在React 16.8-17.x的项目中使用
"react-dom": ">=16.8.0 <18.0.0"
}
optionalDependencies 可选依赖
optionalDependencies 中是可选依赖,即使安装失败也不阻塞流程。
如果一个包同时在 dependencies 和 optionalDependencies 中被列出,其行为由 optionalDependencies 决定,即安装失败不算错误
SemVer 语义化版本控制
npm 使用 语义化版本 SemVer 描述版本号主版本号.次版本号.修订号
major.minor.patch
版本号递增规则如下:
- major 主版本号:做了不兼容的 API 修改
- minor 次版本号:做了向下兼容的功能性新增
- patch 修订号:做了向下兼容的问题修正
^
符号表示允许安装指定版本之后的最新 兼容版本,要求 不改变最左边非零数字的版本号,最常用,是默认行为
- 如果主版本号不为0,即 x.y.z 中 x≠0,允许 minor 版本和 patch 版本更新,
^x.y.z
等于>=x.y.z && <(x+1).0.0
例如^4.18.2
允许的版本范围是>=4.18.2 && <5.0.0
,拒绝 5.0.0 及以上 - 如果主版本号为0,即
0.y.z
,表示处于开发阶段,此时 minor 版本被视为不兼容的大版本更新,仅允许更新 patch 版本,^0.y.z
等于>=0.y.z && <0.(y+1).0
例如^0.2.3
允许的版本范围是>=0.2.3 <0.3.0
,拒绝 0.3.0 及以上 - 主次版本均为 0 时,例如
^0.0.3
表示>=0.0.3 <0.0.4
,其实就是必须完全等于0.0.3
,此时直接使用精确版本号即可,避免使用这种主次都是0的兼容版本号
4.18.2
精确版本,拒绝任何其他版本~4.18.2
安全版本,约等于,仅允许补丁更新,允许的版本号范围是 大于等于 4.18.2 且 小于 4.19.0,拒绝 4.19.04.18.x
通配符,匹配特定版本段的任何补丁更新,等效于 ~4.18.0>4.17.0 <4.19.0
区间描述符,指定版本安装范围,安装符合范围的最高版本,例如 >version
>=version
<version
4.18.2-beta.3
预发布版本,安装特定预发布版本,需明确指定完整版本号*
或 ""
任意版本,安装最新版本(高危操作),可能引入破坏性更新"latest"
安装最新正式版,等效于 *
特殊依赖
dependencies 也可以被指定为一个 git 地址或者一个压缩包地址。
1、Git 仓库依赖:
{
"dependencies": {
"private-pkg1": "git+https://github.com/user/repo.git", // 指定git仓库
"pkg-on-branch": "github:user/repo#branch-name", // 指定特定分支
"pkg-on-commit": "git+https://github.com/user/repo#commit-hash" // 指定特定提交
}
}
2、本地文件/压缩包依赖
{
"devDependencies": {
"local-pkg": "file:./path/to/local-module",
"tarball": "https://registry.com/pkg-1.2.3.tgz"
}
}
scripts 自定义脚本字段
npm run
是一个在项目中执行自定义脚本的接口,其能力来源于 package.json 文件中的 scripts
字段。
scripts
字段是 npm run 的 『指令集』scripts
字段是一个 JSON 对象,属性名(键)是自定义的脚本名称(如 dev, serve, build, lint),属性值(值)是该脚本实际要执行的 shell 命令。
例如 Vue3 项目 package.json 文件中的 scripts
字段如下:
{
"name": "my-vue3-app",
"version": "0.1.0",
"scripts": {
"dev": "vite", // 用于启动开发服务器
"build": "vite build", // 用于构建生产包
"preview": "vite preview" // 用于预览生产包
"build-only": "vite build",
"type-check": "vue-tsc --build",
"lint": "eslint . --fix",
"format": "prettier --write src/"
},
"dependencies": { ... },
"devDependencies": { ... }
}
node_modules/.bin 模块的可执行文件
当通过 npm 安装一个包时(无论是 dependencies 还是 devDependencies),如果这个包提供了一个可以在命令行中调用的可执行文件(通常在其 package.json 中有 “bin” 字段声明),那么 npm 就会在项目的 node_modules/.bin 目录下创建指向这些可执行文件的符号链接(Symlinks)(在 Windows 上可能是 .cmd 或 .ps1 文件)。
问题
npm does not support Node.js v8.17.0
问题:
npm WARN npm npm does not support Node.js v8.17.0
npm WARN npm You should probably upgrade to a newer version of node as we
npm WARN npm can't make any promises that npm will work with this version.
npm WARN npm You can find the latest version at https://nodejs.org/
查看 node 和 npm 版本号
# node -v
v12.14.0
# npm -v
6.13.4
原因:
node 版本太新,npm 版本太旧,不支持新版 node
解决:
更新 npm 版本
切换到 root 用户:
# npm install -g npm
# npm -v
7.20.0
上一篇 TypeScript
下一篇 NPM-Package
页面信息
location:
protocol
: host
: hostname
: origin
: pathname
: href
: document:
referrer
: navigator:
platform
: userAgent
: