upm 发布:纯 TypeScript 编写的轻量 npm 包管理器
Original title: npm 太慢?把 n 翻过来,装包直接起飞!
The title and summary in the selected language are awaiting translation.
upm 是一个运行在 Node.js 上、面向 npm 仓库的轻量级包管理器,用 TypeScript 编写,工具本身约 256 KB、压缩后约 85 KB,官方称安装速度可与 Rust 编写的包管理器相当。
The full text in the selected language is awaiting translation. The original is shown for now.
谁想出来的?把 npm 的 n 翻过来,装包快得离谱!
前端包管理器又多了一个新选择,名字挺好记:把 npm 的 n 翻过来变成 u,就是 upm。
它用 TypeScript 编写,体积约 256 KB。官方介绍里还写了一句很吸引人的话:安装速度与 Rust 编写的包管理器相当。
npm、pnpm、Bun 都已经有了,它还能玩出什么新东西?
什么是 upm?
upm 是一个运行在 Node.js 上、面向 npm 仓库的轻量级包管理器。项目里的依赖照常安装,不需要换一套生态。
官方列出的特点很直接:
🟦 纯 JS: 使用 TypeScript 和 Node.js 内置能力构建,不需要额外安装其他运行时。
🪶 小巧: 磁盘占用约 256 KB,压缩后约 85 KB,足够小,可以直接打包进自己的工具。
🚀 速度快: 官方称,安装速度可以与 Rust 编写的包管理器相当,实际表现取决于项目和运行环境。
🧩 可编程: 每个命令都有对应的 JavaScript 函数,可以直接导入自己的程序。
🎯 简单: 不额外引入一套配置方式,沿用
.npmrc中的仓库、认证等配置。🔒 默认安全策略: 设置 1 天的版本发布等待期,并跳过依赖的生命周期脚本。
📦 兼容锁文件: 支持读取现有的
package-lock.json、pnpm-lock.yaml和bun.lock。
注意,256 KB 指 upm 工具本身,不包含 Node.js,也不是说项目的 node_modules 能缩到这么小。它优化的是安装依赖的过程,不能直接理解成项目运行、构建也会跟着提速。
为什么还要做一个包管理器?
作者在文档里专门回答了这个问题,对现有工具的评价也挺直接:
npm: 随 Node.js 一起提供,但他觉得安装速度慢。
pnpm: 速度快、设计好,不过体积、功能和可配置项都在不断增加。
Yarn Berry: 引入了不少自己的概念和使用要求,变得复杂。
Bun、Deno、Nub: 很快,但作者认为,同时采用它们的运行时会更合适。
这些是作者的取舍,不代表上述工具不能用于 Node.js 项目。
他想继续用 Node.js,又希望工具足够小、安装足够快,还能方便地嵌进其他程序。upm 就是从这几个需求出发的。
Node.js 已经有的能力,直接用
工作线程、zlib、fetch、文件系统,Node.js 已经提供了这些能力,没必要再随包管理器带上一整套实现。
upm 同时会在多个项目之间共享缓存,通过硬链接减少文件复制,并保存安装状态。依赖没有变化,重复安装时就尽量少做事。
所以它虽然用 TypeScript 编写,下载、解压、文件操作也不是全部拿 JavaScript 从头实现。真正能省下时间的,还有重复下载、复制和检查这些环节。
不想每次装包,都启动一个子进程
另一个出发点是 JavaScript API。
开发脚手架、项目生成器时,安装依赖往往需要单独启动命令,再处理输出和退出状态。作者希望把这些操作直接做成函数,工具本身也足够小,能够一起打包进去。
upm 最初就是一个实验:充分利用 Node.js,看看纯 TypeScript 的 npm 客户端能做到多小、多快。
如何使用?
需要 Node.js 22.3 +,官方提供的 npm 安装命令如下:
npm i -g upm --min-release-age 0先建一个空项目,试试常用操作:
mkdir upm-demo
cd upm-demo
npm init -y
# 添加项目依赖
upm add vue@^3
# 添加开发依赖
upm add --dev vitest
# 安装依赖,也可以写成 upm i
upm install
# 删除依赖
upm remove vitest项目里已经定义了 build 脚本,就可以用 upm run build 执行。它还带了一个 upx,用来临时执行 npm 包提供的命令,必要时先安装对应的包:
upx cowsay hello使用 upm 自己的锁文件时,记得把 upm.lock 提交到仓库。CI 中执行:
upm install --frozen-lockfile锁文件缺失或与项目不一致时直接报错,不会重新选择依赖版本。
已有项目,注意这几个地方
切换前,官方建议先清理旧的 node_modules,避免继续引用残留的包。原来的锁文件可以保留,但此时 upm 只负责按它安装,增删依赖仍需使用原工具。包含工作区、补丁、Git 或 file 依赖的外部锁文件,目前不支持。
另外,upm 目前还是预发布版本,默认不执行依赖的 install、postinstall 等脚本。项目中有靠这些脚本编译或下载文件的包,需要单独检查。前面说的“一天等待期”,也不限制已经锁定或明确指定的精确版本。
写脚手架的,可以重点看看 JS API
在自己的工具项目里安装 upm 依赖后,安装项目依赖就可以写成一次函数调用:
import { install } from'upm';
await install({
dir: './my-project',
log: (message) =>console.log(message),
});函数会返回安装结果,进度和警告通过 log 接收。添加包、解析版本、生成锁文件、执行脚本,也都有对应接口。
比如做一个 Vue 项目脚手架,用户选好模板之后,生成文件、安装依赖、处理错误、输出启动提示,就能接在同一个程序里。
upm 还支持可插拔存储后端,可以接入团队共享缓存或键值存储,不必只使用默认的本地缓存。
只想日常装包,先拿一个小项目试试就够了。正在写脚手架、项目生成器的同学,可以多看看 JavaScript API 这一节:除了换一条安装命令,upm 还把装包这件事做成了一套可以直接调用的接口。
Source: 前端开发爱好者 · mp.weixin.qq.com