从注册表下载的所有包都存储在 ~/.bun/install/cache
的全局缓存中。它们存储在命名为 ${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 上项目的 node_modules
目录中,因此包的内容只存在于磁盘上的一个位置,从而大大减少了专用于 node_modules
的磁盘空间量。
此优势也适用于 macOS,但有一些例外。它使用的是 clonefile
,它是写时复制,这意味着它不会占用磁盘空间,但它会算作驱动器的限制。如果某些内容尝试修补 node_modules/*
,则此行为非常有用,因此不可能影响其他安装。
此行为可通过 --backend
标志进行配置,Bun 的所有包管理命令都尊重此标志。
hardlink
:Linux 上的默认设置。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
。请参阅 Node.js 关于 --preserve-symlinks
的文档。
bun install --backend symlink
node --preserve-symlinks ./foo.js
Bun 的运行时目前不提供 --preserve-symlinks
的等效项。