Use Rust in a Node.js project

Use Rust in a Node.js project

Rust is the most loved language right now — sounds like a cliche already 😃, but it’s true. In fact, it has been added to the Linux Kernel and going to be added to the Windows Kernel.

Not every language enjoys that kind of privilege and love, you know. One of the benefits of Rust is that it’s fast, if you have implemented something awesome in Rust and you want to use it in your NodeJS project to enjoy the benefits of Rust, it’s possible. You can compile your rust code as a dynamic library and use it in your NodeJS application. I’ll show you how you can do that in this article.

Note: In this article, I’ll assume you are familiar with Rust and Javascript on a very basic level

So, let’s start by writing a basic Rust addition function and release it as a library.

Run cargo init --lib to initialize a brand new Rust library project. Replace the content of the lib.rs file that will be generated with the code below:

#[no_mangle]pub fn add_numbers(a: i32, b: i32) -> i32 {
    a + b
}

Now, let me explain the code. This is a simple function that adds two integers. But what about the #[no_mangle] , you asked?

In compiler construction, name mangling (also called name decoration) is a technique used to solve various problems caused by the need to resolve unique names for programming entities in many modern programming languages. It provides a way of encoding additional information in the name of a function, structure, class or another datatype in order to pass more semantic information from the compiler to the linker.

Wikipedia

In our case, we don’t want the compiler to tamper with the name we want to be able to access the function name as it’s since we need to use it in external applications or programming languages.

So, with Rust, you can decorate your function with the #[no_mangle] attribute and the compiler will leave your function name as it is.

We have the rust code, now, let’s compile it. But wait before we do that, replace your Cargo.toml file with the code below, so that we’ll be on the same page:

[package]
name = "addition_library"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[lib]
name="addition_library"
path = "src/lib.rs"
crate-type = ["dylib"]

The crate-type = ["dylib"] is a configuration option that specifies that a Rust crate should be compiled as a dynamic library, also known as a shared library. It will generate the library with a file extension of .so on Linux, .dll on Windows, or .dylib on macOS

So, now that we’ve completed this, let’s compile it and use it in our Node.js app.

Run the command below to create a new build for the library.

cargo build --release

Your file structure should now look like this:


├── Cargo.lock
├── Cargo.toml
├── src
│   └── lib.rs
└── target
    ├── CACHEDIR.TAG
    └── release
        ├── build
        ├── libaddition_library.dylib
       

Since I am on a MacOS, I am interested in the libaddition_library.dylib file. That’s what I’ll import into my NodeJs project.

Now, create a NodeJS project. It does not have to be in the same directory. In fact, I will advise that you create it in a different folder for the sake of this tutorial.

In the directory run npm init -y to initialize a new project with npm and then install the Node FFI library by running npm i ffi-napi. The node-ffi-napi package allows you to load and call dynamic libraries from your Javascript application.

Once the installation is complete, create a directly rustlib (you can call it whatever you want), copy the libaddition_library.dylib file into it.

Now, create an app.js file and add the following content to it:

const ffi = require("ffi-napi");

// Load the dynamic library
const lib = ffi.Library("rustlib/libaddition_library.dylib", {
  add_numbers: ["int", ["int", "int"]],
});

// Call the add_numbers function
const result = lib.add_numbers(2, 3);
console.log(result);

So far our file structure for the Node.js app should look like this:

.
├── app.js
├── package-lock.json
├── package.json
└── rustlib
    └── libaddition_library.dylib

So, let’s take a closer look at the code:

  • const lib = ffi.Library("rustlib/libaddition_library.dylib", {...});This line loads the dynamic library file we generated from our Rust build. The ffi.Library method takes two arguments: the path to the library file, and an object that defines the functions in the library that can be called from JavaScript.
  • add_numbers: ["int", ["int", "int"]]This line defines a function called add_numbers in the loaded library. The function takes two int parameters and returns an int. The first element of the array ("int") specifies the return type of the function, and the second element of the array (["int", "int"]) specifies the types of the function’s two parameters.

If we had more functions we wanted to call from the library we could also specify them in the second parameter.

And finally, we can call the function and pass the required parameters.

const result = lib.add_numbers(5, 8);
console.log(result);

So, let’s try running the code with node app.js

And there you have it. We have written Rust and imported it into our Node.Js application.

Please share with your audience if you enjoyed reading this. Follow me on Twitter

If you have questions, please, ask in the comment.

Buy Me A Coffee

Published by Eze Sunday Eze

Hi, welcome to my blog. I am Software Engineer and Technical Writer. And in this blog, I focus on sharing my views on the tech and tools I use. If you love my content and wish to stay in the loop, then by all means share this page and bookmark this website.

2 comments on “Use Rust in a Node.js project”

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.