Começando
Comece com @napi-rs/cli
A Maneira recomendada.
Instale a cli
yarn global add @napi-rs/cli
# or
npm install -g @napi-rs/cli
# or
pnpm add -g @napi-rs/cli
Crie um projeto
napi new
Nome do pacote
O campo name no package.json
.
Escolha os alvos que deseja suportar
Plataformas que você desejar dar suporte.
Habilite GitHub actions
Gere a configuração do GitHub actions para você.
Aprofundamento
Aqui é recomendado distribuir seu pacote sob escopo npm (opens in a new tab) porque @napi-rs/cli
por padrão, anexa os diferentes sufixos de plataforma ao nome do pacote npm como o nome do pacote para a distribuição binária de plataforma diferente. O uso do escopo npm reduzirá a chance de o nome do pacote já estar em uso.
Por exemplo, se você quiser publicar o pacote @cool/core
, com suporte para macOS x64
, Windows x64
e Linux aarch64
, o @napi-rs/cli
criará e publicará quatro pacotes para você:
@cool/core
inclue apenas códigosJavaScript
, que na verdade carregam o binário nativo de cada plataforma.@cool/core-darwin-x64
para a plataformamacOS x64
.@cool/core-win32-x64
para a plataformaWindows x64
.@cool/core-linux-arm64-gnu
para a plataformaLinux aarch64
.
Em cada pacote binário de plataforma, há os campos cpu
e os
em seu package.json
:
{
"name": "@cool/core-darwin-x64",
"version": "1.0.0",
"os": ["darwin"],
"cpu": ["x64"]
}
E @cool/core
utiliza esses pacotes nativos como optionalDependencies
:
{
"name": "@cool/core",
"version": "1.0.0",
"optionalDependencies": {
"@cool/core-darwin-x64": "^1.0.0",
"@cool/core-win32-x64": "^1.0.0",
"@cool/core-linux-arm64": "^1.0.0"
}
}
E seu index.js
em @cool/core
será isso:
const { existsSync, readFileSync } = require('fs')
const { join } = require('path')
const { platform, arch } = process
let nativeBinding = null
let localFileExisted = false
let isMusl = false
let loadError = null
switch (platform) {
case 'darwin':
switch (arch) {
case 'x64':
localFileExisted = existsSync(join(__dirname, 'core.darwin-x64.node'))
try {
if (localFileExisted) {
nativeBinding = require('./core.darwin-x64.node')
} else {
nativeBinding = require('@cool/core-darwin-x64')
}
} catch (e) {
loadError = e
}
break
case 'arm64':
localFileExisted = existsSync(join(__dirname, 'core.darwin-arm64.node'))
try {
if (localFileExisted) {
nativeBinding = require('./core.darwin-arm64.node')
} else {
nativeBinding = require('@cool/core-darwin-arm64')
}
} catch (e) {
loadError = e
}
break
default:
throw new Error(`Unsupported architecture on macOS: ${arch}`)
}
break
// ...
default:
throw new Error(`Unsupported OS: ${platform}, architecture: ${arch}`)
}
if (!nativeBinding) {
if (loadError) {
throw loadError
}
throw new Error(`Failed to load native binding`)
}
const { plus100 } = nativeBinding
module.exports.plus100 = plus100
O arquivo index.js
gerado ajudará você a carregar o arquivo binário correto onde quer que esteja. E o index.js
lida com dois casos:
Pacote instalado nos node_modules
dos usuários
Para carregar o binário correto, a função index.js
tenta carregar todos os pacotes possíveis para essa plataforma (pode haver vários pacotes binários possíveis para uma determinada arquitetura de sistema e CPU), por exemplo, na plataforma Linux x64
, index.js
tenta carregar @cool/core-linux-x64-gnu
e @cool/core-linux-x64-musl
. O pacote @cool/core-linux-x64-gnu
será carregado se o usuário estiver usando um sistema operacional como Ubuntu
Debian
com gnu libc
pré-instalado. E se o usuário estiver usando um sistema operacional como Alpine
com musl libc
pré-instalado, então @cool/core-linux-x64-musl
será carregado.
Desenvolvimento local
O comando build
no package.json no projeto gerado pelo comando @napi-rs/cli
irá gerar a biblioteca de vínculo dinâmico binária compilada a partir do código Rust
no diretório atual para fins de depuração. index.js
também tentará carregar o binário correspondente do diretório atual nesse caso. Novamente, usando Linux x64
como exemplo, a função index.js
tentará carregar os arquivos core.linux-x64-gnu.node
e core.linux-x64-musl.node
sucessivamente.
Problema de suporte ao IDE
Caso sua IDE se recusa a autocompletar/surgerir automaticamente código ao usar o macro #[napi]
, você pode usar a seguinte configuração para corrigir isso:
Para vscode em settings.json
:
{
"rust-analyzer.procMacro.ignored": { "napi-derive": ["napi"] }
}
Para Neovim.
['rust-analyzer'] = {
procMacro = {
ignored = {
['napi-derive'] = { 'napi' },
},
},
},
Este problema pode emitir o seguinte erro no Rust Analyzer:
[ERROR proc_macro_api::msg] proc-macro tried to print : `napi` macro expand failed.
Comece a partir do GitHub template project
- Acesse o GitHub template project (opens in a new tab)
- Clique em Usar este modelo.
- Clone o seu projeto.
- Execute o comando
yarn install
para instalar as dependências. - Execute o comando
npx napi rename
na pasta do projeto para renomear o seu pacote.