Comment utiliser renv pour rendre vos applis Shiny reproductibles ?

Auteur : Charles Bordet Mise à jour : 29 Jul 2025

Jeudi dernier, je me suis lancé un petit défi perso.

La veille, on avait décidé d’ajouter une fonctionnalité importante dans un projet : Pouvoir sauvegarder et reprendre la conversation d’un chatbot codé avec ellmer.

Le challenge ? On voit le client à 10h pour un point de suivi.

Bon, pas de pression, ce n’est pas vital pour le rendez-vous, mais c’est toujours sympa de pouvoir dire « Oui, c’est déjà prêt ».

Je me chauffe, je branche Spotify, et je fonce dans le code.

J’avais déjà repéré une Merge Request toute fraîche dans le package qui faisait plus ou moins ce qu’il me fallait.

Je l’installe, je bricole, je teste… et ça marche.

Alors je commit, je pousse, la pipeline passe, et je file en visio, tout content de mon « exploit ».

Le call se passe bien, je pars faire mon sport, et je reviens l’après-midi, prêt à continuer.

Et là… message de Léo sur notre Mattermost :

Léo rapporte le bug sur notre messagerie instantanée

COMMENT ÇA ÇA MARCHE PAS ?

Je vérifie chez moi, tout roule.

« Ça marche sur ma machine », que je lui dis.

« OK, mais sur la mienne, non. »

Je commence à m’énerver, je soulève mon bureau (╯°□°)╯︵ ┻━┻, et là je réalise :

On n’a plus la même version du package ellmer.

On est exactement tombés dans le piège des gens qui n’utilisent pas renv. Dans mon rush, j’avais oublié la mini étape de mettre à jour le renv.lock.

Résultat : chez moi ça marche, mais chez Léo, rien ne passe.

Comment ça, la même chose vous est déjà arrivé ? Et vous n’utilisez pas renv ??

Ou alors, vous l’avez déjà installé mais vous ne savez pas trop à quoi il sert, ni comment l’utiliser au quotidien ?

Bon, OK, c’est justement le sujet de cet article. On va voir :

  • Pourquoi renv est indispensable pour tout projet R un minimum sérieux (et pas seulement en équipe)
  • Comment il fonctionne concrètement
  • Et comment résoudre tous les problèmes que vous pourriez avoir avec

C’est parti !

À quoi ça sert renv ?

Avoir les mêmes versions des packages sur tous vos environnements

C’est LA base.

renv permet de garantir que tout le monde travaille avec exactement les mêmes versions de packages : vous, vos collègues, la machine de prod, la machine de test, etc.

Concrètement, ça veut dire quoi ?

  • Plus de « ça marche sur ma machine » (mais pas sur celle du voisin)
  • Sur l’onboarding d’un nouveau collègue, il a juste à cloner le dépôt de code, lancer renv::restore(), et c’est tout. Il a exactement le même environnement que tout le monde, sans prise de tête
  • Pour le déploiement en prod, même chose : le code tournera exactement de la même manière qu’en local
  • Et surtout, pour de l’ancien code, qu’il soit vieux de 6 mois ou 6 ans, vous repartez d’exactement le même endroit qu’il y a 6 ans.

Bref : On élimine tous les bugs invisibles qui nous font perdre des heures et qui sont bêtement liés à des différences de versions de packages.

Utiliser des versions différentes selon vos projets

Sur une machine, tous les projets R partagent le même ensemble de packages par défaut.

C’est pratique… jusqu’au jour où c’est pas pratique. Vous mettez à jour un package pour un projet, et ça casse un autre projet à côté.

Chez nous à Data Champ’, on travaille sur des dizaines de projets en parallèle toute l’année. Ce serait impossible de retester toutes les applis dès qu’on met à jour un package.

Avec renv, chaque projet a son propre environnement isolé :

  • On peut bosser sur un vieux projet qui tourne avec R 3.6.3 et les packages d’époque, tout en profitant des dernières versions sur les autres projets.
  • On évite les conflits entre projets. On n’a pas toujours le luxe de choisir de travailler avec la dernière version de R et des packages.
  • Pour n’importe quel projet, on sait qu’on a juste à le cloner, à restaurer l’environnement, et on est sûr que tout fonctionnera comme prévu.

Ce n’est même pas une question d’être en équipe. C’est un outil de productivité qui facilite la vie en général pour tous les utilisateurs de R.

Et en plus, c’est très simple à utiliser !

Comment utiliser renv ?

Il y a trois verbes fondamentaux à connaître. C’est tout.

Initialiser renv avec renv::init()

Quand un client m’envoie le code d’un projet, c’est la toute première chose que je fais.

Si le projet est un package, alors renv vous propose d’utiliser le fichier DESCRIPTION pour installer les packages.

> renv::init()
This project contains a DESCRIPTION file.
Which files should renv use for dependency discovery in this project? 

1: Use only the DESCRIPTION file. (explicit mode)
2: Use all files in this project. (implicit mode)

Selection:

Nous on utilise rarement une structure de package pour nos applis Shiny, et en plus rien ne nous dit que le fichier DESCRIPTION est bien à jour, donc j’ai plutôt envie de privilégier l’option 2 (mode implicite).

L’option 2 va scanner l’ensemble des fichiers du projets, et détecter automatiquement tous les packages utilisés :

  • Quand vous utilisez library(package)
  • Ou bien l’écriture package::function_name()

Les packages vont ensuite être téléchargés, et installés, automatiquement. Vous n’avez rien à faire de plus.

Un message de succès va s’afficher :

The version of R recorded in the lockfile will be updated:
- R                    [* -> 4.4.3]

- Lockfile written to "~/path/renv.lock".
- renv activated -- please restart the R session.

Deux informations sont importantes ici :

  • renv a enregistré la version de R utilisée (la 4.4.3)
  • renv vous informe qu’il faut redémarrer la session R. C’est nécessaire après l’activation de renv.

Lors de son initialisation, renv a ajouté quelques fichiers dans votre environnement :

  • Le fichier renv.lock est le plus important. Il contient la liste exhaustive de tous les packages nécessaires à votre code et les versions utilisées.
  • Une ligne dans le fichier .Rprofile (qu’il crée s’il n’existe pas) permettant d’activer renv automatiquement au démarrage de la session.
  • Le dossier renv contient des fichiers techniques et les packages installés. Il contient aussi un fichier .gitignore qui exclut automatiquement ce qu’il faut.

Il n’est pas nécessaire de rajouter le dossier renv dans le .gitignore. Vous n’avez rien à faire de spécial à ce niveau.

Tout ce qui vous avez à faire est de lancer renv::init(), c’est tout.

Sauvegarder les nouveaux packages avec renv::snapshot()

Au fil de votre développement, vous allez rajouter ou enlever des dépendances à certains packages. Ou bien vous pouvez aussi décider de mettre à jour certains packages.

Dans ce cas, pour que l’information du nouveau package soit bien enregistrée, il faut utiliser la commande renv::snapshot()

renv va vous présenter les changements qui vont avoir lieu :

  • Les packages ajoutés
  • Les packages dont la version change
  • Les packages enlevés
> renv::snapshot()
The following package(s) will be updated in the lockfile:

# CRAN -----------------------------------------------------------------------
- anytime           [0.3.9 -> *]
- BH                [1.81.0-1 -> *]
- bookdown          [0.36 -> 0.43]
- brio              [1.1.3 -> 1.1.5]
...
- xfun              [0.41 -> 0.52]
- XML               [3.99-0.15 -> 3.99-0.18]
- zip               [2.3.0 -> 2.3.3]
- textshaping       [* -> 1.0.1]

Do you want to proceed? [Y/n]:

Une fois que vous validez, le fichier renv.lock est mis à jour. Il peut alors être ajouté dans un commit pour que les collègues le récupèrent.

C’est exactement cette étape que j’avais oublié dans mon histoire en début d’article !

Et du coup, comment ils font les collègues pour installer les packages ?

Restaurer l’environnement avec renv::restore()

Lorsque vous récupérez un projet qui utilise renv, il va s’activer tout seul dès le lancement de la session :

# Bootstrapping renv 1.1.4 ---------------------------------------------------
- Downloading renv ... OK
- Installing renv  ... OK

ℹ Using R 4.4.3 (lockfile was generated with R 4.1.2)
- Project '~/path' loaded. [renv 1.1.4]
- One or more packages recorded in the lockfile are not installed.
- Use `renv::status()` for more details.
R version 4.4.3 (2025-02-28) -- "Trophy Case"
Platform: x86_64-pc-linux-gnu (64-bit)

Plusieurs informations importantes sont affichées ici :

  • Il a automatiquement installé renv en version 1.1.4. Très bien.
  • On m’informe que j’utilise R 4.4.3 alors que le lockfile (c’est-à-dire le fichier renv.lock) a été généré avec R 4.1.2. Là j’ai un problème, puisque je n’ai pas la bonne version de R.
  • On me dit aussi que certains packages enregistrés dans le lockfile ne sont pas installés. C’est normal, puisque je viens juste de lancer le projet.
  • Finalement, on m’invite à lancer renv::status() pour en savoir plus.

Je relance le projet avec la bonne version de R cette fois-ci, puis je lance un renv::status() :

> renv::status()
The following package(s) are in an inconsistent state:

 package         installed recorded used
 anytime         n         y        ?   
 AsioHeaders     n         y        ?   
 askpass         n         y        ?   
 backports       n         y        ?   
 ...
 xtable          n         y        ?   
 yaml            n         y        ?   
 zip             n         y        ?   
 zoo             n         y        ?   

See `?renv::status` for advice on resolving these issues.

Le renv::status() m’affiche la liste des packages “problématiques” avec trois colonnes :

  • Le package est-il installé ?
  • Le package est-il sauvegardé dans le lockfile ?
  • Le package est-il utilisé dans le projet ?

Dans mon cas ici, je restaure un projet. Donc tous les projets sont sauvegardés dans le lockfile et ne sont pas installés.

Pour les installer, rien de plus simple : renv::restore()

Mettre à jour tous les packages avec renv::update()

Dernière petite astuce. Si vous avez lu notre article « Quelle version de R faut-il utiliser en production ? », vous savez que c’est pas mal de régulièrement mettre à jour les packages. Disons une fois par an ou tous les deux ans.

Rien de plus simple : renv::update().

C’est tout.

La documentation

Cet article ne traite que d’un usage basique du package renv (et honnêtement il n’y a pas grand chose de plus à savoir pour 99% du temps).

Si jamais vous avez besoin de creuser davantage, la documentation est par ici : Introduction to renv

Les problèmes et les solutions aux problèmes

renv est vraiment un super outil.

Mais… il faut croire que gérer des arbres de dépendances dans tous les sens, ce n’est pas si évident.

Au-delà de la simplicité apparente des trois fonctions basiques pour un usage quotidien, vous risquez parfois de vous retrouver dans des situations un peu complexes.

C’est pourquoi j’ai rajouté cette section, avec tous les problèmes que j’ai moi-même rencontrés. J’entends enrichir cette section au fil des nouveaux problèmes qui apparaissent.

Et si vous-même avez un problème qui n’est pas traité ici, on se retrouve en bas dans la section Commentaires.

J’ai installé un package et renv ne l’inclut pas dans le renv.lock

Vous avez fait :

  • install.packages("packagename")
  • Puis : renv::snapshot()

Et renv ne vous propose pas de rajouter packagename dans le lockfile.

C’est normal : renv n’enregistre pas TOUS les packages que vous installez. Il enregistre seulement les packages qui sont utilisés dans l’application.

Donc si vous installez microbenchmark pour vous aider à optimiser vos traitements de calcul, le package ne va pas être ajouté.

C’est une bonne chose : Inutile de surcharger les environnements de vos collègues ou en production avec des packages non utilisés.

Et si vous voulez VRAIMENT imposer à renv d’ajouter le package ?

Alors je vous conseille de le faire de cette manière :

if (FALSE) library(microbenchmark) # Necessary to add in renv.lock

Le simple fait d’avoir écrit library(microbenchmark) suffit à renv pour inclure le package.

Mais : Le package n’est jamais chargé. Vous économisez ces précieuses millisecondes de chargement.

Et le commentaire est utile pour vos collègues qui ne comprendront peut-être pas pourquoi cette ligne existe et pourraient être tentés de la supprimer.

Les packages utilisés dans mes fichiers R Markdown ne sont pas détectés

Ce problème survient si le package yaml n’est pas installé. D’ailleurs, vous avez peut-être reçu le warning suivant :

Warning message:
The 'yaml' package is required to parse dependencies within R Markdown files
Consider installing it with `install.packages("yaml")`.

Dans ce cas, installez le package yaml.

Erreur : package ‘name’ is not available

En général, cette erreur survient lors d’un renv::init(). Votre code utilise certains packages que renv ne sait pas où aller chercher parce qu’ils ne sont pas sur le CRAN.

J’ai par exemple eu le cas avec le package polars, qui est accessible depuis le R-multiverse :

The following package(s) were not installed successfully:
- [polars]: package 'polars' is not available

Dans ce cas, installez le package depuis la source où il est accessible, en général Github ou un autre repository que le CRAN.

Commentaires

Laisser un commentaire

Les champs obligatoires sont marqués d'un astérisque *

Markdown accepté

Les commentaires sont validés manuellement.
La page va se rafraîchir après envoi.