Dash avec golem : premier contact

dash-with-golem_header
Author : Sébastien Rochette
Tags : développement, docker, package, serveur, shiny, thinkrverse
Date :

{golem} a été développé pour aider à construire de grosses applications Shiny à mettre en production. Et si {golem} pouvait être utilisé pour construire une autre application web interactive populaire, récemment mise à la disposition des programmeurs R : Dash?

Dash, un nouveau venu dans les applications web interactives

Il y a quelques jours, Plotly a annoncé que Dash était maintenant disponible pour R. Après avoir lu cette annonce, j’ai trouvé que c’était une belle alternative aux populaires applications Shiny ! Mais ensuite, je me suis souvenu que nous venions juste de commencer notre communication à propos de {golem} et de toutes nos ressources pour mettre en production des applications Shiny.

Et la panique est montée en moi !

Que se passerait-il si, pendant nos vacances d’été, tous les utilisateurs de R décidaient de passer à Dash ? Est-ce que tout notre travail avec Shiny et {golem} serait perdu ? Comment l’équipe ThinkR réagirait-elle à cette catastrophe après deux semaines de bronzage au soleil ?

Pour quitter la maison dans de bonnes conditions, j’ai pris une heure pour regarder Dash. Dans cet article, j’expliquerai brièvement pourquoi je suis parti en toute confiance…
Par ailleurs, {golem} a finalement atteint le CRAN pendant nos vacances ! Une bonne nouvelle a fêter avec Dash!

Dash est similaire à Shiny

Je n’ai pas eu à passer beaucoup de temps à passer pour comprendre l’architecture de Dash et implémenter le premier exemple. En effet, bien qu’il soit construit comme un objet R6, la construction d’une application Dash est proche d’une application Shiny.

  • Une partie du code pour construire l’interface utilisateur, appelée layout.
  • Une partie pour déclencher des mises à jour de l’interface utilisateur, appelée callback.

Ce qui est intéressant, c’est que, comme tout autre code R, tout peut être une fonction. Et, comme nous avons l’habitude de dire, dès que vous écrivez une fonction, vous devriez construire un package R, de sorte que vous êtes obligé de documenter et de tester votre travail. Si vous avez besoin d’en savoir plus sur cette façon de penser, vous pouvez lire notre article “Rmd first : When development starts with documentation”.

{golem} entre en jeu pour déployer Dash

{golem} a été conçu pour vous aider à construire, documenter et déployer une application interactive divisée en deux parties : l’interface utilisateur et le serveur. Nous recommandons l’utilisation de modules Shiny pour séparer les différentes parties de l’application et faciliter le développement.
Avec Dash, il est également recommandé de séparer votre application en plusieurs fonctions pour les mêmes raisons. Bien sûr, ça ne fonctionne pas exactement de la même manière que Shiny, mais ici, seule l’architecture est intéressante.

J’ai construit le premier exemple de Dash en utilisant {golem} : cette app est disponible sur github sous le nom de package : {appwithdash}. Vous pouvez vous référer à l’historique des commit pour voir les différentes modifications du code {golem} comme expliqué ci-dessous. Bien sûr, vous devrez d’abord installer les paquets Dash.

Créer un golem pour {Dash}

Testé uniquement sur Ubuntu 18.04 LTS.

  • Créer un golem: golem::create_golem(path = "appwithdash")
  • Retirer les appels à @import shiny dans app_ui et app_server
  • Modifier run_app ainsi :
run_app <- function() {
  # Packages need to be loaded for Dash to work
  # Imports is not enough, maybe Depends would be good.
  library(dash)
  library(dashCoreComponents)
  library(dashHtmlComponents)
  # Init app
  app <- Dash$new()
  # UI
  app$layout(app_ui())
  # Callback
  # app$callback(app_server())
  # Use host 0.0.0.0 to embed in Docker later
  app$run_server(host = "0.0.0.0", port = 8050, block = TRUE, showcase = FALSE)
}
  • Remplir la fonction app_ui avec l’example de layout de Plotly: https://dashr.plot.ly/getting-started
  • Documenter son package avec {attachment}: attachment::att_to_description()
  • Charger votre golem avec {golem}: golem::document_and_reload()
  • Lancer l’app: appwithdash::run_app()
    • Avec l’option showcase = FALSE, vous devrez ouvrir votre navigateur manuellement : browseURL("http://localhost:8050")

🎉

dash-with-golem-deploy

Je n’ai pas essayé d’ajouter les callback ici, mais je suppose que ça devrait fonctionner avec la bonne fonction app_server.

Déployer Dash dans un docker

Si vous nous suivez attentivement, vous savez que nous aimons déployer nos applications avec Docker. Nous aimons aussi jouer avec Rstudio Connect, mais dans le cas de Dash, comme il vient avec son propre mode de déploiement avec Fiery, il y a conflit.

Pour créer le bon Dockerfile à déployer, {golem} nous aide avec golem::add_dockerfile(). Vous devrez modifier les couches pour télécharger les packages Dash et exposer le bon port. De plus, le Dockerfile créé avec {golem} suppose que vous avez construit votre golem avant de construire le conteneur Docker.
Le code ci-dessous vous guidera :

# Build your golem inside your package and hide ----
devtools::build(path = ".")
usethis::use_build_ignore(".*\.tar\.gz$", escape = FALSE)
usethis::use_git_ignore("*.tar.gz")
  
# Add golem Dockerfile skeleton ---
golem::add_dockerfile()
# Modify dockerfile to include 'remotes::install_github("plotly/dashR")'
# Modify dockerfile to expose to EXPOSE 8050
  
# Build docker ----
system("docker build -t appwithdash .")
  
# Run docker ----
# future allows to keep the R console free
library(future)
plan(multisession)
future({
  system(paste0("docker run --rm --name app -p 8050:8050 appwithdash"), intern = TRUE)
})
browseURL("http://127.0.0.1:8050")
  
# Stop docker ----
system("docker kill app")
system("docker rm app")

Jouer avec Dash et {golem}…

Maintenant, si vous voulez tester Dash pour R, vous pouvez essayer avec {golem} pour vous aider à construire la structure de base. Au moins, ça vous conduira dans la direction d’applications documentées et testées. Cela dit, je ne peux pas vous assurer que toute autre fonction de {golem} fonctionnera avec Dash, car {golem} a été conçu pour fonctionner avec Shiny. De même, je ne peux pas promettre que Dash sera entièrement supporté par {golem}, mais nous garderons un oeil dessus et verrons s’il y a besoin d’un package différent ou de quelques ajustements seulement.


Comments


Also read