The Emscripten WebAssembly (Wasm) environment provides a virtual filesystem (VFS) which supports the concept of mounting. With this, an entire file and directory structure can be packaged into a filesystem image, efficiently making individual files or entire R package libraries available for use in webR.
Create filesystem images
Emscripten’s file_packager
tool
The file_packager
tool, provided by Emscripten, takes in a directory structure as input
and produces a webR compatible filesystem image as output. The file_packager
tool may be invoked from the rwasm package:
It can also be invoked directly using its CLI1, if you prefer:
In the above examples, the files in the directory
./input
are packaged and an output filesystem image is
created2
consisting of a data file, output.data
, and a metadata
file, output.js.metadata
.
To prepare for mounting the filesystem image with webR, ensure that
both files have the same basename (in this example,
output
). The resulting URLs or relative paths for the two
files should differ only by the file extension.
Compression
Filesystem image .data
files may optionally be
gzip
compressed prior to deployment. The file extension for
compressed filesystem images should be .data.gz
, and
compression should be indicated by setting the property
gzip: true
on the metadata JSON stored in the
.js.metadata
file.
NOTE: Loading compressed VFS images requires at least version 0.4.1 of webR.
Mount .tar
archives as a filesystem image
Archives in .tar
format, optionally gzip compressed as
.tar.gz
or .tgz
files, can also be used as
filesystem images by pre-processing the .tar
archive using
the rwasm::add_tar_index()
function. The function reads
archive contents and appends the required filesystem metadata to the end
of the .tar
archive data in a way that is understood by
webR. For further information about the format see the Technical details for .tar archive metadata
article.
> rwasm::add_tar_index("./path/to/archive.tar.gz")
# Appending virtual filesystem metadata for: ./path/to/archive.tar.gz
Once processed by rwasm::add_tar_index()
, the
.tar
archive can be deployed and used directly as a
filesystem image.
Mounting filesystem images
When running in a web browser, the webr::mount()
function downloads and mounts a filesystem image from a URL source,
using the WORKERFS
filesystem type.
webr::mount(
mountpoint = "/data",
source = "https://example.com/output.data"
)
Filesystem images should be deployed to static file hosting3 and the
resulting URL provided as the source argument. The image will be mounted
in the virtual filesystem under the path given by the
mountpoint
argument. If the mountpoint
directory does not exist, it will be created prior to mounting.
When running under Node.js, the source may also be provided as a relative path to a filesystem image on disk.
To test filesystem images before deployment, serve them using a local
static webserver. See the Local Testing section below for an example
using httpuv::runStaticServer()
in R.
Building an R package library image
A collection of R packages can be collected and bundled into a single filesystem image for mounting.
To build an R package library image we must first build one or more
Wasm R packages using add_pkg()
. As an example, let’s build
a package with a few hard dependencies. Ensure that you are running R in
an environment with access to Wasm development tools4, then run:
rwasm::add_pkg("dplyr")
After the build process has completed, the new repo
directory contains a CRAN-like package repository with R packages build
for Wasm.
Next, run the following to build an Emscripten VFS image:
rwasm::make_vfs_library()
By default, this function will create a new directory named
vfs
if it does not exist. The files
vfs/library.data
and vfs/library.js.metadata
together form an Emscripten filesystem image containing an R package
library consisting of all the packages previously added to the CRAN-like
repository in repo
using add_pkg()
.
Local testing
The following R command starts a local web server to serve your
filesystem image for testing5. When serving your files locally, be sure
to include the Access-Control-Allow-Origin: *
HTTP header,
required for downloading files from a cross-origin server by the CORS
mechanism.
httpuv::runStaticServer(
dir = ".",
port = 9090,
browse = FALSE,
headers = list("Access-Control-Allow-Origin" = "*")
)
Once the web server is running start a webR session in your browser,
such as the console at https://webr.r-wasm.org/latest/. Use
webr::mount()
to make the R library image available
somewhere on the VFS6:
webr::mount("/my-library", "http://127.0.0.1:9090/vfs/library.data")
Once mounted, the contents of the filesystem image are available at
/my-library
in the virtual filesystem.
list.files("/my-library")
#> [1] "R6" "cli" "dplyr" "fansi" "generics" "glue"
#> [7] "lifecycle" "magrittr" "pillar" "pkgconfig" "rlang" "tibble"
#> [13] "tidyselect" "utf8" "vctrs" "withr"
This new directory should be added to R’s .libPaths()
,
so that R packages may be loaded from the new library.