npm
Node Pacakge Manager。Nodejs 的包管理工具。
类似于:PHP-Composer,Java-Maven,Python-pip,Rust-Cargo。
package.json
{
"name": "ferhannah-cli",
"version": "1.0.1", // 主版本号(大版本架构更新).次版本号(功能更新).bug修复
"description": "ferhannah-cli 脚手架工具",
// 模块化相关--
"main": "index.js", // 用户用的时候找的路径
"type": "module",
"module": "",
"browser": "",
//---
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "rollup -c rollup.config.js",
"build-ts": "rollup --config rollup.config.ts --configPlugin typescript"
},
"keywords": ["Vite", "Vue3", "React", "CLI", "Ant Design", "Element Plus"],
"bin": {
// 配置可执行文件
"ferhannah": "./bin/index.js"
},
"devDependencies": {}, // 开发时依赖
"dependencies": {}, // 生产环境依赖
"peerDependencies": {}, // 对等依赖,一般是插件人员和npm包开发人员使用;如果需要安装开发的插件必须下载其依赖的插件(对等插件)
// npm 仓库配置信息--
"repository": {
"type": "git",
"url": ""
},
"files": [], // 发布后能看到的文件
"homepage": "",
"author": "fxh",
"license": "ISC"
//--
}
npm install 原理
npm install 发生了什么?
安装的依赖会存放在根目录的 node_modules 下,默认采用扁平化的方式安装。在遍历依赖书时使用广度优先算法逐层处理每个依赖包中的依赖,直到所有的依赖都被处理完毕。在处理依赖时,npm 会检查该依赖的版本号是否符合依赖树中其他依赖版本要求,如果不合适则会尝试安装合适的版本。
如果发现需要相同依赖的不同版本,则会在需要该依赖的包下又新建一个 node_modules,再将依赖装进去。
- 先检查 npm config;
- 在当前目录下寻找
.npmrc文件(项目级别),如果找到; - 再找当前用户的
.npmrc文件(用户级别) - 再找全局的
.npmrc文件(全局:AppData) - npm 内置的
.npmrc文件(nodejs) - 检查是否有
package-lock.json文件。- 有:则比较
package.json和package-lock.json内的依赖版本是否一致。- 不一致:会根据
package.json下载并更新package-lock.json。针对 npm 高版本,现在基本上都是。
- 一致:检查缓存(之前是否安装过);
- 有:直接解压到 node_modules。
- 没有:去 npm 官网/镜像下载资源包,检查完整性,添加到缓存,更新
package-lock.json文件;
- 不一致:会根据
- 没有:获取包信息,构建依赖树和扁平化依赖,然后检查缓存;
- 有:直接解压到 node_modules。
- 没有:去 npm 官网/镜像下载资源包,检查完整性,添加到缓存,更新
package-lock.json文件;
- 有:则比较
package-lock.json
可以锁定版本,记录依赖树的详细信息。
- version:包版本号;
- resolved:包的下载地址;
- integrity:验证包的完整性的哈希值(摘要);
- dev:当前包是一个开发依赖包;
- bin:包中可执行文件的路径和名称;
- engines:包所依赖的 Nodejs 版本范围;
它还帮我们做了缓存,通过 name + version + integrity 生成一个唯一的 key,这个 key 用于映射 npm 缓存文件(一般在 npm-catch 下),如果生成的 key 能与 integrity 对上,就会从映射文件中取出缓存的二进制包并解压出来使用。
npm run 原理
npm run 发生了什么?(也就是指定 node 命令时)
nodejs 的所有命令都在 node_modules/.bin 下的可执行文件中。nodejs 支持跨平台、跨系统:
.sh:Unix、Linux 以及 MacOS 使用;.cmd:cmd 执行文件(windows);.ps1:powershell 执行文件(windows);
命令是在 package.json 中的 bin 内配置的。
- 会在当前项目找 node_modules/.bin 中是否有该命令环境;
- 再去全局的 node_modules 下找;
- 再去环境变量中找;
- 都找不到报错;
npm 生命周期
在执行 dev 之前和之后都有对应的生命周期使用,执行 dev 会自动调用 predev 和 postdev:
{
"scripts": {
"predev": "node prev.js",
"dev": "node index.js",
"postdev": "node post.js"
}
}
应用场景:
- predev:打包之前清除 dist 目录;
- postdev:CI 脚本,发布之后自动将代码提交;
注意:dev 命令可以换成其他任何自定义命令,周期命令的配置也一样。
npm 私服
优势:
- 可以离线使用;
- 提高包的安全性,避免公共 npm 包出现漏洞;
- 提高包的下载速度;
搭建
https://verdaccio.org/zh-cn/docs/installation/
npm install -g verdaccio
npm ci
同 npm install,但是是一种更干净的安装:
- 要求 package-lock.json 等锁依赖版本的文件必须存在,且版本必须和 package.json 中要求的版本对应,否则会报错;
- 在安装之前先把 node_modules 文件夹(下文可能会称为 modules)删除;
- 无法单个安装;
场景:一般用于 docker 镜像构建时使用。