-
Notifications
You must be signed in to change notification settings - Fork 6
/
mount-fs-image.Rmd
92 lines (66 loc) · 4.51 KB
/
mount-fs-image.Rmd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
---
title: "Mounting filesystem images"
output: rmarkdown::html_document
vignette: >
%\VignetteIndexEntry{Mounting filesystem images}
%\VignetteEngine{knitr::rmarkdown}
%\VignetteEncoding{UTF-8}
---
## Introduction
The Emscripten WebAssembly 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 to be loaded and mounted at runtime by WebAssembly (Wasm) applications. We can take advantage of this interface to efficiently mount R package libraries, pre-packaged and containing potentially many related R packages, in the VFS accessible to webR.
## Building an R package library
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 tools^[See the "Setting up the WebAssembly toolchain" section in `vignette("rwasm")` for further details.], then run:
```{r eval=FALSE}
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:
```{r eval=FALSE}
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()`.
### Packaging arbitrary data
It is also possible to package an arbitrary data directory as an Emscripten filesystem image using the `file_packager()` function:
```{r eval=FALSE}
rwasm::file_packager("./some/data/directory", out_name = "output_image.data")
```
Again, this function writes output filesystem images to the `vfs` directory by default.
## Mounting filesystem images
The filesystem image(s) should now be hosted by a web server so that it is available at some URL. Such a URL can then be passed to `webr::mount()` to be made available on the virtual filesystem for the Wasm R process.
### Local testing
The following R command starts a local web server to serve your filesystem image for testing^[Ensure that the latest version of the `httpuv` package is installed so that the `?httpuv::runStaticServer` function is available.]. 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](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) mechanism.
```r
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 VFS^[You might need to adjust the path portion of the URL, depending on your set-up. If it does not work, you could also try `"http://127.0.0.1:9090"` or `"http://127.0.0.1:9090/output/vfs"`]:
```{r eval=FALSE}
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.
```{r eval=FALSE}
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.
```{r eval=FALSE}
.libPaths(c(.libPaths(), "/my-library"))
library(dplyr)
#> Attaching package: ‘dplyr’
#>
#> The following objects are masked from ‘package:stats’:
#>
#> filter, lag
#>
#> The following objects are masked from ‘package:base’:
#>
#> intersect, setdiff, setequal, union
```
### Deployment
The filesystem image files should be deployed to the static file hosting service of your choice, so that they are available for download anywhere. See the "Deployment to static hosting" section in `vignette("rwasm")` for an example of how to host static files with GitHub pages, substituting the `repo` directory for the `vfs` directory containing Emscripten filesystem images.