Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Go製CLIツールをnpmで配布するには

Avatar for syumai syumai
July 28, 2025

 Go製CLIツールをnpmで配布するには

『GopherのためのCLIツール開発』最新事情 LT @Findy TECH BATON (2025/7/28) の資料です。
https://findy.connpass.com/event/362163/

Avatar for syumai

syumai

July 28, 2025
Tweet

More Decks by syumai

Other Decks in Programming

Transcript

  1. 自己紹介 syumai ECMAScript 仕様輪読会 / Asakusa.go 主催 株式会社ベースマキナで管理画面のSaaS を開発中 Go

    でGraphQL サーバー (gqlgen) や TypeScript でフロント エンドを書いています Software Design 2023 年12 月号から2025 年2 月号まで Cloudflare Workers の連載をしました Twitter ( 現𝕏): @__syumai Website: https://syum.ai
  2. npm

  3. npm Node.js のpackage manager https://npmjs.com Node.js をインストールすると一緒についてくる コード内で使うpackage だけでなく、コマンドも配布可能 npm

    install -g {コマンド名} # グローバルにコマンドをインストール npx {コマンド名} # インストールせずにコマンドを実行 (or プロジェクト内実行) # bunx {コマンド名} / deno run npm:{コマンド名} でも使える
  4. 配布方法のPros / Cons Pros 1. Wasm で配布 アーキテクチャに縛られない 2. 各OS/

    アーキテクチャ向けのビルド済みバイナリで配布 CGO が使える OS の機能がフルに使える 高パフォーマンス
  5. 配布方法のPros / Cons Cons 1. Wasm で配布 CGO が使えない 使えるOS

    の機能が限定される 仕組み上、比較的低パフォーマンスになりやすい goroutine がJS ランタイム上でシングルスレッドで動くなど 2. 各OS/ アーキテクチャ向けのビルド済みバイナリで配布 ビルド・配布がやや面倒 GoReleaser などで楽はできる JS / Wasm に閉じないので、optionalDependencies / postinstal script といった仕 組みを使う必要がある
  6. xidgen をnpm に公開した手順 1. package.json を追加 2. Wasm にビルド 3.

    wasm_exec.js とwasm_exec_node.js を追加 4. wasm_exec_node.js を修正 5. package.json に bin の設定を追加 6. npm publish で公開
  7. 2. Wasm にビルド GOOS=js GOARCH=wasm でビルドするコマンドをpackage.json に入れます npm run build

    で実行できます { "name": "xidgen", "version": "0.1.0", "scripts": { "build": "GOOS=js GOARCH=wasm go build -o ./main.wasm ." } // ... } GOOS=wasip1 GOARCH=wasm でビルドする方法もあるが、Node.js の node:wasi はま だExperimental (2025 年7 月28 日時点) https://nodejs.org/api/wasi.html
  8. 3. wasm_exec.js とwasm_exec_node.js を追加 以下が golang/go リポジトリに含まれている wasm_exec.js Go のWasm

    をブラウザ / Node.js で実行するための設定を行うスクリプト wasm_exec_node.js Go のWasm をNode.js で実行するエンドポイントのスクリプト 上記2 ファイルを取得する https://github.com/golang/go/tree/go1.24.5/lib/wasm (Go 1.24.5 の場合) または、 $GOROOT/lib/wasm から cp で取得するのも可 ( この方が楽かも)
  9. 4. wasm_exec_node.js を修正 修正その1 以下の引数のカウント、引数のslice 処理を直す // Wasmバイナリのパスは固定なので、引数の最低数を数える必要がない if (process.argv.length

    < 3) { console.error("usage: go_js_wasm_exec [wasm binary] [arguments]"); process.exit(1); } const go = new Go(); // Wasmのパスの指定が含まれないので、`2`だと除外しすぎになる // 引数を使わないコマンドなら、行ごと消してOK go.argv = process.argv.slice(2);
  10. 4. wasm_exec_node.js を修正 修正その2 コマンドライン引数からWasm バイナリのパスを受け取る箇所がある WebAssembly.instantiate(fs.readFileSync(process.argv[2]), go.importObject) これを、直接指定する形に直す //

    Wasmバイナリはpackageに同梱されている const wasmPath = path.resolve(__dirname, "./main.wasm"); WebAssembly.instantiate(fs.readFileSync(wasmPath), go.importObject)
  11. 5. package.json に bin を追加 wasm_exec_node.js を実行する形で設定する { "name": "xidgen",

    "version": "0.1.0", "scripts": // ... "bin": { "xidgen": "wasm_exec_node.js" }, // ... }
  12. 6. npm publish する publish に成功すると、npm install できるようになる publish 結果の例

    http://npmjs.com/package/xidgen ※ *.wasm を .gitignore に入れると、( .npmignore が無いときに) npm package に 入らないので、別で .npmignore を作った方がいいです