posit-dev / r-shinylive

https://posit-dev.github.io/r-shinylive/
Other
156 stars 16 forks source link

Distribute Wasm package binaries as part of shinylive exported site #63

Closed georgestagg closed 2 months ago

georgestagg commented 6 months ago

@schloerke: Here is THE PLAN:

1) Run renv::dependencies() on shiny app to list dependencies at build time

2) Loop through the list of packages, use packageDescription() to find information.

3) Lookup information about package list:

4) Build package library for inclusion as part of exported static files

5) (At runtime, using Shinylive & JavaScript):

@schloerke to handle 1-4, @georgestagg to handle upgrade of webR in Shinylive to v0.3.0 and then 5).

schloerke commented 6 months ago

Notes on implementation:


For all packages found by {renv}; Use pak::pkg_deps(pkgs, upgrade=FALSE, dependencies=NA) to get default package deps.

meta data: list of lists where each list item is:

Only update package builds if the metadata changes.

======================================================================

Building bundles:

Given bundle files

georgestagg commented 6 months ago

The PR at https://github.com/posit-dev/shinylive/pull/121 now attempts to read the metadata file _webr/metadata.rds, produced by something like,

saveRDS(
  list(
    list(name = "cli", path = "packages/cli/cli_3.6.2.data", type = "package", version = "3.6.2", ref = "3.6.2"),
    list(name = "dplyr", path = "packages/dplyr/library.data", type = "library", version = "1.1.4", ref = "1.1.4")
  )
)

and automatically downloads and mounts the VFS images from the URL paths e.g. [...]/shinylive/webr/packages/cli/cli_3.6.2.data at app startup. Note that the static directory [...]/shinylive/webr already exists as part of a distributed app. r-shinylive will need to create and populate the new directory [...]/shinylive/webr/packages, though.

The code adds the mounted directory to the .libPaths(), if it is an image of a full package library rather than a single package. It decides to do this or not based on the type property in the metadata.


I was originally thinking metadata.rds could be distributed as part of the static assets somewhere under [...]/shinylive/webr/, to be downloaded at runtime, but I'm thinking now we should just add it to app.json as a base64 encoded binary file. This saves on a full HTTP round-trip to the server.

Below is an example app.json I've been using to test this:

[
    {
        "name": "app.R",
        "content": "library(shiny)\n\n# Define UI for app that draws a histogram ----\nui <- fluidPage(\n\n  # App title ----\n  titlePanel(\"Hello Shiny!\"),\n\n  # Sidebar layout with input and output definitions ----\n  sidebarLayout(\n\n    # Sidebar panel for inputs ----\n    sidebarPanel(\n\n      # Input: Slider for the number of bins ----\n      sliderInput(inputId = \"bins\",\n                  label = \"Number of bins:\",\n                  min = 1,\n                  max = 50,\n                  value = 30)\n\n    ),\n\n    # Main panel for displaying outputs ----\n    mainPanel(\n\n      # Output: Histogram ----\n      plotOutput(outputId = \"distPlot\")\n\n    )\n  )\n)\n\n# Define server logic required to draw a histogram ----\nserver <- function(input, output) {\n\n  # Histogram of the Old Faithful Geyser Data ----\n  # with requested number of bins\n  # This expression that generates a histogram is wrapped in a call\n  # to renderPlot to indicate that:\n  #\n  # 1. It is \"reactive\" and therefore should be automatically\n  #    re-executed when inputs (input$bins) change\n  # 2. Its output type is a plot\n  output$distPlot <- renderPlot({\n\n    x    <- faithful$waiting\n    bins <- seq(min(x), max(x), length.out = input$bins + 1)\n\n    hist(x, breaks = bins, col = \"#75AADB\", border = \"white\",\n         xlab = \"Waiting time to next eruption (in mins)\",\n         main = \"Histogram of waiting times\")\n\n    })\n\n}\n\n# Create Shiny app ----\nshinyApp(ui = ui, server = server)\n",
        "type": "text"
    },
    {
        "name": "DESCRIPTION",
        "content": "Title: Hello Shiny!\nAuthor: RStudio, Inc.\nAuthorUrl: http://www.rstudio.com/\nLicense: MIT\nDisplayMode: Showcase\nTags: getting-started\nType: Shiny\n",
        "type": "text"
    },
    {
        "name": "Readme.md",
        "content": "This small Shiny application demonstrates Shiny's automatic UI updates. \n\nMove the *Number of bins* slider and notice how the `renderPlot` expression is automatically re-evaluated when its dependant, `input$bins`, changes, causing a histogram with a new number of bins to be rendered.\n",
        "type": "text"
    },
    {
        "name": "_webr/metadata.rds",
        "content": "H4sIAAAAAAAAA4vgYmBgYGZgYWZkYGYFMhlYQ0PcdC2ADGEgZgIiEA2SEQBiRgYWBk6QhuSc\nTDQh6YLE5OzE9NRifaAcCMcb65npGemlJJYkoillhypFE2YFa8AhyMKELJiXmJtaDFXJChVk\nAQnC2AWJJRkwdkllAUycvSy1qDgzPw/mjaLUNCD1D4cvWVMKciqLcPoTLKufk5lUlFhUidWf\nUDk0YUZDLAIg/zH+p56XAFiF71XYAQAA",
        "type": "binary"
    }
]
gadenbuie commented 3 months ago

This issue should be closed when we update the default shinylive assets version, correct?