39

I am developing a shiny app and since I wanted to use automated testing and documentation of the function, I started to develop the interface within a package (as recommended here).

I develop this shiny app within RStudio and I have a server.R file which I can click on the Run App button within RStudio and everything works. I commit my package to a github repository and from this point I want to install it on my R shiny server using devtools and install_github function.

Now I am wondering how to start my app within the server. I was naively thinking to install the package and pointing to the server.R file, but this is somehow not working. Not sure where the problems are.

My second try was creating a file called app.R in a folder accessible by the shiny server and in this file I basically load my package, shiny and other needed packages but it somehow complains because of missing variables...

Can somebody give me an advice? I am also happy to answer any question since I am not sure how to ask for this problem properly. Thanks in advance.

EDIT Deploying to shiny server

Since Colin D was asking in the comments, how to deploy these packages on a shiny server, I wanted to demonstrate how I do this.

First of all I install my package on the shiny server directly via the command line as root with the following command.

su - -c "R -e \"devtools::install_github('user/shinypackage')\"" 

The next step is to change the owner of the package folder

chown -R shiny:shiny /usr/local/lib/R/site-library/shinypackage/

Then I restart the shiny server since this was sometimes problematic with caching or so.

systemctl restart shiny-server

These are the steps I do when I update my shiny app. I do this normally again as root in a single line

su - -c "R -e \"devtools::install_github('user/shinypackage')\"" &  chown -R shiny:shiny /usr/local/lib/R/site-library/shinypackage/ & systemctl restart shiny-server

One thing we still need to do is to setup the directory in the shiny-server.conf file. I just added the package path+the application directory where the ui.R and server.R is saved.

  location /shinypackage {
    app_dir /usr/local/lib/R/site-library/shinypackage/application;
    log_dir /var/log/shiny-server;
  }

Then I have to restart the server again by using systemctl restart shiny-server.

This is in use on a Ubuntu Server.

DeanAttali
  • 25,268
  • 10
  • 92
  • 118
drmariod
  • 11,106
  • 16
  • 64
  • 110
  • I do this as a matter of routine. I put my app files in the `inst` directory of the package and include a function called `launch_application` which merely calls `runApp` with my desired default arguments. The app files are found via `system.file` – Benjamin Jun 15 '16 at 09:20
  • Sounds like what I am looking for. What files are in the `inst` folder then? Just the call of the `launch_application` function and the `library` calls? Since I put each function in an extra file in the `R` folder, I hoped I can export them and just load my package... – drmariod Jun 15 '16 at 10:39

3 Answers3

31

There is already an accepted answer with many votes, but I'd like to add a few things, so I'll answer myself as well. For more information, you can read my article Supplementing your R package with a Shiny app.

This is the folder structure I use:

- mypacakge
  |- inst
      |- myapp
         |- ui.R
         |- server.R
  |- R
     |- runApp.R
     |- ...
  |- DESCRIPTION
  |- ...

Inside the R/ folder is where I place all the non-shiny code. The code for the shiny app itself lives in inst/. The R/runApp.R file is defined as

#' @export
runExample <- function() {
  appDir <- system.file("myapp", package = "mypackage")
  if (appDir == "") {
    stop("Could not find myapp. Try re-installing `mypackage`.", call. = FALSE)
  }

  shiny::runApp(appDir, display.mode = "normal")
}

(You can see this in action; for example, shinyalert uses this structure for its demo app).

In a comment, you asked how can this be deployed on a shiny server. It's simple, you can simply have a file /srv/shiny-server/myapp.app.R that calls and runs that package (after you've installed the package on the server):

dir <- system.file("myapp", package = "mypackage")
setwd(dir)
shiny::shinyAppDir(".")

(You can see this in action as well, code here)

DeanAttali
  • 25,268
  • 10
  • 92
  • 118
  • Hi, thanks @DeanAttali, for your code ! I have documented the file myapp/global.R. It contains all the functions used by the application. How can add them to the documentation of the package ? – Virginie Apr 23 '18 at 15:23
  • Thank you, @DeanAttali, your explanation helps me. – Camford Oxbridge Jul 02 '19 at 13:15
30

When I make shiny applications as a stand-alone package, I usually organize the files as so:

In the R directory:

  • All of my methods to support the application (these should be exported if they will be used in either the ui.R, server.R, or global.R files)
  • A launch_application function

The definition of launch_application is similar to:

launch_application <- function(x, ...)
{
  shiny::runApp(appDir = system.file("application", package = [my_pkg]),
                ...)
}

In the inst directory

  • application/server.R
  • application/ui.R
  • application/global.R

After building and installing the package, I then just need to run

library(my_pkg)
launch_application(...)
Benjamin
  • 16,897
  • 6
  • 45
  • 65
  • Ahhh, now I got it... So `server.R` and `ui.R` go into the `application` folder and only my functions staying in the `R` folder. I will give it a try though... – drmariod Jun 15 '16 at 11:56
  • 1
    Maybe one more specific question... I am using `DT::renderDataTable` in my server file. Where should I actually load the library? I was first putting `DT` as a dependency in my `DESCRIPTION` file, now, since I moved the `server.R` into the application directory, while building the package complains, I do not use all dependencies. – drmariod Jun 15 '16 at 12:54
  • 1
    List `DT` under `Suggests` and you should be fine. – Benjamin Jun 15 '16 at 12:55
  • Ok, and it took me a while to figure out that I have to set the `app_dir` in the `shiny_server.conf` to the output of `system.file('application', package='my_pkg')`... Since I was creating a file `app.R`, loading the package and using your suggestion `launch_application` function but it ended in `ERROR: Key / already in use`... Not it is working! Thanks – drmariod Jun 15 '16 at 14:22
  • 4
    How would you deploy an app with this format on shiny server? – Colin D Mar 10 '17 at 21:01
  • I've never used shiny server. So I wouldn't be able to give an informed answer. This may be a good topic to pose as a separate question. – Benjamin Mar 11 '17 at 05:29
  • @ColinD I updated my answer on how I deploy the package directly on the server. Together with a github account, this works in a single line. Write me back if you have questions – drmariod Mar 21 '17 at 07:55
  • Will this work if using app.R with combined ui and server objects, rather than separately stored in ui.R and server.R ? – RDavey Apr 15 '20 at 08:09
  • Yes. See the `appDir` argument of `?shiny::runApp` for details. – Benjamin Apr 15 '20 at 11:28
3

A lot of packages with proof-of-concept Shiny demos are not designed for deployment on Shiny Server, but instead, include something like this in a function meant to be run from RStudio:

fooRun <- function() {
   app <- shinyApp(appUI, appServer)
   runApp(app, launch.browser = TRUE, ...)
}

This function won't work in Shiny Server (you can't run runApp within runApp) but it gives some clues as to how to create an app.R that can act as a placeholder to use in /srv/shiny-server/foo/app.R

library("foo")
shinyApp(ui = foo:::appUI, server = foo:::appServer)
Jeremy Leipzig
  • 1,914
  • 3
  • 21
  • 26