Dash with golem: First contact

dash-with-golem_header
Author : Sébastien Rochette
Categories : development, docker, package, server, shiny
Tags : dash, golem
Date :

{golem} has been developed to help building big Shiny application to put in production. What if {golem} could be used to build another popular interactive web application, recently made available to R programmers: Dash ?

Dash, a newcomer in interactive web applications

A few days ago, Plotly announced Dash now available for R. After reading this announcement, I thought this looked like a nice alternative to the popular Shiny applications ! But then, I remembered that we just started our communication about {golem} and all our resources to put big Shiny Application in production.

And the panic went up in me!

What if, during our Summer break, every R user decided to switch to Dash ? Would all our work with Shiny and {golem} be lost ? How would the ThinkR team react to this disaster after two weeks of sunbathing ?

To leave home in good conditions, I took an hour to look at Dash. In this blog post, I will briefly explain why I left with confidence…
Moreover {golem} finally reached the CRAN during our holiday! What a good news to enjoy with Dash!

Dash is similar to Shiny

I did not have a long time to spend to understand the architecture of Dash and implement the first example. Indeed, although it is built as an R6 object, the construction of a Dash application is close to a Shiny application.

  • A part of the code to build the UI, called layout
  • A part to trigger UI updates, called callback

The interesting thing is that, like any other R code, everything can be a function. And, as we use to say, as soon as you write a function, you should build a R package, so that you are forced to document and test your work. If you need to know more about this way of thinking, you can read our article “Rmd first : Quand le developpement commence par la documentation”.

Here comes {golem} to deploy Dash

{golem} has been designed to help you build, document and deploy an interactive application divided in two parts: the UI and the server. We recommend the use of Shiny modules to separate the different parts of the application and ease the development.
With Dash, it is also recommended to separate your application into multiple functions for the same reasons. Of course, this does not work exactly in the same way than Shiny, but here, only the architecture is of interest.

I built the first example of Dash using {golem}: this is available on github under {appwithdash} package name. You may refer to the commit history to see the different modifications of {golem} code as explained below. Of course, you will first have to install Dash packages.

Create a golem for {Dash}

This was only tested on Ubuntu 18.04 LTS.

  • Create a golem: golem::create_golem(path = "appwithdash")
  • Remove all calls to @import shiny in app_ui and app_server
  • Modify run_app as follows:
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)
}
  • Fill app_ui function with the example app: https://dashr.plot.ly/getting-started
  • Document your package with {attachment}: attachment::att_to_description()
  • Load your golem with {golem}: golem::document_and_reload()
  • Run the app: appwithdash::run_app()
    • With option showcase = FALSE, you will have to open your browser manually: browseURL("http://localhost:8050")

🎉

dash-with-golem-deploy

 

I did not try to add callbacks here, but I assume that this should work with the correct app_server() function.

Deploy Dash inside a Docker

If you follow us carefully, you know that we like to deploy our applications using Docker. We also like to play with Rstudio Connect, but in the case of Dash, as it comes with its own deployment way using Fiery, there is a conflict.

To create the correct Dockerfile to be deployed, {golem} helps us with golem::add_dockerfile(). You will have to modify layers to download Dash packages and also expose the correct port. Moreover, the Dockerfile created with {golem} assumes you built your golem before building the Docker container.
The code below will guide you:

# 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")

Play with Dash and {golem}…

Now, if you want to test Dash for R, you can try with {golem} to help you build the raw structure. At least, this will drive you in the direction of documented and tested deployed applications. That being said, I cannot assure you that any other {golem} function will work with Dash, as {golem} has been designed to work with Shiny. Also, I cannot promise that Dash will be fully supported by {golem}, but we will keep an eye on it and see if it needs a different package or only a few tweaks.


Comments


Also read