第一個 neon 程式
neon nodejs rust -Why
強強聯手
How
如果沒有 rust,則先安裝 Rust。
一個 Neon 專案是一個 Node package,也是一個 Rust crate。
使用 npm init neon cpu-count 產生一個叫 cpu-count 的 Neon 專案目錄結構。
Rust 程式通常放在 src 目錄中。
設定檔 Cargo.toml 提供給 Neon 和 Rust 使用。
而 package.json 則是作為 nodejs 與整個程式的設定檔。
現在整的程式是空的,但卻是可以編譯的。
先利用 npm install 將需要的部分安裝起來。
package.json
{
  "name": "cpu-count",
  "version": "0.1.0",
  "description": "",
  "main": "index.node",
  "scripts": {
    "build": "cargo-cp-artifact -nc index.node -- cargo build --message-format=json-render-diagnostics",
    "build-debug": "npm run build --",
    "build-release": "npm run build -- --release",
    "install": "npm run build-release",
    "test": "cargo test"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "cargo-cp-artifact": "^0.1"
  }
}
根據 package.json,npm 會安裝 cargo-cp-artifact 套件並執行編譯。
這時會多出 target 目錄,這是 Rust 用來構建的目錄。
使用 cargo clean 可以清除這些編譯檔。
在根目錄下會多出 index.node,這是編譯最後的產物。
在 Rust 程式中只是簡單提供一個 hello 函式的接口,該函式被呼叫時會輸出一個 hello node 字串。
src/lib.rs
use neon::prelude::*;
fn hello(mut cx: FunctionContext) -> JsResult<JsString> {
    Ok(cx.string("hello node"))
}
#[neon::main]
fn main(mut cx: ModuleContext) -> NeonResult<()> {
    cx.export_function("hello", hello)?;
    Ok(())
}
現在讓我們在 nodejs 的 REPL 環境中執行編譯程式。
> require('.').hello()
// hello node
退出 nodejs 的 REPL 環境。
在 Cargo.toml 加入對 num_cpus 套件的依賴。
Cargo.toml
[dependencies]
num_cpus = "1"
增加一個函式 get_num_cpus,並將它導出。
src/lib.rs
// add get_num_cpus
fn get_num_cpus(mut cx: FunctionContext) -> JsResult<JsNumber> {
    Ok(cx.number(num_cpus::get() as f64))
}
#[neon::main]
fn main(mut cx: ModuleContext) -> NeonResult<()> {
    cx.export_function("hello", hello)?;
//  export function
    cx.export_function("get", get_num_cpus)?;
    Ok(())
}
然後借用
npm run build -- --release
重新編譯。
進入 nodejs 的 REPL 環境。
> const cpuCount = require('.')
> cpuCount.get()
// cpu num
這就是我們第一個 neon 。
功能是使用 nodejs 呼叫 rust 程式,取得 cpu 數量後回傳給 nodejs 程式。