包的概念
package.json 是一个 Node 项目的描述文件,描述项目的基本信息、项目依赖等等。一个包含 package.json 的目录或它的压缩包被称为 Package(包)。Git URL、本地路径或网络路径、已上传到 Registry 通过 name@version 检索,都是被 package.json 接受的访问 Package 的有效形式,前提是最终能访问到一个包含 package.json 的目录或压缩包。
能够被 Node.js 的 require 方法导入的文件、目录称为 Module(模块),单一JavaScript文件、包含 package.json 文件并定义main字段的目录、包含index文件的目录都是 require 可检索的对象 ,因此都是 Module。
package.json 一般配合包管理器使用,package.json 类似一张记录表,记录项目的直接依赖、生命周期脚本对应等。包管理器负责依据 package.json 执行依赖包安装管理、脚本调用等操作。
包管理器:npm 和 yarn
npm 和 yarn 是可替代的包管理工具,或者说是竞品关系。
包管理工具是集中管理开源包,并提供 CLI 供用户查找、安装、发布开源包的工具。大致包含三个模块:
- 官方 Registry:大家常说的“源”, 本质是大型数据库,用于存放用户上传的开源应用包及其元信息;一个服务器端连接数据库并且实现对外所需的API,也就可以作为 Registry 使用了。
- CLI: 终端交互工具,前端开发者通过 CLI 进行包搜索、安装、卸载、更新、发布操作;
- 网站:可视化操作,查找包,管理账户,管理已上传的包。
npm 和 yarn 对这些基础功能都有所实现。在依赖树管理、安装流程、缓存管理、网络下载这些方面理念和具体实现。两者在竞争和学习中发展,从 npm 一家独大到 yarn 横空出世,再到 npm v5 借鉴改进,npm v6 性能提升。如今 npm v6 和 yarn v1 的差异并不大。两者可以互相转换,比如将 package-lock.json 转换为 yarn.lock。但在同时期的一个项目中最好统一一种包管理工具以防冲突,vue-next 的在 preinstall 阶段 checkYarn 的做法也是一种可参考的控制方案。
lockfile 理念
在 npm v3 时代,npm 在 JavaScript 包管理器领域一家独大。那时 npm install 速度慢、易出错、依赖环境安装结果不一致的问题饱受诟病。原因在于项目目录中只有一份 package.json 文件负责描述项目依赖,对依赖包仅仅是规定了期望的版本范围。在不同的环境、不同的时间点进行依赖安装,可能得到不一致的安装结果。这意味着代码运行所依赖的环境不一定完全相同,在生产环境出现的问题不一定会在开发环境中预现,对于稳定性和可控性而言这是一个明显的隐患。
于是Facebook 联合 Google 发布了 Yarn,其定位同样一款包管理器,目标则是引入新的理念改进行业在包管理方面的问题。Yarn 引入 lockfile 的理念,试图通过 lockfile 精准地描述依赖包的版本。lockfile 的作用原理可以简单概述为:
- 添加或更新依赖后,在 lockfile 中记录依赖包的版本号(version)、下载地址(resolved)、hash值(integrity)。
- 安装依赖时,以 package.json 中列出的首层依赖列表为起点开始遍历安装依赖包,在安装一个依赖包时:
- 如果 lockfile 中的写定的版本符合期望的版本范围,以 lockfile 中写定的版本安装
- 如果 lockfile 中的写定的版本不符合,比如说更新了 package.json 文件;yarn 向 Registry 确认符合版本范围的最高版本,下载到本地缓存并解压到 node_modules 目录,然后更新 lockfile。
yarn 中 lockfile 以 yarn.lock 的方式实现;而 npm 也在 v3 版本之后借鉴了 Yarn lockfile 的理念,给出 package-lock.json 的实现方式。
包管理器现状
Yarn
2019.1
由于 yarn v1 架构不足以支持后续开发维护,yarn 团队选择在 v2 版本完全重构,v2 版本名为 Berry。Roadmap
2020.1
yarn@berry 低调发布,改变比较激进。
- 默认使用 PnP 替代掉 node_modules
- 增强 workspace 支持;增强 CLI 交互设计。 Introducing Yarn 2 !
2021.1
yarn 包中支持切换至 v2 版本,可通过 yarn set version 2 切换,v2 并未完全替代 v1
NPM
2020.10
NPM v7 发布,与 Node.js v15 “捆绑销售”。
- peerDependencies 自动安装
- 支持 workspace
- 支持 acceptDependencies
- 优化 package-lock 格式,支持 yarn.lock