从注册表中下载的所有软件包都存储在一个全局缓存中,路径为 ~/.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