How to write Node modules with Rust

TLDR: there’s a sample repo here if you’re lazy to read this post. The sample repo include GitHub Actions sample for CI as well.

The Rust bit

It’s very simple. You write your function in Rust

fn say_hello(ctx: CallContext) -> Result<JsString> {
  let name = ctx.get::<JsString>(0)?.into_utf8()?;
  let name = name.as_str()?;
  let s = ctx.env.create_string_from_std(format!("Hello, {}!", name))?;

And then you expose it to Node.js runtime with

fn init(mut exports: JsObject) -> Result<()> {
  exports.create_named_method("say_hello", say_hello)?;



You then build it with napi by using this command napi build --platform

And if you want to build for multi-platform, you will have multiple binaries, so you need to load accordingly in Node.js. We use detect-libc library for this.

let parts = [process.platform, process.arch];
if (process.platform === 'linux') {
  const {MUSL, family} = require('detect-libc');
  if (family === MUSL) {
  } else if (process.arch === 'arm') {
  } else {
} else if (process.platform === 'win32') {

module.exports = require(`./node-module-rust-example.${parts.join('-')}.node`);

And that’s it. You can replace test.js with your favorite test runner. The test code there is just dummy code.