Pages Functions with WebAssembly Demo

This is a demo application that exemplifies the use of Wasm module imports inside ⚡️Pages Functions code. Head over to our announcement blog post to read more about it, or play with the live demo here.

The application computes the distance in kilometers on the surface of Earth between your current location (based on the geo coordinates of the incoming request) and any other point on the globe, each time you click on the globe's surface. The code that performs the actual high-performance distance calculation is written in Rust, but is invoked from within a Pages Function via the Wasm module import mechanism.

Credits

Kudos to Vasco Asturiano and all other contributors for their fantastic work on globe.gl.

❤︎

Prerequisites

In order to run this project, you will need to have the following installed:

  • wasm-pack to generate the WebAssembly binaries from the Rust code. We recommend following these instructions.
  • Node.js
  • yarn or npm package manager

Project structure

app-rust

The folder where the Rust application lives.

Our Rust application project is based on wasm-pack-template. Please refer to the Rust and WebAssembly book to read more about how to use Rust and WebAssembly together, and how to setup a project for that purpose.

app-rust/src/lib.rs

This file is the root of the Rust crate that we are compiling to WebAssembly. It uses wasm-bindgen to interface with JavaScript.

In our case, lib.rs contains the source code of distance_between(), the function which computes the distance on the surface of Earth between two points, and which we invoke within our Pages Function.

#[wasm_bindgen]
pub fn distance_between(from_latitude_degrees: f64, from_longitude_degrees: f64, to_latitude_degrees: f64, to_longitude_degrees: f64) -> f64 {
  let earth_radius_kilometer = 6371.0_f64;

  let from_latitude = from_latitude_degrees.to_radians();
  let to_latitude = to_latitude_degrees.to_radians();

   let delta_latitude = (from_latitude_degrees - to_latitude_degrees).to_radians();
   let delta_longitude = (from_longitude_degrees - to_longitude_degrees).to_radians();

  let central_angle_inner = (delta_latitude / 2.0).sin().powi(2)
    + from_latitude.cos() * to_latitude.cos() * (delta_longitude / 2.0).sin().powi(2);
  let central_angle = 2.0 * central_angle_inner.sqrt().asin();

  let distance = earth_radius_kilometer * central_angle;
    
  return distance;
}

To build the app-rust project you will need to run:

wasm-pack build

This orchestrates the following steps (*):

  • Ensure that we have the correct Rust version and the wasm32-unknown-unknown target installed via rustup,
  • Compile our Rust sources into a WebAssembly .wasm binary via cargo,
  • Use wasm-bindgen to generate the JavaScript API for using our Rust-generated WebAssembly.

The resulting build artifacts will be outputted in the pkg directory. One of these artifacts is src_wasm_bg.wasm, the WebAssembly binary that contains the compiled-to-wasm versions of all of our Rust functions and data. This binary is the one we will import as a WebAssembly Module inside our Pages Function.

app-web

The folder where the client-side application lives.

The client application is responsible of rendering the globe on the page, allowing users to interract with it, and making all the necessary API calls.

functions

The Pages Functions folder

Please refer to the Pages official docs for more information about Functions.

Develop

Install npm dependencies

yarn

Build Rust project

yarn build:app-rust

Start local server

yarn dev

and go to http://127.0.0.1:8788/ in your browser.