node.js
package.json与package-lock.json的区别
参考文档 https://nodejs.dev/learn/the-package-lock-json-file
package-lock.json是为了弥补package.json的一些不足之处。
package.json中记录的包依赖版本信息遵循如下语法:
- 如果package.json中记录的版本信息格式为
~0.13.0
,则表示仅允许更新补丁版本(0.13.1),不允许更新小版本(0.14.0) - 如果package.json中记录的版本信息格式为
^0.13.0
,则表示除了最靠近左边的非0版本号不可以更新(如果主版本非0,则可以更新小版本和补丁版本;如果主版本为0,小版本不为0,那么只允许更新补丁版本)
项目进行版本管理时,node_modules中安装的包我们不会提交到远端仓库,我们只会把package.json纳入版本管理,那么当其他开发者在本地拉取项目,执行npm install
命令后会发生如下行为:
- npm遵循package.json的包版本要求在本地安装依赖包
此时可能会安装包最新的小版本或者补丁版本,导致的结果会是每个开发者初始化后的项目不一致,还有可能会因为安装依赖包的小版本中引入bug。
package-lock.json就是解决上述的问题,其他开发者可以严格遵循package-lock.json中的版本下载依赖包(通过执行npm ci
命令),这样便能确保每个开发者初始化项目后环境一致。
什么情况下package-lock.json中的版本信息会更改
参考文档:https://nodejs.dev/learn/update-all-the-nodejs-dependencies-to-their-latest-version
- 执行
npm update
命令会更新package-lock.json中依赖版本 - 当执行
npm install
命令时,会发生如下行为:- 检查package-lock.json中的包版本是否符合package.json中的范围
- 如果满足,按照package-lock.json安装最新的可用包被安装到node_modules路径,包对应的版本信息被添加到package.json和package-lock.json(package.json是大概版本,package-lock.json中是确切的版本)
- 如果不满足,则更新包最新的版本
npm
版本语法
参考文档 https://nodejs.dev/learn/semantic-versioning-using-npm
版本采用三个数字来标识,x.y.z
- x表示主版本
- y表示小版本
- z表示补丁版本
package.json中记录的版本前会增加一些符号,这些符号在执行npm update
是会起作用,具体规则查看参考文档
命令选项
ci
- 如果package-lock.json中的版本与package.json中不符合,则报错,ci命令退出
- 执行ci不会更新package.json
- ci执行更快,常用于自动化环境,比如测试平台,持续集成,持续部署
install
安装一个或者多个依赖的包,如果包有package-lock,则npm install会遵循package-lock.json
lerna
lerna是一个多项目开发下的包管理工具
命令选项
clean
清除非根路径下的node_modules
bootstrap
处理本地包关联,然后安装包
–hoist选项把子模块的共用模块提升至根路径
–ci选项指通过npm ci安装依赖包,通过npm ci安装要求必须要有package-lock.json
-hoist和–ci冲突,当添加–hoist选项时,默认执行npm i,但是不会更新package-lock.json
相关issue https://github.com/lerna/lerna/issues/2047
//源代码 if (hoist) { let hoisting; if (hoist === true) { // lerna.json `hoist: true` hoisting = ["**"]; } else { // `--hoist ...` or lerna.json `hoist: [...]` hoisting = [].concat(hoist); } if (nohoist) { if (!Array.isArray(nohoist)) { // `--nohoist` single hoisting = hoisting.concat(`!${nohoist}`); } else { // `--nohoist` multiple or lerna.json `nohoist: [...]` hoisting = hoisting.concat(nohoist.map((str) => `!${str}`)); } } this.logger.verbose("hoist", "using globs %j", hoisting); this.hoisting = hoisting; } if (npmClient === "npm" && this.options.ci && hasNpmVersion(">=5.7.0")) { // never `npm ci` when hoisting this.npmConfig.subCommand = this.hoisting ? "install" : "ci"; if (this.hoisting) { // don't mutate lockfiles in CI this.npmConfig.npmClientArgs.unshift("--no-save"); } }
执行
lerna bootstap --hoist --ci --loglevel verbose
输出lerna notice cli v4.0.0 lerna info ci enabled lerna verb hoist using globs ["**"] lerna info Bootstrapping 4 packages lerna verb lifecycle preinstall
npm ci与npm i主要有以下的区别。
- npm i依赖package.json,而npm ci依赖package-lock.json。
- 当package-lock.json中的依赖于package.json不一致时,npm ci退出但不会修改package-lock.json。
- npm ci只可以一次性的安装整个项目依赖,但无法添加单个依赖项。
- npm ci安装包之前,会删除掉node_modules文件夹,因此他不需要去校验已下载文件版本与控制版本的关系,也不用校验是否存在最新版本的库,所以下载的速度更快。
- npm安装时,不会修改package.json与package-lock.json
打印更多日志
lerna --loglevel 日志级别
比如打印verbose日志
lerna --loglevel verbose