Plug for my forecasting project:
If you’d like to show some support, check out my forecasting platform on www.forecastmarket.co and spread the word to those that may be interested in this service. I will be writing a new document soon about how I deployed those forecasting models as API’s in the cloud.
What Will Be Covered:
- What is Shiny and what are the deployment options
- When you might want standalone desktop deployment
- Options for desktop deployment
- How-to example: package a Shiny app into a desktop executable
- With special attention to problems I faced and how I solved them
- Known issues and solutions
This article assumes the reader is comfortable navigating R and developing Shiny apps as well as some familiarity with using command line. While it is not impossible to follow these directions without these prerequisites, I expect a reader meeting these criteria will have an easier time. If your interest is less on the technical side there may still be some points that interest you such as considerations for cost, ease of use (friction), and data privacy.
What is Shiny and What Are the Deployment Options:
Shiny is the framework for deploying applications using R programming. These applications could range from a static dashboard to display an analysis to an interactive application that takes user input to build models and provide dynamic actionable predictions for the user. Shiny apps can be one page or multiple pages with each page having the option for different layouts with options for tables, graphs, text, images, and maps. A great resource to gather Shiny app ideas from is https://shiny.rstudio.com/gallery/. To see some of the apps I’ve made (due for an update) you can look at https://foretodata.com/example-of-apps/.
The common options for deploying Shiny apps are either locally through R or on the Shiny server. When it comes to deploying these Shiny apps, you must consider the end-user. If you deploy it locally without making it a desktop app, this means the user will need to be comfortable and willing to download R and RStudio, load the proper packages with correct versioning, and run the app script. If you are both the creator and end-user of the app, this means you will be comfortable or at least capable of completing these necessary steps EACH time you use the app. However, if the end-user is not accustomed to these steps, this adds friction, which can deter the user. The other common option is to deploy the shiny app on a server, the most convenient server is the Shiny server https://www.shinyapps.io/ which you can deploy to directly from RStudio. This option has a free level and paid tiers that grant higher usage allowances, total apps deployed, and can even have a sign in to allow some degree of security for the apps. The free level has a max of 5 apps and 25 active user hours per month.
Regarding server deployment, there are other options, including deploying to cloud services other than the shiny server like this example with AWS or the open-source shinyproxy using Docker containerization. Each of these options comes with additional trouble-shooting or necessary skills to get the app into production. I’m sure this is not an exhaustive list, but it shows there are server alternatives outside of RStudio related options.
When You Might Want a Standalone Desktop Deployment:
One of the major motivators for making a standalone desktop app is maintaining privacy of the code and/or data necessary to make the app. This may be sensitive medical data, financial data from a company, or data or code that provides a competitive advantage. In addition to the privacy advantage of making a standalone app, another major advantage is the ease of use (like deployment on a server) where the user just needs to point and click to get it running. There may also be cost advantages if you distribute the packaged desktop app compared to hosting the app on a paid level server.
Options for Desktop Deployment:
There are a few different options for packaging Shiny apps into standalone desktop applications. The one I will give a “how-to” on is the method championed by Columbus Collaboratory now rebranded as Covail which has an accompanying talk by Katie Sasso. Other options include RInno, Travis Hinkelman’s work using Electron Template for R on Mac, and the methods used in this blog & this one. The point of this “how-to” is to expand upon some of the basic instructions and make clear some of the areas that were a hang-up for me, in hopes it can save others some time.
How-To Example: Package a Shiny App into a Desktop Executable
Step 1: Download Git CMD
Navigate to https://git-scm.com/downloads and download the windows version of git.
Step 2: Open the Columbus Collaboratory GitHub Repository
Navigate to https://github.com/ColumbusCollaboratory/electron-quick-start which is where we will follow commands from
Step 3: Download Node.js
This was one part that took a little time for me to figure out. I made an account with npm thinking this was necessary and then searched for how to download node.js from there. This is not necessary. Go directly to https://nodejs.org/en/download/ and download the windows version.
Step 4: Open Git Bash or Git Command
If you successfully completed Step 1 you should be able to navigate to Git CMD or Git Bash using your desktop search bar.
Step 5: Follow the First Command
One thing to consider before executing this command is what directory you are in. You will likely start in User/YourName. You may want to navigate to your Desktop directory using “cd Desktop” before running command below to make your work more easily accessible.
git clone https://github.com/ColumbusCollaboratory/electron-quick-start
This will result in the Columbus Collab directory being cloned to the directory you passed the above command from. It should be a folder.
Step 6: Install Electron Packager
Since you are following this tutorial, I am assuming this may be your first time using this approach. In this case, you will need to run the command below. Each time you clone the GitHub directory to a new file you will also need to run this command.
npm install electron-packager -g
Step 7: Navigate to electron-quick-start
Step 8: Install Dependencies
Step 9: Set Up the Environment
This is the penultimate step to packaging your Shiny app into a desktop executable. At this point you will want to consider what your environment needs. Does your Shiny app need certain csv files that it will call for data? What about the packages it will use? Those need to be installed as well. And what about your Shiny app.r file itself? You will need to replace the default app.r file that is in the directory.
Step 9.1: Import Necessary Data/Other
Anything your shiny app needs to run through such as a csv, will also need to be in the same directory as your app.r file in the electron-quick-start folder
Step 9.2: Replace the Default app.r File (Optional)
If you wish to use your custom Shiny App you may now replace the default app.r (old faithful geyser data) in the electron-quick-start directory with your desired Shiny app.r.
Step 9.3: Install Required Packages
This is a very important step as your app will not run if you do not install the correct packages to be packaged in the desktop app. To install packages, navigate to “R-Portable-Win” and then to “bin” and then click “R.exe”. This will bring up a command line interface which you can use to install the necessary packages using the regular install.packages() function or other alternatives.
Step 10: Bundle Your Desktop App
Run the following in the Git CMD or bash.
npm run package-win
Step 11: Run Your App
The packaged app will be added to a folder in electron-quick-start directory. Simply navigate through that new folder until you find electron-quick-start.exe. Double click the .exe file and it will open your app. If the screen is blank, click “View” and “Force Reload”. If this solution doesn’t fix the blank screen, something is likely missing earlier in the process which you will need to fix.
Known Problems and Solutions:
Blank White Screen
If you try to open the app and the electron window starts up but remains blank for longer than you would expect, you may need to hit “View” and then “force reload”.
This should only happen if you have more than one of these desktop electron apps on your desktop. If you pull up one app and get the screen of another that means that process is still running in the background and needs to be shut down manually. To do this, navigate to the task manager and close down the electron-quick-start app. Even if you close the window you may still need to do this step.
The packaged .exe will be large and when you consider the other resource files, the app can get up into the GB range. You may decrease the size by navigating to the library and deleting unnecessary packages before packaging the app. You may also zip the folder containing the app before transferring it.
If at any point in the process a warning prompts you to “npm audit” arises, I would advise following it. It is a quick way to make sure all the dependencies are squared away.
Are there any conventions on folder where extra .csv files or other data files go or do you just keep everything in the same location as app.R?
You can choose to have everything in the same directory as the app.r or add new folders with deeper directories as long as they originate from the same directory as app.r.
Thanks for this post. It worked for me. The problem is that my app.R still needs to be present in the electron directory for the .exe file to function. Meaning that If I’d like to share my .exe file, I have to share all the electron folder, including the app.R file. So no way to make code privacy like you said in the beginning of this post.
Hi Bervelin, the code and any other parts (data for example) are private to the end user was what I intended to convey. Since I’ve posted this I’ve seen some other interesting approaches to hosting shiny apps you might google, including on AWS. I think the AWS approach might better protect your code in the way you desire but it also will cost you money the same way shinyapps.io will. Both of these would also require the end-user being ok with the code and data being outside of their network and security, which is one of the things the electron+shiny combination avoids.