3、包管理工具介绍:remotes、devtools、pak的适用场景与基本用法

做R包开发,装包不是只敲一个 install.packages() 就完事了。尤其是当你遇到依赖冲突、版本锁定、或者要装GitHub上的开发版时,内置函数往往力不从心。

这时候你需要专门的包管理工具。我个人常用三个:remotes、devtools 和 pak。它们各有侧重,但很多人分不清该用谁。我最早也踩过坑——用devtools装一个纯依赖包,结果它把整个编译链都拖下来了,慢得离谱。

三个工具,各自定位不同

咱们先捋一下它们之间的关系。devtools是个大而全的“开发套件”,不光管安装,还管测试、文档、检查。remotes则是它内部的一个轻量模块,后来独立成包,专门负责“从各种来源安装”。pak更年轻,是RStudio团队的新作品,主打并行下载+依赖解析,速度和稳定性都上了一个台阶。

我自己的经验是:

  • 如果只是临时装一个GitHub包,用 remotes 就够了,轻巧无负担。
  • 如果你在写包、需要做单元测试或生成文档,那 devtools 全家桶更合适。
  • 如果你是生产环境、或者要批量安装几十个包,pak 是首选——它不会因为一个包失败就让整个安装停掉。
工具 主要场景 依赖数量 并行安装 我的推荐
remotes 从GitHub/GitLab/BitBucket/本地安装 极少 否 快速装一两个包
devtools 开发全流程(安装+测试+文档+检查) 多 否 R包开发日常
pak 高可靠安装、依赖冲突解决、离线安装 中等 是(5线程) 生产环境/大项目

remotes:轻装上阵,专治“从别处装包”

remotes的核心思路就一个——把你从CRAN之外的来源拉包进来。GitHub、GitLab、BitBucket、本地tar.gz、甚至一个URL都可以。代码很直观:

# 从GitHub安装(默认master分支)
remotes::install_github("tidyverse/dplyr")

# 指定分支或tag
remotes::install_github("rstudio/shiny@v1.7.4")

# 从GitLab
remotes::install_gitlab("user/repo")

# 从本地的压缩包
remotes::install_local("~/Downloads/mypackage_1.0.tar.gz")

我最喜欢它的 install_deps() 函数。当你拿到一个包的源码,只想把它的依赖都安好,不需要编译这个包本身时,这个函数特别爽。举个例子:

# 下载一个包的源码后,只安装它的依赖
remotes::install_deps(".", dependencies = TRUE)

一点经验:如果你从GitHub装包老是失败,先检查一下是不是网络问题。在国内建议设置代理:Sys.setenv(GITHUB_TOKEN = "你的token") 可以提升速率。

devtools:瑞士军刀,但请按需使用

devtools是Hadley Wickham的杰作,几乎每个R包开发者都绕不开它。它把remotes、testthat、roxygen2这些工具打包在一起。安装命令跟remotes很像,但因为依赖多,第一次安装要等很久。

# devtools安装GitHub包
devtools::install_github("hadley/ggplot2")

# 安装本地包(会自动构建)
devtools::install_local("~/my_package")

# 安装依赖(区别于remotes,devtools只装depends)
devtools::install_deps(".")

你可能会问:既然devtools包含了remotes,那我是不是只用devtools就行了?

我个人建议:做普通安装时,别轻易用devtools。原因是它会依赖很多开发工具(如roxygen2、testthat、pkgbuild等),如果你只是装包用,这些完全多余。我在一个服务器上因为装devtools而搞出了gcc版本冲突,折腾了半小时。

避坑指南:千万不要用devtools::install_github()来装devtools自己——这会产生循环依赖。先装remotes,再用remotes装devtools是标准做法。

pak:下一代安装利器,快且稳

pak是RStudio在2021年推出的新工具,用C++重写了核心依赖解析引擎。它的特点:

  • 并行下载:默认5个线程同时拉包,速度翻倍。
  • 智能缓存:第二次装同一个包几乎不花时间。
  • 冲突处理:当多个包对同一依赖有版本需求时,pak会自动选一个合理版本,而不是报错。
# 安装pak本体(需从GitHub或源代码装)
install.packages("pak", repos = "https://r-lib.github.io/p/pak/dev/")

# 基本用法:安装一个包
pak::pkg_install("dplyr")

# 批量安装多个
pak::pkg_install(c("tidyverse", "shiny", "rmarkdown"))

# 从GitHub安装(语法类似remotes)
pak::pkg_install("tidyverse/ggplot2")

# 查看安装计划(不实际安装,只预览依赖树)
pak::pkg_deps_tree("ggplot2")

我去年帮一个团队部署R环境,150多个包用install.packages装了快两小时,还中途断了两次。换成pak后,同样是那些包,35分钟搞定,而且中途网络闪断时它自动重试了。

SVG:三工具选择决策图

下面这张图帮你快速判断当前场景该用谁。记住:先看“是不是开发”,再问“是不是批量”。

R包安装工具选择决策图 你是只安装,还是开发? 只安装(生产/临时) 开发包(测试/文档) 是否批量(≥10个包)? remotes 轻量、无依赖 pak 并行、缓存、批处理 是否同时需要测试/文档? devtools 全家桶、开发标配 remotes + pkgbuild 只要安装,不求其他 提示:生产环境尽量用pak,开发环境用devtools,临时装一两个包用remotes。

对比表格:命令对应关系

为了方便你记忆,我把三个工具的常用命令放在一起对比。你会发现,核心功能差异很小,主要区别在附加能力。

操作 remotes devtools pak
装GitHub包 install_github() install_github() pkg_install("user/repo")
装本地包 install_local() install_local() pkg_install("path")
装依赖 install_deps() install_deps() pak::pkg_deps()
卸载包 无 无 pkg_remove()
查看版本冲突 无 无 pkg_deps_tree()

避坑清单:我踩过的三个雷

最后,分享几个我用这些工具时遇到的典型问题,希望你能直接跳过。

  1. 忘了重启R会话:用remotes装完包后,如果发现新包的函数找不到,八成是没重启。最好在装完后执行 .rs.restartR()(RStudio)或重新打开R。
  2. 依赖版本冲突时硬装:我遇到过装一个包需要dplyr 1.0,另一个需要0.8。两个都用install.packages直接报错。用pak的话,它会自动降级/升级其中一个依赖,并且告诉你原因。
  3. 从GitHub装私有仓库没认证:如果你在公司的私有GitHub上,记得先用Sys.setenv(GITHUB_PAT = "你的token")设置环境变量。remotes和devtools都能识别这个变量,但pak需要用pak::pkg_install(credentials = gitcreds::gitcreds_get())。

一句话总结:日常装包首选pak,快、稳、智能;做包开发用devtools;只装一两个远程包时,用remotes最轻便。