从注册表中下载的所有软件包都存储在一个全局缓存中,路径为 ~/.bun/install/cache
,或者由环境变量 BUN_INSTALL_CACHE_DIR
定义的路径。它们存储在名为 ${name}@${version}
的子目录中,因此可以缓存同一软件包的多个版本。
[install.cache]
# the directory to use for the cache
dir = "~/.bun/install/cache"
# when true, don't load from the global cache.
# Bun may still write to node_modules/.cache
disable = false
# when true, always resolve the latest versions from the registry
disableManifest = false
Bun 致力于避免多次重新下载软件包。在安装软件包时,如果缓存中已包含 package.json
指定范围内的某个版本,Bun 将使用缓存的软件包而不是再次下载。
如果 semver 版本带有预发布后缀(1.0.0-beta.0
)或构建后缀(1.0.0+20220101
),则会将其替换为该值的哈希值,以减少与长文件路径相关的错误。
当 node_modules
文件夹存在时,在安装之前,Bun 会检查 node_modules
是否包含所有预期的软件包以及正确的版本。如果包含,则 bun install
完成。Bun 使用自定义的 JSON 解析器,一旦找到 "name"
和 "version"
就会停止解析。
如果缺少某个软件包或其版本与 package.json
不兼容,Bun 会在缓存中查找兼容的模块。如果找到,则将其安装到 node_modules
。否则,将从注册表中下载软件包然后进行安装。
一旦软件包下载到缓存中,Bun 仍需要将这些文件复制到 node_modules
。Bun 使用可用的最快系统调用来执行此任务。在 Linux 上,它使用硬链接;在 macOS 上,它使用 clonefile
。
由于 Bun 在 Linux 和 Windows 上使用硬链接将模块“复制”到项目的 node_modules
目录,因此软件包的内容在磁盘上只存在一个位置,大大减少了分配给 node_modules
的磁盘空间。
此优势也适用于 macOS,但存在例外。它使用 clonefile
,这是写时复制的,意味着它不会占用磁盘空间,但会计入驱动器的限制。如果有人尝试修改 node_modules/*
,此行为会很有用,因此不可能影响其他安装。
此行为可通过 --backend
标志进行配置,Bun 的所有包管理命令都支持此标志。
hardlink
:Linux 和 Windows 上的默认设置。clonefile
:macOS 上的默认设置。clonefile_each_dir
:与 clonefile
类似,但它会为每个目录单独克隆每个文件。它仅在 macOS 上可用,并且通常比 clonefile
慢。copyfile
:当上述任何方法失败时的备用选项。这是最慢的选项。在 macOS 上,它使用 fcopyfile()
;在 Linux 上,它使用 copy_file_range()
。symlink
:目前仅用于 file:
(以及最终的 link:
)依赖项。为防止无限循环,它会跳过符号链接 node_modules
文件夹。
如果使用 --backend=symlink
进行安装,Node.js 将无法解析依赖项的 node_modules,除非每个依赖项都有自己的 node_modules
文件夹,或者您将 --preserve-symlinks
传递给 node
或 bun
。请参阅 Node.js 关于 --preserve-symlinks
的文档。
bun install --backend symlink
node --preserve-symlinks ./foo.js
bun --preserve-symlinks ./foo.js