How to write Node modules with Rust
Posted on August 13, 2021 • 1 minutes • 187 words
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
#[js_function(3)]
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))?;
Ok(s)
}
And then you expose it to Node.js runtime with
#[module_exports]
fn init(mut exports: JsObject) -> Result<()> {
exports.create_named_method("say_hello", say_hello)?;
Ok(())
}
Build
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) {
parts.push('musl');
} else if (process.arch === 'arm') {
parts.push('gnueabihf');
} else {
parts.push('gnu');
}
} else if (process.platform === 'win32') {
parts.push('msvc');
}
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.