Hello, World!

This guide will walk you through writing, building, and running your first Neon project. We’ll try to walk you through each step carefully, but if you want to skip ahead, you can always go straight to the full demo in the examples repository.

Our first project will be a tiny module that returns a number indicating how much hardware multithreading the current machine supports. If you’re not familiar with multithreading, don’t panic! We’ll be using Sean McArthur’s num_cpus library to do all the heavy lifting for us, and we’ll just return the number it gives us.

But even this simple example already demonstrates some of Neon’s usefulness: Rust’s crate ecosystem is younger than npm but growing quickly and already full of useful and unique libraries. A library like num_cpus could be useful, for example, as a hint for tuning the size of a Web Worker pool in an Electron app.

Creating a New Project

The first thing we have to do is create our new threading-hint Neon project:

$ neon new threading-hint

This will ask us a series of questions similar to the ones asked by npm new. When it completes, the tool will have created a threading-hint directory with the following layout:

├── .gitignore
├── README.md
├── lib/
│   └── index.js
├── native/
│   ├── Cargo.toml
│   └── src/
│       └── lib.rs
└── package.json

The first thing to notice about this layout is that a Neon project is a Node package. In other words, the way to think of a Neon project is:

Node on the outside, Rust on the inside.

The front-end of a Neon package is a pure JavaScript module (lib/index.js, by default), and the back-end is a native library implemented as a Rust crate. The Rust crate lives in the native/ subdirectory of the project.

Building and Running

We haven’t yet implemented anything, but just to see that neon new produced a complete, minimal Neon project, let’s try building it:

$ neon build

The build process generates a handful of files that you don’t need to work with directly:

An easy way to clean up build artifacts is to run:

$ neon clean

Once we’ve built the project, we can try running it:

$ node
> require('.')
hello node

Adding a Rust dependency

Let’s add a Rust dependency on the num_cpus crate. In native/Cargo.toml, under the [dependencies] section, add the following line:

num_cpus = "1.4.0"

This tells Cargo, Rust’s build tool, to fetch a version of the num_cpus crate that is semver-compatible with 1.4.0. (The package.json equivalent would be "num_cpus": "^1.4.0".)

Implementing our Function

Now let’s edit the Rust code to make use of the new dependency. First we have to declare the use of the the num_cpus crate:

extern crate num_cpus;

Next we can replace the sample hello function that was generated by neon new with the function we actually want. Instead of returning a string, our function should return a JavaScript number. So we’ll use the JsNumber::new() API. Since JsNumber expects a Rust f64 (i.e., a 64-bit floating-point number), and num_cpus::get() returns a usize (i.e., a pointer-sized integer), we’ll use Rust’s as operator to cast to convert the integer to floating-point:

use neon::js::JsNumber;

fn threading_hint(call: Call) -> JsResult<JsNumber> {
    Ok(JsNumber::new(call.scope, num_cpus::get() as f64))

A few more things to note about this code:

Finally, we’ll modify the code that neon new created for us to set up the module exports with this function instead of the initial “hello world” function it created for us:

register_module!(m, {
    m.export("threading_hint", threading_hint)

This tells Neon to initialize the module when it’s first loaded by creating a JavaScript function implemented with the threading_hint function we defined above and exporting it as a module property named "threading_hint".

You can see the full lib.rs file in the examples repository.

Exporting our Function

Now that the Rust code is implemented, all we have left to do is export it from the project’s public module. The native module exported a threading_hint property, so we’ll just make that function our entire public module:

var addon = require('../native');

module.exports = addon.threading_hint;

Try it Out!

Now we should be able to rebuild the project with neon build again:

$ neon build

Assuming we didn’t make any mistakes, we can test out our new Neon module at the Node console:

$ node
> var threadingHint = require('.')
> threadingHint()

Keep in mind that the result of calling threadingHint() will vary based on the machine you run this demo on—by design!