Resources

{shinylive}: Serverless Shiny Apps | Barret Schloerke | Posit

In the rapidly evolving landscape of web technologies, the integration of R (and Python) with modern web frameworks has become increasingly important for data scientists and developers. This presentation introduces {shinylive}, a new R package that exports Shiny applications to be run within statically hosted websites. We will explore the capabilities of {shinylive} through its use of the innovative R package {webR}, which allows for the execution of R code in the browser (via WebAssembly and service workers) without the need for a centralized server. The presentation will cover the technical foundation of {shinylive}, including its architecture and the integration process with Quarto documents. We will also discuss the practical aspects and drawbacks of exporting Shiny apps with {shinylive}, highlighting the ease of exporting apps to a folder for local use or hosting them on GitHub pages. {shinylive} bridges the gap between Shiny and static websites, making it a valuable resource for interactive data analysis and presentation. Link to app: https://schloerke.com/presentation-2024-04-18-appsilon-shinylive/ Link to script: https://github.com/posit-dev/r-shinylive/blob/main/examples/deploy-app.yaml Link to use_github_action(): https://github.com/posit-dev/r-shinylive#github-pages Shinylive website: https://posit-dev.github.io/r-shinylive/ {webr} docs: https://docs.r-wasm.org/webr/latest/

image: thumbnail.jpg

Transcript#

This transcript was generated automatically and may contain errors.

Hi, my name is Barret Schloerke, and I'm a software engineer at Posit, and I work on the Shiny team. And today, we're going to talk about shinylive, and what it can do for you by making serverless Shiny applications. Sounds odd, but it's pretty exciting when it's in practice.

What is shinylive?

So what is shinylive? When we do our typical Shiny deployment, we have one centralized server, or many centralized servers, but we have a server that is detached from the user's computers. And this is where all your beef of your server computations are done, and it makes it so that you can have your secrets for your databases and everything like that. And then the user just gets this very thin UI within their browser.

But shinylive kind of flips that up on its head and says, hey, I actually want to take this computation, and I want to distribute it to all of the users so that I don't have a centralized server. But instead, I send R, and I send the computations to the server's browser. And then it runs within their own machine on their own compute cycles, and they can look at all of the code within the app there.

First off, saying this makes it seem like it's pretty trivial to do, but there's been years of work been done to try to make this possible to even allow R to run in the browser. If I would have told myself 10 years ago that R could run in the browser, I would have laughed at you, and I still laugh because it's a crazy idea that just happens to work today.

If I would have told myself 10 years ago that R could run in the browser, I would have laughed at you, and I still laugh because it's a crazy idea that just happens to work today.

And now, since R is within each user's browser, we don't need that centralized server. It is now distributed and infinitely horizontally scalable as long as you can send out the static resources.

Live demo

So let's check this out. Let's look at our old faithful from Shiny that has been updated. Let me refresh this here, even though I'm supposed to say, hey, demo, don't do anything live. But this is actually going to refresh, download R, download all the things and get everything ready to go.

And we have our old faithful app. We have a title in this, Hello Shiny, and the number of bins is 30. And then we have our plot that is done by base R graphics. So it's not something that you can fake. We'll change the bins and it quickly updates the plot.

And I know it's hard to say like, oh, look at my servers. You know, I'm not doing something underneath the hood. This is under my own personal website and I'm an open source engineer. Like, I don't want to pay for anything if I don't have to. So all you can do is take my word for it that this is running live without opening up the console. But it's too hard to see on demo.

How it works: the export function

So how is this done? This is done by the export function within the r-shinylive R package. All you need to do is provide it your Shiny app folder and we will look around to find your app.R or UI.R server R or any combination that you have. We will then export this to a WebR Shiny app folder. It's something that's not an app.R folder, but or a folder that contains your app.R, but instead it's something that is exported using WebR and is ready to be hosted.

And this is the requirement is that the exported folder must be hosted due to some security requirements done by the WebR interactions, which is underneath the hood of running R within your browser. We're kind of right now in the situation of, well, if I can host a folder, I can host a Shiny application, but we wouldn't want to host it on our own personal machine because, you know, I want to put my machine to sleep. You can't visit my personal machine's web address easily. We would like it to be somewhere.

Deploying with GitHub Pages and GitHub Actions

And so this is where I get really excited because GitHub and GitHub actions have done a wonderful part for the open source community where your code is publicly available. So GitHub, along with GitHub pages, hosts your static websites and WebR is our static asset. So this is this works out really well.

We can use a GitHub action also, which is free for public repos. So we haven't had to pay anything yet. And using GitHub actions, we can run some sort of commit our shinylive export command on every commit. And then once we've exported it, we can then upload that bundle to our website.

And to do so, just make sure that you open up the settings within your website of settings, pages, build and deployment underneath source and GitHub actions. This location may change tomorrow, but at least that's where it is as of this recording.

And I know I kind of blazed through that, but I just want to kind of reiterate what we've done. So for every commit that you do to a GitHub repo, you can have GitHub actions run in the background to do some work on your repo. It'll take your repo, check it out. It will then run shinylive export. It'll then save that to a folder, will then take that folder and then upload it for our website to GitHub pages. And this is all done for free as long as your repo is public.

So let's look at what that action file will look like. So there we have this GitHub actions workflow. I would just call it, you know, deploy our app to GitHub pages and it runs on push to main or any other pull request. And then we have a job that we call shinylive that uses a workflow that we have said Hey, I will take your app dot R and I will a folder or your repo that, you know, is a shiny app. And then I will turn it into your GitHub website.

This way is, you know, as we're rapidly making developments within shinylive, that contract will try to be maintained. And then that makes it so that you don't have to update all of your shiny apps moving forward. We just have one location that we need to install. There are some permissions that you need to enable that we've added comments to, which is pages right and ID token right. This is required to publish the results to your website so that the proper permissions are there, which are off by default.

To simplify all of this, there is a single command that you can run within your repo so that you can get that GitHub action. You can use the use this package and execute, use this GitHub action with the URL here, you can get this on the r-shinylive GitHub repo page and links will be below.

The no-secrets trade-off

So everything is all better. Everything's free now. We don't need to pay for anything. Right. Like that's that's what happens now. Moving forward. Unfortunately, Gandalf wants you to keep it secret and he wants you to keep it safe. But sadly, Gandalf is going to be really sad because the one problem with this whole approach with shinylive is that there are no secrets. Everything is within the browser.

the one problem with this whole approach with shinylive is that there are no secrets. Everything is within the browser.

So if you have a very savvy user, they will be able to find any secret environment variable, whatever you are using to run your Shiny application. It is available. But that is also an interesting part in that if you don't have any secrets, you just have, you know, let's say a CSV, some logic in your app that are and you don't mind if someone inspects every single piece of it, then this is the perfect solution because there are no secrets.

And so it's OK. But if you do have a database that you want to keep secret, you can either hide it behind a plumber API or fast API somewhere else and then Shiny can call out to it. You know, the location of that API will be public within your app, but the API's logic is then hidden away somewhere else. But your personal Shiny app can be then done with shinylive.

There have been questions as well about, well, what if I run it behind my firewall? Sure, no problem. It will be public to your company, you know, within the firewall. But obviously, since the firewall is there, I won't be able to access it. So you would only have to worry about bad actors within the company. And typically that's OK. But yes, the important part is the whole app is in the browser and users can inspect everything somehow in the future.

What's next for shinylive

We want to minimize the required usage of WebR so that you don't even know that you're using WebR along with shinylive. And then we also want to minimize the start time. Today, when I was demoing it, it was about five seconds. And that's with cached R, cached packages and things like that. It used to be 30, 30 plus. And, you know, we hope to get it under the one second mark or as fast as we can by pre-bundling those applications. And so we're only doing the minimal amount of work at runtime and we can preload some of that heavy lifting.

This would hopefully utilize some of our MetaCran repositories or even where you're within company Cran repositories. So if you have pre-built your different packages which are not on Cran or you have specific versions of things that you want to use, we can use our MetaCran instances and hopefully this will be a little more automatic. And so you don't need to manually say point here, point here for all of my 50 packages.

And then this is leading up to making custom bundles using GitHub actions so that you yourself don't need to have a developer environment for exporting shinylive or web R applications, sorry, R libraries. Instead, we'll have a GitHub action and we just send a small command, you wait a little bit and then let GitHub do all the heavy lifting and then it'll send you back a tar ball or zip folder of special information. But all that leads up to the fastest start time that we can possibly get.

Recap

So to recap, we have positive R shinylive. The main function within that shinylive package is the export function where you're going to export it from the folder from here to there and then we'll take that folder to there and host it using GitHub actions or GitHub pages and everything throughout that whole pipeline is free to users today given that you're using a public repo.

Just remember, there are no secrets and so don't put your database in there, database connection information that you want to keep secret that would normally be held secret when doing a traditional Shiny server deployment. Thanks again. See you soon.