webR Code Extension for Quarto HTML Documents
This extension enables the webR code cell in a Quarto HTML document.
The goal of webR is to:
run R code in the browser without the need for an R server to execute the code
For more details on webR, please see:
Installation
To use this extension in a Quarto project, install it from within the project's working directory by typing into Terminal:
quarto add coatless/quarto-webr
Usage
For each document, place the webr
filter in the document's header:
filters:
- webr
Then, place the R code for webR
in a code block marked with {webr-r}
---
title: WebR in Quarto HTML Documents
format: html
engine: knitr
filters:
- webr
---
This is a webr-enabled code cell in a Quarto HTML document.
```{webr-r}
fit = lm(mpg ~ am, data = mtcars)
summary(fit)
```
When quarto render
or quarto preview
is called, the filter will execute under engine: knitr
.
During the execution, the filter adds two files to the working directory: webr-worker.js
and webr-serviceworker.js
. These files allow for the
webR
session to be started and must be present with the rendered output.
Note: If engine: knitr
is not specified, then the jupyter
compute engine will be used by default.
Packages
By default, the quarto-webr
extension avoids loading or requesting additional packages. Additional packages can be added
when the document is first opened or on per-code cell basis. You can view what packages are available by either executing
the following R code (either with WebR or just R):
available.packages(repos="https://repo.r-wasm.org/", type="source")
Or, by navigating to the WebR repository:
https://github.com/r-wasm/webr-repo/blob/main/repo-packages
Install on document open
Add to the document header YAML the packages
key under webr
with each package listed using an array, e.g.
---
webr:
packages: ['ggplot2', 'dplyr']
---
Install on an as needed basis
Packages may also be installed inside of a code cell through the built-in webr::install()
function. For example, to install ggplot2
, you would need to use:
webr::install("ggplot2")
Customizing webR from the Quarto Extension
The quarto-webr
extension supports specifying the following WebROptions
options:
home-dir
: The WebAssembly userβs home directory and initial working directory (Documentation
). Default:'/home/web_user'
.base-url
: The base URL used for downloading R WebAssembly binaries (Documentation
). Default:'https://webr.r-wasm.org/[version]/'
.service-worker-url
: The base URL from where to load JavaScript worker scripts when loading webR with the ServiceWorker communication channel mode (Documentation
). Default:''
.
The extension also has native options for:
show-startup-message
: Display in the document header the state of WebR initialization. Default:true
show-header-message
: Display in the document header whether COOP and COEP headers are in use for faster page loads. Default:false
For these options to be active, they must be placed underneath the webr
entry in the documentation header, e.g.
---
title: WebR in Quarto HTML Documents
format: html
engine: knitr
webr:
show-startup-message: false
show-header-message: false
home-dir: '/home/r-user/'
packages: ['ggplot2', 'dplyr']
filters:
- webr
---
Known Hiccups
As this is an exciting new frontier, we're learning as we go. Or as my friend Lawrence says, "I like to build airplanes in the air-". Please take note of the following issues:
Stuck at Loading webR...
If webr-worker.js
or webr-serviceworker.js
are not found when the document loads either at the root /
or relative directory, then Loading webR...
will appear above the code cell instead of Run code
. Please make sure the files are at the same location as the quarto document. For example, the following structure will work:
.
βββ demo-quarto-webr.qmd
βββ webr-serviceworker.js
βββ webr-worker.js
Still having trouble? Try specifying where the worker files are located using the service-worker-url
option in the document's YAML header.
Directly accessing rendered HTML
When using quarto preview
or quarto render
, the rendered HTML document is being shown by mimicking a server running under https://localhost/
. Usually, everything works in this context assuming the above directory structure is followed. However, if you directly open the rendered HTML document, e.g. demo-quarto-web.html
, inside of a Web Browser, then the required WebR components cannot be loaded for security reasons. You can read a bit more about the problem in this StackOverflow answer.
There are a few possible solutions to avoid requiring quarto on a local computer to directly open the rendered file:
- Use Chrome's
--allow-file-access-from-files
access - Use the WebServer for Chrome extension
- Or, use NPM to obtain
local-web-server
Speed up webR
When serving webR documents, please try to ensure the COOP and COEP HTTP headers are set to speed up the process:
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp
For users who host their website with Netlify, add to the netlify.toml configuration file:
[[headers]]
for = "/directory/with/webr/content/*"
[headers.values]
Cross-Origin-Opener-Policy = "same-origin"
Cross-Origin-Embedder-Policy = "require-corp"
For users who deploy their site with GitHub Pages, please hang tight! By default, GitHub Pages does not allow for headers to be modified. There have been notable efforts by the GitHub Pages community to circumvent this limitation by using
coi-servicworker
. We're currently testing it out.
For users who administer a server with nginx
, the add_header
directive
can be used to add headers into the configuration file at /etc/nginx/nginx.conf
.
server {
# Enable headers for the webr directory
location ^~ /directory/with/webr/content {
add_header "Cross-Origin-Opener-Policy" "same-origin";
add_header "Cross-Origin-Embedder-Policy" "require-corp";
}
}
More information may be found in nginx
's Serving Static Content.
For additional justificaiton on why the headers are required, please see webR's documentation page for Serving Pages with WebR.
Engine Registration
If using the knitr
engine instead of the jupyter
engine and you are using the original tag of {webr}
instead of {webr-r}
,
there is a known warning that will appear in the render processing output of:
Warning message:
In get_engine(options$engine) :
Unknown language engine 'webr' (must be registered via knit_engines$set()).
This warning does not prevent or impact the ability of the webr
filter to function.
Though, we would like to address it at some point since it is not aesthetically pleasing.
Acknowledgements
We appreciate the early testing feedback from Eli E. Holmes and Bob Rudis.
We also appreciate the Quarto team assisting with setting up a new code cell type.
This repository builds ontop of the initial proof of concept for a standalone Quarto HTML document in:
https://github.com/coatless-r-n-d/webR-quarto-demos
The proof of concept leaned heavily on the webR developers public-facing examples:
For the extension, we greatly appreciated insights from:
- Extensions
- Quarto Documentation
- Pandoc Documentation