はじめに
この記事はnpmパッケージを公開する前に、確認するべきポイントを記録、共有するためのものです。パッケージを公開する前のチェックリストとしてご利用ください。
前提とする読者
- JavaScript / TypeScriptの開発経験がある
- GitHubを利用している
- npmのアカウントを持っている
この記事ではnpm自体の解説やアカウントの作成方法については取り扱いません。
前提とする環境
- node.js v18.15.0
- npm v9.5.0
- TypeScript v5.1.3
対象となるパッケージのメジャーバージョンが変わると、記事の内容がそのまま適用できないかもしれません。記事を読む前に、お手元の環境をご確認ください。
この記事と記事内のサンプルコードは、npmパッケージを一般公開することを前提に書かれています。プライベートnpmパッケージを作成する場合は、サンプルコードをそのまま利用せず読み替えてください。
package.json
package.jsonはnpmパッケージの公開に必要な情報を含んでいます。公開前にファイルをメンテナンスしましょう。
npm initからはじめる
package.jsonをテンプレートから作成している場合、npmに公開するためのフィールドが抜けているかもしれません。npm init
コマンドはpackage.jsonがすでに作成されているプロジェクトでも再実行でき、必要なフィールドを対話式で追加してくれます。
npm init --scope=[あなたのnpmユーザー名]
パッケージ名にはスコープをつける
パッケージ名のスコープはnpm v6から導入された仕組みです。これから公開するパッケージには原則としてスコープをつけましょう。
versionは0.1.0から
npmに公開するパッケージはセマンティックバージョニングのルールに従いましょう。バージョン1.0.0は、APIの仕様が固まったリリース版です。もしあなたのパッケージが初期開発フェーズにあり、今後も破壊的なAPIの変更があるならバージョンは0.1.0から開始しましょう。
0.y.zのような初期の開発フェーズにおけるバージョンの取り扱いはどのようにすべきでしょうか?
一番簡単な方法は0.1.0からで開発版をリリースし、その後のリリースのたびにマイナーバージョンを上げていけばよいでしょう。
filesフィールドを追加する
package.jsonのfilesフィールドは、npmで公開するファイルを指定するための設定です。単体テストファイルやトランスパイル前のソースファイルは、パッケージの動作に必要ではありません。動作に必要のないファイルは積極的に除外しましょう。
README
READMEはユーザーがパッケージを理解するために最初に触れる情報です。ユーザーの視点に合わせてREADMEの情報を整理、追加しましょう。
ユーザーが一番知りたい情報はライセンス
パッケージを利用しようと考えるユーザーがもっとも欲しい情報は、ライセンスの形態です。READMEには必ずライセンスを明記しましょう。また、ライセンス表記をREADMEの先頭に表示するためにバッジを利用することも検討してください。
文章よりも画像、画像よりも動画
パッケージを一般公開する場合、ユーザーはそのパッケージの背景となる情報を共有していません。あなたのパッケージの核となる機能を、文章だけではなく画像や動画を使って説明しましょう。核となる機能を読み取れなかったユーザーは、ごく短時間であなたのリポジトリから離脱します。
CI/CD
GitHub ActionsはGitHubの提供するCI/CD環境です。まずは最低限のテスト環境を構築し、その後は徐々にあなたのプロジェクトに機能を取り込んでいきましょう。
tsc
だけのテストでもないよりはずっといい
あなたがTypeScriptでパッケージの開発を行なっている場合、最初の一歩としてtsc
コマンドをCI/CD環境に組み込みましょう。後述するブランチ保護ルールと併用することで、ビルド不可能なコードのマージを防げます。
単体テストを追加していく
最低限のCI環境が構築できたら、Jestなどのテスティングフレームワークを導入していきましょう。テストを書くことで、パッケージの品質を維持できるほか、破壊的な変更とバージョン変更のタイミングを明確化できます。
GitHubの機能を取り込んでいく
テスト環境が整ったら、次はGitHub Actionsをテスト以外の処理にも利用していきましょう。
npm publish
手動でnpmの公開コマンド実行はヒューマンエラーの原因となります。GitHub Actionsを利用して、リリース操作をトリガーとして自動化しましょう。
まずはnpmのアクセストークンをGitHubのシークレットに登録します。
gh secret set NPM_TOKEN --body "あなたのnpmシークレット"
次にワークフローファイルを作成します。
▼.github/workflows/npm_publish.yml
name: Publish to NPM
on:
release:
types: [created]
jobs:
npm-publish:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Use Node.js
uses: actions/setup-node@v3
with:
node-version: "18"
cache: "npm"
registry-url: "https://registry.npmjs.org"
- run: npm ci
- run: npm run build
- name: Publish package on NPM 📦
run: npm publish --access public
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
GitHub上でリリースを作成すると、その操作をトリガーにワークフローが起動します。事前に登録されたアクセストークンをもとに、npmにパッケージを公開します。
Dependabot
Dependabotは、GitHubのセキュリティ自動化ツールです。Dependabotは依存パッケージに更新版がある場合、自動でバージョンアップ用のプルリクエストを作成します。依存パッケージの更新はパッケージの維持に欠かせない作業です。プルリクエスト作成をトリガーにテストを実行すれば、依存パッケージの更新がパッケージを破壊しないかを検証しながら作業を進められます。
公式ドキュメントのサンプルをもとに、Dependabotの設定ファイルを作成し、.github/dependabot.yml
に保存します。
▼.github/dependabot.yml
version: 2
updates:
# Maintain dependencies for GitHub Actions
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
# Maintain dependencies for npm
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "weekly"
これで、ワークフロー内で利用してるアクションと、npmパッケージの更新が1週間に1回確認されます。確認頻度はinterval
で変更できますので、あなたのパッケージの性質に合わせて調整してください。
branch protection rule(ブランチ保護ルール)
ブランチ保護ルールは、指定したブランチに対して特定の操作を禁止する機能です。
- デフォルトブランチへの直接プッシュを禁止
- テストを通過していないプルリクエストのマージを禁止
- ブランチの削除を禁止
などに利用できます。
ブランチ保護ルールは誤操作によるデフォルトブランチの破壊を防ぎます。公開パッケージの価値はユーザーと開発者の信頼感によって成り立っています。ブランチ保護はユーザーとの信頼感を維持するために欠かせません。
パッケージの粒度
大きすぎるよりも小さすぎるほうがずっといい
パッケージを開発している間に「こんな機能があったらいいのではないか」というアイデアが湧いてくると思います。そうした場合、その機能は別のパッケージに切り分けられないかと考えてみてください。パッケージを小さく保つことは、メンテナンス性を引き上げます。
GitHub Actionsの機能向上によって、複数のパッケージを維持する作業が簡単になりました。パッケージが肥大化しそうな場合は切り分けを検討してみてください。
個人的な感想
npmやGitHub Actionsには膨大な機能があります。パッケージ公開の作業を通じて、なぜその機能が必要だったのかの理解が進みました。「このコードまた書いてるな」と思ったあなたは、ぜひパッケージを公開してみてください。
以上、ありがとうございました。