Netlify Function using Rust (wasm-bindgen)

All Posts

Netlify Function using Rust (wasm-bindgen)

Updated: September 16, 2020 by Tony Alves

We would like to build a Rust library to be able to use during our Netlify function call. Netlify doesn't support setting up Rust for functions exactly how we would on AWS Lambda like Netlify does with GO. We will use a Node compatible wasm package builder called wasm-pack to provide a package for use from our javascript handler function. Netlify doesn't have support for the Rust compiler (yet) in the build environment during our CI/CD, so we will have to prebuild our Rust library local and commit the package with our repository. Although this isn't optimal for our workflow, the pre-build solution will work just fine.

Note: There is a way to use GitHub actions to build our Rust package, but outside the scope of this tutorial. We could then use actions to build our Netlify functions and deploy to Netlify.

Credits: Thanks to Benjamin Lannon for pointing to the solution and Prince Wilson for starting us down this path.

Steps we'll take

  • Create the Rust library
    Includes dependency wasm-bindgen
  • Setup our Netlify function
  • Install wasm-pack

Requirements:

  • Rust and Cargo installed
  • Install wasm-pack

Create the Rust library

$ cargo new rust-netlify-function --lib

Include our dependency for wasm-bindgen into the Cargo.toml file. We have to setup options for wasm-opt due to an issue when using wasm-pack.

Cargo.toml

[package]
name = "hello"
version = "0.1.0"
authors = ["talves"]
edition = "2018"
[package.metadata.wasm-pack.profile.release]
wasm-opt = ["-Oz", "--enable-mutable-globals"]
[lib]
crate-type = ["cdylib"]
[dependencies]
wasm-bindgen = "=0.2.65"

Replace the src/lib.rs contents with the following:

src/lib.rs

use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub fn hello_world(name: &str) -> String {
String::from(format!("Hello {}!", name))
}

Setup our Netlify function

functions/hello/hello.js

const { hello_world } = require('./pkg/hello');
exports.handler = async function({ queryStringParameters = {} }) {
try {
const { name = 'World' } = queryStringParameters;
const message = hello_world(name);
return {
statusCode: 200,
body: message,
};
} catch (error) {
console.log(error);
return { statusCode: error.statusCode || 500, body: error.message };
}
};

We will setup a Netlify config (netlify.toml) in the root of our repository (optional but recommended).

netlify.toml

[build]
command="mkdir site && echo '<h1>Our Rust Netlify Function</h1>' > site/index.html"
publish="site"
functions="functions"

Install wasm-pack

You can get the install instructions from here for your system.

Since I'm using WSL2 on Windows, I can run this curl:

$ curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
$ wasm-pack --version

Run wasm-pack to include our package

We now want to run wasm-pack so we can include the package in our function bundle inside our repository.

$ wasm-pack build --out-dir functions/hello/pkg --target nodejs

Done!

Commit our code up to GitHub and go to Netlify and setup our new site using the repository.

If you'd like to skip over this work, here is a repo including all the source code and also a one-click button in the Readme to deploy to Netlify and create your own copy on GitHub.

Test your function by going to your site at:
https://your-site-name.netlify.app/.netlify/functions/hello

Or
https://your-site-name.netlify.app/.netlify/functions/hello?name=Everyone

© Tony Alves