一个简单的包
本教程将创建一个 napi-rs v3 插件,从 Node.js 调用它,并为项目配置 CI。请先完成前置条件。
创建项目
请选择一个你有权使用的包名。强烈建议使用 scope,因为发布工作流会为每个目标创建一个 npm 包。
以下命令使用 Yarn 模板,并为其他选项提供非交互式默认值:
npx @napi-rs/cli new cool \
--name @your-scope/cool \
--no-interactive
改用 pnpm 模板:
pnpm dlx @napi-rs/cli new cool \
--name @your-scope/cool \
--package-manager pnpm \
--no-interactive
运行命令前,请替换 @your-scope。如果希望交互式选择 Node-API 级别、目标、许可证和 CI 工作流,请省略 --no-interactive。
INFO
napi new 支持持续维护的 Yarn 和 pnpm 模板。它不会生成一个之后可随意切换包管理器的通用模板。
了解生成的项目
进入项目并安装依赖:
cd cool
yarn install
pnpm 模板请使用 pnpm install。最先会用到的文件有:
.
├── .github/workflows/CI.yml
├── Cargo.toml
├── build.rs
├── package.json
├── src/lib.rs
└── __test__/index.spec.ts
src/lib.rs是 Rust 插件源代码。Cargo.toml声明cdylib和 napi-rs v3 crate。build.rs调用 napi-rs 构建设置,必须保留在 crate 根目录。package.json包含 CLI 脚本与napi打包配置。.github/workflows/CI.yml构建并测试从模板保留的目标任务。
此时还没有 npm/。各平台构建完成后,发布任务会通过 napi create-npm-dirs 创建各平台包目录。
生成的 Rust 源代码导出了一个简单函数:
#![deny(clippy::all)]
use napi_derive::napi;
#[napi]
pub fn plus_100(input: u32) -> u32 {
input + 100
}
该宏会把 Rust 函数公开为 JavaScript 函数 plus100,并在构建时写入相应的 TypeScript 声明。
构建插件
为当前平台运行模板的 release 构建:
yarn build
pnpm 请运行 pnpm build。该脚本调用 napi build --platform --release,生成类似以下文件:
cool.darwin-arm64.node
index.js
index.d.ts
.node 的确切后缀取决于当前操作系统、架构和 ABI。例如 Linux glibc 构建使用 linux-x64-gnu。需要调试构建时使用 yarn build:debug。
生成的声明包含:
export declare function plus100(input: number): number
从 Node.js 调用原生函数:
node -e "const { plus100 } = require('./index.js'); console.log(plus100(42))"
输出为:
142
修改并测试 Rust API
在 src/lib.rs 中添加另一个导出函数:
#[napi]
pub fn multiply(left: i32, right: i32) -> i32 {
left * right
}
重新构建,然后验证运行时导出和生成的类型:
yarn build
node -e "const { multiply } = require('./index.js'); console.log(multiply(6, 7))"
在 __test__/index.spec.ts 中添加对应的 AVA 断言:
**test/index.spec.ts**
import test from 'ava'
import { multiply } from '../index'
test('multiply in native code', (t) => {
t.is(multiply(6, 7), 42)
})
运行测试:
yarn test
准备仓库
推送生成的工作流之前,请更新 package.json:
- 将
name设为你有权发布的包名和 scope。 - 将
repository设为最终 GitHub 仓库。npm provenance 会检查该元数据,因此不要保留模板仓库 URL。 - 检查
license、description、keywords、homepage和bugs。 - 检查
napi.targets。它控制包创建与发布,但每个目标仍需实际的 CI 构建任务。
如果之后更改包名或二进制名称,请使用 CLI,使 Cargo、包配置、CI 和生成的绑定名称保持一致:
yarn napi rename \
--name @your-scope/cool \
--binary-name cool \
--repository https://github.com/your-name/cool.git
然后创建并推送仓库:
git init
git add .
git commit -m "Create napi-rs package"
git branch -M main
git remote add origin git@github.com:your-name/cool.git
git push -u origin main
准备 npm 和 GitHub Actions
生成的工作流通过 npm 发布,并创建 GitHub release。对于其基于 token 的设置:
- 创建要使用的 npm scope 和包访问权限。
- 创建一个能发布根包和所有平台包的 npm automation token。
- 将其添加为
NPM_TOKENActions secret。 - 为 GitHub release 保留工作流的
contents: write权限,为 npm provenance 保留id-token: write权限。 - 尝试发布前,先确保普通 CI 路径成功运行。
WARNING
发布不是原子操作。napi pre-publish 会更新包元数据、发布平台包,并且可能在 npm 发布根包之前创建或更新 GitHub release。不要把真实凭据用于试运行。
请阅读发布原生包,了解完整的发布前检查、发布与恢复流程。确切的副作用和标志见 napi pre-publish。