Using webR in an Express JS REST API
Tags: r, webr, webassembly
Published: 2023-08-28 08:00:27

---
title: Using webR in an Express JS REST API
published: true
date: 2023-07-04 00:00:00 UTC
tags: r, webr, wasm
canonical_url: https://colinfay.me/calling-webr-from-expressjs/
---

## webR? wat again?

As described in the [doc](https://docs.r-wasm.org/webr/latest/):

> WebR is a version of the statistical language R compiled for the browser and Node.js using WebAssembly, via Emscripten.

In this post, I won’t go into details into what `webR` is, as if you want to know more, you’ll probably get a better understanding by going through the documentation.

But if like a normal person you don’t read the doc, let’s sum up what `webR` is. Simply put, `WebAssembly` (shorten wasm) is a format that can be used to encode a programming language to something that can then be called from a JavaScript runtime (in the browser or in NodeJS). Schematically, you take one language, you translate it to wasm, and the output can be read and used from JavaScript.

If you still have no idea what wasm is but want to get a better grasp on what it is, I suggest reading [this blogpost](https://www.jesuisundev.com/en/understand-webassembly-in-5-minutes/) that really sums it well, especially this quote:

> WASM is a way to use non-Javascript code and run it in your browser.

I also suggest reading the blogposts by [boB](https://rud.is/b/) on the subject.

The rest of this post assume that you understand what wasm & `webR` are.

## Playing with webR

I’ve been interested with WebAssembly for a while now, and can remember talking about it late during the night at R conferences around 2018 and 2019… but that’s a story for another time 😅

Today’s story is about exploring how to build tools in JavaScript that will call `webR`.

I’ll try to document my experimentations, and this post is the first one of a series that I hope I’ll find time to continue over the summer.

## Hello World! - Creating an API where we call webR

I’ll start with a simple [Express JS](https://expressjs.com/) REST API that uses webR to run R code.

```
# Initiating a projet and opening it with VSCode
mkdir webrexpresshelloworld
code webrexpresshelloworld

# Quick init of a node project
npm init -y
touch index.js
npm install express

```

We’ll now install the webR nodejs package

```
npm i @r-wasm/webr

```

And now, let’s move to our index.js file. We’ll start with the basics of Express JS: creating the `app` object.

```
// Creating the express app
const app = require('express')()

```

Then, we’ll import `WebR` from `@r-wasm/webr`.

```
// importing the `WebR` class inside the runtime
const { WebR } = require('@r-wasm/webr');

```

We’ll now be initiating the webR session by:

- creating an instance of webR
- binding it to `globalThis` so that it’s available everywhere
- calling the `init` method
- Once `webR` is ready, we’ll launch the `app`

As webR communicates via the worker thread asynchronously, we need to use `async`/`await`.

```
(async () => {
  globalThis.webR = new WebR();
  await globalThis.webR.init();
  console.log("webR is ready");
  // Starting the express app
  // only after webR is ready
  app.listen(3000, () => {
    console.log('http://localhost:3000')
  })
})();

```

Finally, we add a route that returns an hello world:

```
// Creating a route for the express app
// that will return a titleCase hello world from r
app.get('/', async (req, res) => {
  // Evaluating the R code inside the R worker
  let result = await globalThis.webR.evalR('tools::toTitleCase("hello from r!")');
  // Converting the result to a JS object
  let output = await result.toJs();
  // Sending the result back to the client,
  // (webR outputs an object with types/names/values
  // and here we only want the values)
  res.send(output.values)
});

```

And now, let’s run our app!

```
node index.js

```

You can find the code [here](https://github.com/ColinFay/webr-examples/tree/main/express-webr-hello-world), and see it live at [srv.colinfay.me/express-webr-hello-world](https://srv.colinfay.me/express-webr-hello-world).

You can also try it with

```
docker run -it -p 3000:3000 colinfay/express-webr-hello-world

```