But what is a “server” anyhow?
A server is a machine, connected to the Internet, that runs 24/7 ready to run your Shiny app.
On-prem:
Cloud:
Some web services offer an excellent mix of scalability, features, and cost:
However, they can’t run traditional Shiny apps!
This is static hosting. No way to run dynamic R or Python code.
Wouldn’t it be great if we could run Shiny apps using static hosting?
Some technical details
Benefits of Wasm:
Containerisation
Notebook & literate programming
Universal Binaries
Sandboxing
Numerical Reproducibility
Mobile / Tablet computing
Emscripten takes C or C++ source code as input, provides a Unix-like environment, and produces Wasm as output
Observation: Many programming language interpreters are written in C or C++ for Unix/Linux…
BUT: For something like Python or R it’s harder than it first seems
Standard & support libraries (e.g. linear algebra)
Legacy Fortran code
Graphics & font support
Network sockets
Local file I/O
Threading and forking
Limited methods to wait for input
Wasm/Emscripten looks like Unix, but browser security limitations are always there.
We have to work around them, replacing standard OS tools with the provided browser APIs.
Pyodide is a port of CPython to WebAssembly
Pyodide makes it possible to install and run Python packages in the browser
Supported scientific packages include numpy, pandas, scipy, matplotlib, and scikit-learn.
WebR is a version of the R interpreter built for WebAssembly
Execute R code directly in a web browser, without a supporting R server
Alternatively, run an R process server-side using Node.js
We’ll come back to Shiny apps later!
R code editor, multi document support, syntax highlighting
Context aware autocompletion
Folder and file management tools
Mulitple plots, manage and clear plot history
Screenreader support in R console
Works on wide-ranging devices: mobile, tablet, chomebook
coatless/quarto-webr — James Balamuta
In a terminal,
In a Quarto doc,
Any font family available to the web browser can be used in plots
Accurate font metrics for text sizing and positioning
Advanced text features such as ligatures & colour emoji 😃
RTL text and automatic font fallback for international scripts
const ret = await webR.evalR("penguins");
const data = await ret.toJs();
const penguins = data.values[0].values.map((_, idx) => {
return {
species: data.values[0].values[idx],
island: data.values[1].values[idx],
bill_length_mm: data.values[2].values[idx],
bill_depth_mm: data.values[3].values[idx],
sex: data.values[6].values[idx],
}
});
Plot.dot(penguins, {
x: "bill_length_mm",
y: "bill_depth_mm",
stroke: "species", symbol: "species",
channels: {island: "island", sex: "sex"},
tip: true
}).plot({ grid: true, symbol: { legend: true } })
Binary R packages for Wasm are available, hosed at https://repo.r-wasm.org
webR 0.2.1: 10324 packages (about 51% of CRAN) - Note: not all have been tested
Service Workers are a JavaScript API that enables Shiny to work with webR.
Tricky to set up, especially for non-JavaScript developers.
Anyone can create their own serverless Shiny apps!
Option 1: Shinylive online editor
Option 2: Convert a Shiny app
Option 3: Embed a Shiny app with Quarto
Share a Shiny app with anyone using a single URL: Example Shinylive App
Share a Shiny app from a GitHub Gist: https://shinylive.io/py/app/#gist=e62218aa28bf26e785fc6cb99efe8efe
Install the Shinylive R package:
Preview the application:
Static file output:
Ready to be uploaded to GitHub Pages or other static web hosting
First, in a terminal run the command:
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor
incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis
nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo.
```{shinylive-r}
#| standalone: true
library(shiny)
# Create Shiny UI
ui <- [...]
# Create Shiny server function
server <- function(input, output, session) {
[...]
}
# Build Shiny app
shinyApp(ui = ui, server = server)
```
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu
fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in
culpa qui officia deserunt mollit laborum.
#| standalone: true
#| viewerHeight: 700
library(shiny)
library(bslib)
theme <- bs_theme(font_scale = 1.5)
# Define UI for app that draws a histogram ----
ui <- page_sidebar(theme = theme,
sidebar = sidebar(open = "open",
numericInput("n", "Sample count", 50),
checkboxInput("pause", "Pause", FALSE),
),
plotOutput("plot", width=1100)
)
server <- function(input, output, session) {
data <- reactive({
input$resample
if (!isTRUE(input$pause)) {
invalidateLater(1000)
}
rnorm(input$n)
})
output$plot <- renderPlot({
hist(data(),
breaks = 30,
xlim = c(-2, 2),
ylim = c(0, 1),
xlab = "value",
freq = FALSE,
main = ""
)
x <- seq(from = -2, to = 2, length.out = 500)
y <- dnorm(x)
lines(x, y, lwd=1.5)
lwd <- 5
abline(v=0, col="red", lwd=lwd, lty=2)
abline(v=mean(data()), col="blue", lwd=lwd, lty=1)
legend(legend = c("Normal", "Mean", "Sample mean"),
col = c("black", "red", "blue"),
lty = c(1, 2, 1),
lwd = c(1, lwd, lwd),
x = 1,
y = 0.9
)
}, res=140)
}
# Create Shiny app ----
shinyApp(ui = ui, server = server)
Loading R packages works, but is very slow. We’re working on it!
Not all R packages work in Wasm
Browser security restrictions: very limited networking, no raw socket access
Moving data into and out of the virtual Wasm environment is clunky right now (at best!)
https://webr.r-wasm.org/v0.2.1/
npm install webr
https://docs.r-wasm.org/webr/v0.2.1/
https://github.com/posit-dev/shinylive
https://github.com/quarto-ext/shinylive