node_modules 目录,Bun 将放弃 Node.js 风格的模块解析,转而使用 Bun 模块解析算法。
在 Bun 风格的模块解析下,所有导入的包将在运行时自动安装到一个全局模块缓存中(与 bun install 使用的缓存相同)。
"foo" 并缓存它。下一次运行该脚本时,将使用缓存的版本。
版本解析
为确定安装哪个版本,Bun 遵循以下算法:- 检查项目根目录中是否存在
bun.lock文件。如果存在,则使用锁文件中指定的版本。 - 否则,向上遍历目录查找包含
"foo"作为依赖项的package.json。如果找到,则使用指定的语义版本或版本范围。 - 否则,使用
latest。
缓存行为
一旦确定了版本或版本范围,Bun 将:- 检查模块缓存中是否有兼容版本。如果存在,则使用它。
- 解析
latest时,Bun 会检查package@latest是否在最近 24 小时内 已下载并缓存。如果是,则使用它。 - 否则,从
npm注册表下载并安装合适的版本。
安装
包被安装并缓存到<cache>/<pkg>@<version>,因此同一包的多个版本可以同时缓存。此外,在 <cache>/<pkg>/<version> 下创建了一个符号链接,以更快地查找缓存中存在的某个包的所有版本。
版本说明符
您可以在导入语句中直接指定版本或版本范围,从而简化整个解析算法。优势
这种自动安装方式有以下几方面的优势:- 空间效率 — 每个依赖的每个版本在磁盘上都只存在于一个位置。与每个项目中为避免重复安装而进行的冗余安装相比,这带来了巨大的空间和时间节省。
- 可移植性 — 要共享简单脚本和 gist,您的源文件是 自包含 的。无需把包含代码和配置文件的目录打包成 zip。通过在
import语句中使用版本说明符,即使没有package.json也不需要。 - 便利性 — 运行文件或脚本之前无需先运行
npm install或bun install。用bun run运行即可。 - 向后兼容 — 因为如果存在
package.json,Bun 仍会尊重其中指定的版本,所以你可以只用一个命令切换到 Bun 风格的解析:rm -rf node_modules。
限制
- 无智能提示。IDE 中 TypeScript 的自动补全依赖于
node_modules内存在类型声明文件。我们正在探索各种解决方案。 - 不支持 patch-package
常见问题解答
这与 pnpm 的做法有何不同?
这与 pnpm 的做法有何不同?
使用 pnpm,必须先运行
pnpm install,该命令会创建一个包含符号链接的 node_modules 文件夹供运行时解析。相比之下,Bun 在运行文件时动态解析依赖,无需事先运行任何安装命令。Bun 也不会创建 node_modules 文件夹。这与 Yarn Plug'N'Play 有何不同?
这与 Yarn Plug'N'Play 有何不同?
使用 Yarn,必须先运行
yarn install 才能运行脚本。相比之下,Bun 在运行文件时动态解析依赖,无需事先运行任何安装命令。Yarn Plug’N’Play 使用 zip 文件存储依赖,这导致依赖加载在运行时更慢,因为对 zip 文件的随机访问通常比等效的磁盘查找更慢。参考这与 Deno 有何区别?
这与 Deno 有何区别?
Deno 需要在每个 npm
import 之前加上 npm: 说明符,不支持通过 tsconfig.json 中的 compilerOptions.paths 使用导入映射,并且对 package.json 配置支持不完整。与 Deno 不同,Bun 目前不支持 URL 导入。