こんにちは!今回は、npmパッケージの作り方について学んだ内容をまとめてみました。特にReactコンポーネントをライブラリとして公開する方法を中心に、初心者にもわかりやすく解説していきます。
npmパッケージって何?
npmパッケージとは、簡単に言うと「みんなで使える便利なコードの塊」のことです。例えば、日付を扱うライブラリや、UIコンポーネントなど、一度作ったものを他の人も使えるように公開できる仕組みです。
事前準備:npmアカウントを作ろう
まずはnpm公式サイトでアカウントを作成します。
知っておきたいポイント:
- 無料プランではパブリック(公開)パッケージのみ作成可能
- プライベート(非公開)パッケージには有料プランが必要
- 個人開発なら基本的に無料プランで十分!
ステップ1:基本的なnpmパッケージを作ってみよう
プロジェクトの初期化
mkdir study-package
cd study-package
npm init --scope=@your-username
--scope
をつけることで、@your-username/package-name
という形式のパッケージが作れます。これの嬉しいポイントは:
- 名前の衝突を避けられる:
react-datepicker
という名前が取られていても、@your-username/react-datepicker
なら使える - ブランド化:自分専用の名前空間ができる
package.jsonの重要なポイント
{
"name": "@your-username/study-package",
"version": "0.1.0",
"main": "index.js",
"scripts": {
"build": "tsc"
}
}
バージョンについて:
0.1.0
から始めるのが一般的(完成前のため)- 左から順に:メジャー.マイナー.パッチ
- 開発中は主にマイナーとパッチを上げていく
簡単なサンプルを作成
// index.js
console.log("Hello");
パッケージを公開
npm publish --access public
注意: 無料プランでは--access public
が必須です!
ステップ2:TypeScriptに対応させよう
TypeScriptの導入
npm install --save-dev typescript
npx tsc --init
ES Modulesに対応
// index.mjs (ES Modules用)
export function sayHello() {
console.log("Hello World");
}
ポイント:
.mjs
拡張子でES Modulesとして認識されるrequire
ではなくimport/export
を使用- package.jsonの
main
もindex.mjs
に変更が必要
TypeScriptファイルの作成
// src/index.ts
export function sayHello(): void {
console.log("Hello World");
}
ビルド設定(tsconfig.json)
{
"compilerOptions": {
"target": "ES2016",
"module": "ESNext",
"outDir": "./dist",
"declaration": true,
"jsx": "react"
},
"include": ["src/**/*"]
}
重要: declaration: true
を忘れずに!これで型定義ファイル(.d.ts)も一緒に生成されます。
ステップ3:Reactコンポーネントライブラリを作ろう
必要なパッケージをインストール
npm install react react-dom
npm install --save-dev @types/react @types/react-dom
Reactコンポーネントの作成
// src/index.tsx
import React from 'react';
export const HelloComponent: React.FC = () => {
return <div>Hello World</div>;
};
Rollupを使ったビルド設定
Reactコンポーネントをビルドするには、TypeScriptコンパイラだけでは不十分です。ここでRollupの登場です。
Rollupとは?
- ES Modulesネイティブなバンドラー
- ライブラリ開発に特化
- Tree-shakingが優秀
- Webpackよりもライブラリビルドに適している
WebpackとRollupの違い:
- Webpack: アプリケーション開発向け、CommonJS時代から存在
- Rollup: ライブラリ開発向け、ES Modulesネイティブ
Rollupの設定
npm install --save-dev rollup @rollup/plugin-node-resolve @rollup/plugin-commonjs @rollup/plugin-typescript tslib
// rollup.config.mjs
import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import typescript from '@rollup/plugin-typescript';
import pkg from './package.json' assert { type: 'json' };
export default {
input: 'src/index.tsx',
output: [
{
file: pkg.main,
format: 'cjs',
sourcemap: true,
},
{
file: pkg.module,
format: 'esm',
sourcemap: true,
},
],
plugins: [
resolve(),
commonjs(),
typescript({
tsconfig: './tsconfig.json',
}),
],
};
プラグインの役割:
resolve
: node_modulesの依存関係を解決commonjs
: CommonJS形式のライブラリを読み込み可能にtypescript
: TypeScriptのコンパイル
package.jsonの調整
{
"name": "@your-username/study-package",
"version": "0.1.0",
"main": "dist/cjs/index.js",
"module": "dist/esm/index.js",
"types": "dist/index.d.ts",
"files": ["dist"],
"scripts": {
"build": "rollup -c",
"publish:patch": "npm version patch && npm publish --access public",
"publish:minor": "npm version minor && npm publish --access public",
"publish:major": "npm version major && npm publish --access public"
},
"devDependencies": {
"typescript": "^4.9.5",
"rollup": "latest",
"@rollup/plugin-node-resolve": "latest",
"@rollup/plugin-commonjs": "latest",
"@rollup/plugin-typescript": "latest",
"tslib": "latest"
},
"peerDependencies": {
"react": ">=16.8.0",
"react-dom": ">=16.8.0"
}
}
重要なフィールド:
main
: CommonJS形式のエントリーポイントmodule
: ES Modules形式のエントリーポイントtypes
: TypeScript型定義ファイルfiles
: 配布に含めるファイルpeerDependencies
: ユーザー側でインストールしてもらう依存関係
ステップ4:不要ファイルを除外しよう
.npmignoreの作成
src/
tsconfig.json
rollup.config.mjs
.git/
node_modules/
*.log
これにより、ソースファイルや設定ファイルがパッケージに含まれなくなります。
メリット:
- パッケージサイズの削減
- セキュリティの向上
- ユーザーの混乱を防げる
バージョン管理のベストプラクティス
セマンティックバージョニング
バージョン番号はメジャー.マイナー.パッチ
の形式で管理します:
- パッチ: バグ修正(0.1.0 → 0.1.1)
- マイナー: 機能追加(0.1.0 → 0.2.0)
- メジャー: 破壊的変更(0.1.0 → 1.0.0)
npmコマンドでバージョンアップ
npm version patch # 0.1.0 → 0.1.1
npm version minor # 0.1.0 → 0.2.0
npm version major # 0.1.0 → 1.0.0
便利なスクリプト
{
"scripts": {
"build": "rollup -c",
"publish:patch": "npm version patch && npm publish --access public",
"publish:minor": "npm version minor && npm publish --access public",
"publish:major": "npm version major && npm publish --access public"
}
}
実際に使ってみよう
テストプロジェクトでの確認
mkdir test-project
cd test-project
npm init -y
npm install @your-username/study-package
Next.jsプロジェクトでの使用例
npx create-next-app@latest test-app --typescript
cd test-app
npm install @your-username/study-package
// pages/index.tsx
import { HelloComponent } from '@your-username/study-package';
export default function Home() {
return (
<div>
<h1>Welcome to Next.js</h1>
<HelloComponent />
</div>
);
}
よくあるトラブルと解決方法
1. 型定義が見つからない
症状: TypeScriptで型エラーが出る
解決方法:
tsconfig.json
でdeclaration: true
を設定package.json
でtypes
フィールドを正しく指定
2. ビルドが失敗する
症状: npm run build
でエラー
解決方法:
- 必要な依存関係がインストールされているか確認
tslib
がインストールされているか確認- Rollup設定ファイルの構文をチェック
3. パッケージが見つからない
症状: npm publish
後にインストールできない
解決方法:
--access public
オプションを付けているか確認- npmレジストリへの反映に時間がかかる場合がある(数分待つ)
高度な設定
複数の出力形式に対応
// rollup.config.mjs
export default {
input: 'src/index.tsx',
output: [
// CommonJS
{
file: 'dist/cjs/index.js',
format: 'cjs',
sourcemap: true,
},
// ES Modules
{
file: 'dist/esm/index.js',
format: 'esm',
sourcemap: true,
},
// UMD (ブラウザでも使える)
{
file: 'dist/umd/index.js',
format: 'umd',
name: 'MyLibrary',
sourcemap: true,
},
],
// ...
};
外部依存関係の処理
// rollup.config.mjs
export default {
// ...
external: ['react', 'react-dom'],
output: {
// ...
globals: {
react: 'React',
'react-dom': 'ReactDOM',
},
},
};
まとめ:学んだポイント
- npm initでプロジェクト初期化(
--scope
でネームスペース作成) - TypeScriptで型安全なライブラリ開発
- RollupでReactコンポーネントのビルド
- CommonJSとES Modules両対応で互換性確保
- 型定義ファイルで開発者体験向上
- npmignoreで配布ファイルの最適化
- セマンティックバージョニングで適切なバージョン管理
次のステップ
機能拡張
- より複雑なコンポーネントの作成
- Tailwind CSSとの組み合わせ
- テーマシステムの実装
開発環境改善
- Storybookでコンポーネントカタログ作成
- Jestでユニットテスト導入
- Cypressでインテグレーションテスト
CI/CD構築
- GitHub Actionsで自動ビルド・テスト
- 自動リリース機能
- コードカバレッジ測定
ドキュメント整備
- README.mdの充実
- JSDocでAPI仕様書作成
- 使用例の追加
おわりに
ライブラリ開発は最初は複雑に感じますが、一度慣れてしまえば自分の作ったコンポーネントを世界中の人に使ってもらえる素晴らしい体験です。
実際に有名なOSSライブラリにコントリビュートしている開発者の中には、海外企業からオファーをもらったり、国内でも高い評価を受けているケースがあります。
まずは小さなライブラリから始めて、徐々に機能を拡張していきましょう。皆さんの作るライブラリが、誰かの開発を助ける日が来ることを楽しみにしています!
ぜひチャレンジしてみてください!🚀