命令行工具
nubjs/nub avatar
nubjs/nub

Nub:在原生 Node 之上复刻 Bun 体验的 Rust 工具链

该项目围绕「The fast all-in-one Node.js toolkit. Script runner, nub run A drop-in for npm run and pnpm run.」构建,适用于实际场景的开源实践,提供可复用的工具链与集成方式。

4,296 个 Star60 个 ForkRustMIT

秒懂

它是什么?
Nub 是一个用 Rust 编写的 Node.js 一体化工具,宣称能以 24 倍速度替代 pnpm run,并集成文件运行、包管理、Node 版本管理等功能。本文基于其 README 和仓库信息,分析其实现机制、适用场景与潜在局限。
适合谁用?
Nub 适合那些已经受够了 npm run 启动延迟、又不想迁移到 Bun 或 Deno 的 Node 开发者,尤其是 TypeScript 项目、需要快速脚本调度或频繁切换 Node 版本的人。它不适合那些依赖原生 npm 生态插件、需要完全可控的 Node 行为、或者对自动下载运行时心存疑虑的团队。
能商用吗?
可以。MIT 是宽松许可证:你可以使用、修改并销售基于它的软件,只需保留版权和许可证声明。
还在维护吗?
在维护。仓库最近一次提交在 1 天前。
用什么语言写的?
主要是 Rust(依据 GitHub 的语言统计)。

以上回答依据项目的 GitHub 数据(最近同步于 2026年9月14日)和我们的分析,不构成法律意见。

开源项目深度解析

它解决什么问题

Node.js 生态的工具链是碎片化的。运行 TypeScript 文件要 tsx,跑脚本要 npm run,装包要 pnpm,管理 Node 版本要 nvm,监视文件要 nodemon。每个工具都有自己的启动成本和配置方式。Nub 想用一个 Rust 二进制把这些全部收拢,且不引入新的运行时。它不实现 JavaScript 引擎,而是站在原生 Node 之上,通过扩展机制增强能力。目标用户是那些不想离开 Node 生态,却羡慕 Bun 的开发者体验的人。

核心机制:站在 Node 的扩展点上

Nub 没有重写 Node,它利用了 Node 本身提供的扩展接口。文档明确列出三个关键依赖:--import 和 --require 预加载、module.registerHooks() 用于转译和解析、N-API 原生插件。它内嵌了 oxc 做预转译。这意味着 Nub 的 TypeScript 支持不是通过独立编译器,而是通过钩子拦截模块加载。文件运行时,Nub 会先解析 Node 版本,根据 .node-version 或 package.json 的 engines 字段自动下载对应版本,然后用那个版本执行你的代码。这解释了为什么它能兼容 enum、namespace 和装饰器,因为这些由 oxc 转译后交给 Node 原生运行。

文件运行:TypeScript 与实验 API 的处理方式

nub index.ts 可以直接运行 TypeScript,无需构建步骤。它支持扩展名省略和 tsconfig.json 的 paths 映射。更特别的是它对现代 API 的处理策略:Temporal 在 Node 26 以下用 polyfill,URLPattern 在 Node 24 以下用 polyfill,而 node:sqlite 和 WebSocket 则通过 unflag 方式启用。这种分级处理意味着同一个文件在不同 Node 版本下行为可能不同。文档声称启动速度比 tsx 快 2.9 倍,但注意这是 README 的声明,我们无法验证。另一个细节是自动加载 .env 文件,这省去了 dotenv-cli,但也意味着环境变量的来源变得隐式,调试时可能困惑。

脚本运行与包管理:速度声明背后的取舍

nub run 被定位为 npm run 和 pnpm run 的直接替代。README 给出 24 倍加速的对比,原因是 Rust 二进制没有 JavaScript 启动开销。nubx 替代 npx,宣称 19 倍加速。nub install 替代 pnpm install,宣称 18 倍加速。这些数字来自项目自己的基准,我们没有独立验证。速度提升的代价是依赖解析逻辑必须重新实现。pnpm 的硬链接和内容寻址存储是经过多年优化的,Nub 的 install 是否支持 monorepo 的 workspace 协议、是否处理 peer dependencies 的复杂情况,README 没有详细说明。对于大型 monorepo,这些细节可能比启动速度更重要。

Node 版本管理与 shims

nub node install 26 可以安装指定版本的 Node,nub pm shim 提供 Corepack 风格的 shims。版本解析的优先级顺序是 NODE_EXECUTABLE 环境变量、package.json 的 devEngines、.node-version、.nvmrc、最后是 engines 字段。这个顺序合理,但注意 devEngines 是相对较新的字段,很多项目还没用上。自动安装 Node 意味着第一次运行某个项目时,Nub 可能静默下载一个运行时,这在 CI 环境可能造成意外延迟。setup-nub 这个 GitHub Action 声称与 actions/setup-node 一对一兼容,但替换后 Node 版本解析行为可能不同,因为 setup-nub 可能也遵循同样的优先级。

已知限制与失败模式

最明显的限制是 Nub 的兼容性依赖 Node 的扩展接口,而这些接口仍在演进。module.registerHooks() 在 Node 22 才稳定,这意味着 Nub 可能无法支持太老的 Node 版本。文档没有明确最低版本要求。另一个问题是 polyfill 的一致性:Temporal 的 polyfill 不可能与原生实现完全一致,如果你的代码依赖 Temporal 的边界行为,在 Node 25 和 Node 26 下运行结果可能不同。watch 模式依赖 Node 的 --watch 引擎,这意味着它继承 Node 自身的限制,比如对某些文件系统事件的响应延迟。最后,Nub 是年轻项目,版本号还在 0.8.0-canary,API 可能变动。

替代方案与对比

最直接的替代是 Bun,它同样提供文件运行、脚本执行和包管理,但 Bun 是独立的 JavaScript 运行时,这意味着你的代码在 Bun 下运行的行为可能与 Node 有差异,尤其是涉及原生模块时。Nub 选择留在 Node 上,避免了这个兼容性问题,但代价是无法获得 Bun 的底层性能优化,比如更快的启动和更高效的内存管理。另一个替代是 Volta 或 fnm 加 tsx 的组合,它们各自解决一个问题,但需要配置多个工具。Nub 的一体化优势在于单一二进制,但如果你只需要其中一个功能,比如只想要更快地跑脚本,那么单独使用 pnpm run 加 shell 优化可能更简单。

维护与升级成本

Nub 以 MIT 许可证发布,这意味着你可以自由使用和修改。但作为 0.8.0 阶段的工具,升级频率很高,从最近的 canary 版本号可以看出,几乎每天都有新构建。这意味着 bug 修复很快,但也意味着行为可能频繁变化。README 提到 nub upgrade 可以自更新,但频繁更新可能带来不确定性。如果你在 CI 中使用 setup-nub,需要锁定版本以避免意外变化。另外,Nub 依赖 oxc 和 Node 的内部接口,这两个上游的变化都可能影响 Nub 的稳定性。在采用前,建议查看其 GitHub issues 了解已知问题,但 README 没有提供这些信息。

编辑结论

Nub 适合那些已经受够了 npm run 启动延迟、又不想迁移到 Bun 或 Deno 的 Node 开发者,尤其是 TypeScript 项目、需要快速脚本调度或频繁切换 Node 版本的人。它不适合那些依赖原生 npm 生态插件、需要完全可控的 Node 行为、或者对自动下载运行时心存疑虑的团队。在采用前,先验证三件事:一是 Nub 对 package.json 中 scripts 的解析是否与你的现有脚本完全兼容,二是其自动 Node 版本解析是否与 CI 环境一致,三是 nubx 在 npx 场景下的行为差异是否影响你依赖的二进制工具。如果你的项目大量使用 Node 的实验性 API,Nub 的自动 unflag 和 polyfill 可能带来便利,但也可能掩盖版本差异,务必在 CI 中固定 Node 版本。最终,Nub 的价值取决于你对速度的敏感度,以及对一个年轻工具链的容忍度。

官方来源

  1. Official documentation
  2. Official README
  3. Project repository
  4. Release notes
社区笔记

社区笔记