webrcli & spidyr: What’s new
Find all my posts about webR here.
Note: the first post of this series explaining roughly what
webRis, I won’t introduce it again here.
In this blogpost, you’ll find some updates about some recent changes made in webrcli & spidyr.
What webrcli & spidy wants to achieve
In a nutshell, the goal of webrcli & spidyr is to provide an interface for bringing your R functions inside a NodeJS runtime.
Think of it as something that wants to achieve the following interation:
-
An R dev writes, builds and shares a package called
{rfuns}, which contains a function calledhello_world() -
A NodeJS dev takes this package, can call it with
rfuns.hello_world(), access and manipulate the results with JavaScript.

An important note
With webR & the tools described below, there is no R session running while the NodeJS app is running. spidyr imports an R function converted to a native JS.
rfuns.hello_world does not call an R session running somewhere else.
That also means that if you build a container containing the app, you don’t need to install R in it. It’s a NodeJS app.
Below are some updates recently made to both webrcli & spidyr.
Making the template code smaller
When drafting the first code of webrcli & spidyr, I focused on providing a minimal template for an index.js loading your R functions, contained in a subdirectory inside your node project.
This worked, but might have been a bit complex to grasp. Provided you don’t change the default names of the folders (in that case you’ll need to modify the default parameters), the new default index.js look like this:
const {
initSpidyr,
mountLocalPackage
} = require('spidyr');
(async () => {
await initSpidyr()
const rfuns = await mountLocalPackage("./rfuns");
const hw = await rfuns.hello_world()
console.log(hw.values);
console.log("✅ Everything is ready!");
})();
This minimal template makes it easier to read and understand what the code does. Note that you’ll get this template if you run webrcli init myproject.
Let’s decompose what this code does :
-
await initSpidyr()will create an object calledspidyr_webRstored asglobalThis.spidyr_webR,init()it (as inwebr.init()), and load the packages contained in the./webr_packagesfolder inside your project dir, the one containing the packages installed withwebrcli install. -
const rfuns = await mountLocalPackage("./rfuns");will take the R package contained in./rfuns, load it into the webR instance (spidyr_webR), recursively get all the exported functions from your package, and store them inside therfunsobject. -
const hw = await rfuns.hello_world()will call thehello_world()function from{rfuns}. The values are thenconsole.loged.
new Library() is now library()
Calling a package is now const spongebob = library("spongebob") instead of the previous approach which was const spongebob = new Library("spongebob");await spongebob.load(globalThis.webR);
Better installation from package.json & DESCRIPTION
The previous version of webrcli did not stored nor re-installed the R package installed in the project, meaning that if you git cloned a project, you had to guess what R packages to re-install.
Now, a project initiated with webrcli will store all the packages installed with webrcli install inside the package.json file.
Then, when running the npm install command, the R packages will also be redownloaded.
You can also installed a series of packages based on a DESCRIPTION file with webrcli installFromDesc.
Other tools
shareEnvallows to copy one, several or all env var from node to the webR instance.
Workflow summary
-
webrcli init myprojectwill create a project skeleton at./myproject -
webrcli install spongebobwill download the version of{spongebob}compiled forwebR, and add it to./webr_packages. -
You can then modify you R code with your own functions.
-
Call your R function from
rfuns.xyz()in Node -
Run with
npm start

Please do give it a shot
I think I’ve been the only user for now 😅, so please do try these and let me know what you think.
Future works
Here are what I plan on working in the upcoming weeks:
-
webrcli initshould allow for specifying awebrversion from npm issue 17 -
initSpidyrshould allow to pass params towebR.init()issue 12 -
Allow to install from
r-universe, something likewebrcli installFromRUniverseissue 16. Probably in the future it will be merged towebrcli installand we’ll have a way to guess what the user wants based on the input. -
A small converter from R named list to JS objects Issue 3
-
More documentation, and probably documenting the conversion of an existing
{shiny}app to aspidyrbased one.
What do you think?