Dependency management

TipLearning Objective

Use {renv} to record current package versions to ensure the environment is reproducible, portable and isolated

{renv} helps us create more reproducible and shareable projects by allowing us to run the same versions of R packages on different machines, across time, and by different people. It takes the packages used in your project and records their versions in a file that you can update as you develop the project. When you come back to your project, or share it with someone else, it ensures they are using the same versions of packages and R that you were.

The main functions used when working with {renv} are:

  • init() for setting up project to use {renv} for the first time

  • snapshot() for recording versions of packages currently installed in the project in the lockfile

  • restore() for restoring a project’s package versions to match the versions recorded by {renv} from the lockfile

  • status() for checking the status of a project, ensuring that the packages installed correspond to the lockfile in the project

Note: {renv} will not install a different version of R, or any other system dependencies that are required. However, {renv} will warn if the renv.lock lists a version of R that differs from your current version of R. You can however use the function sysreqs() to return an estimate of the system requirements for your machine, that you can install before the R packages. If you run a supported version of Linux, check out the {pak} vignette on system requirements.

Setup

The first time you set up a project with {renv}, use the function init(). init() writes a file to the root of your project called renv.lock that tracks the versions and dependencies of R packages installed and the version of R itself. This is a simple text file, so feel free to open it up (but don’t edit) in a text editor. It also edits the project specific .Rprofile to ensure that {renv} is loaded when the project is opened.

Warning

renv::use() does not initiate an {renv} file. It is used only in very specific circumstances (read more here). To start using {renv} in a project, use the function renv::init().

Exercise: setting up {renv}

Instruction: in the console of your project, initialize {renv} with init().

Application

As you work on your project and add or update packages, record your packages used and their version with snapshot(). This will edit the renv.lock file with new versions and packages that describe the package’s environment.

You can always check the status of your {renv} project with status() to see which packages are installed but not recorded, or which packages are recorded but no longer used.

If you have a one-off package that you want to add to the lockfile so that you can continue working, record() is a useful function. It can change the lockfile, i.e., add or update a package, for one (or more) package at a time.

Exercise: using {renv}

Instruction: install a new package with install.packages() then run status(). Follow {renv}’s recommendations to either save (snapshot()) or discard (restore()) these potential changes to your project’s environment.

Sharing

snapshot() is used to save the current state of your project while restore() to recover the state of your project as it was last saved. When you download someone else’s project, you can use restore() to retrieve and install the versions of packages in the project that were recorded.

Before sharing your project (and regularly while you work even if not sharing), make sure your project is up to date by running snapshot().

To restore from an renv.lock file, simply run restore().

At times, {renv} can be difficult to use. Especially with an ongoing project, {renv} can feel like it is slowing you down and making things more confusing, instead of increasing transparency.

One option to address {renv} issues is deactivating (deactivate()) while actively working on a project, then activating (activate()) when you are ready to share and have your dependencies recorded.

Alternatives

pak is a very powerful package installer has many of the same capabilities as {renv}.

You can create a lockfile that records the installed packages using pak::lockfile_create() and install packages later using pak::lockfile_install().

pak can be configured with {renv} to have fast package installation and clear management (documentation).

Bonus

Git is really helpful when working with {renv} because we can track the renv.lock file’s history for changes through time. See these examples:

Use renv::update() to update the packages in your lock file.

You can also use {renv} to track Python dependencies required by your project too. See this vignette for more details: https://rstudio.github.io/renv/articles/python.html