🗂

GitHub Packages 導入フロー

に公開

はじめに

本ドキュメントでは、企業内リポジトリから Private パッケージとして配信し、同じ企業内の別リポジトリからそれを受信して利用する一連の流れを解説します。
特に React + Vite + TypeScript + MUI 6 + Tailwind + Storybook の構成を前提に、MUI 6 のテーマ (theme.ts)カスタムコンポーネント を配布するパターンを中心として、型定義 (d.ts) のビルド / 読み込みGitHub Token 設定パッチアップデート の運用・自動化に触れます。

これは GitHub Packages を用いた プライベートパッケージ の作成・配信・受信・運用までながれ、概要をまとめたドキュメントです。

React / Vite / TypeScript / MUI 6 / Tailwind / Storybook といった環境で、MUI 6 のテーマ (theme.ts)カスタムコンポーネント (CustomComponent) を中心に配信するケースを例に、以下の内容を解説します。

  • GitHub Packages の基本概念・リポジトリ構成
  • GitHub Token (PAT) の設定
  • パッケージの公開(配信側)
  • パッケージの利用(受信側)
  • 型定義(.d.ts)のビルドと解決
  • MUI 6 + Tailwind + Storybook との連携 *現在MUI7がリリースされました
  • パッチアップデートの戦略(バージョン管理や自動化)
  • トラブルシューティング

2025/03/05 時点

GitHub Packages の基本概念

GitHub Packages は、GitHub が提供するパッケージレジストリサービスです。npm (JavaScript)、Docker、NuGet (.NET) などをサポートしています。本ガイドでは npm 形式にフォーカスします。

  • パッケージ名: @組織名/パッケージ名 の形式
  • アクセス制御:
    • パブリック: 誰でもインストール可能
    • プライベート: リポジトリや Organization の権限に応じた制限
  • 必要な権限スコープ:
    • read:packages / write:packages (パッケージ操作)
    • repo (プライベートリポジトリの場合)

環境準備

  • Node.js: v16 以上推奨
  • パッケージマネージャ: npm / yarn / pnpm (ここでは pnpm や npm を例示)
  • React, Vite, TypeScript, MUI 6, Tailwind, Storybook: バージョンは互換性に注意

GitHub Token の設定

1. PAT (Personal Access Token) の作成

  1. GitHub の「Settings」→「Developer settings」→「Personal access tokens (classic)」
  2. 「Generate new token (classic)」を押し、以下のスコープを付与
    • read:packages, write:packages
    • repo (プライベートリポジトリに紐づく場合)
  3. トークンをコピーし、安全に保管

2. トークンのセキュリティ運用

  • Git リポジトリなどに絶対コミットしない
  • Slack 等の公開チャンネルに貼らない
  • 定期的にトークンをローテーション (再生成)

パッケージの公開(配信側)

ディレクトリ構成

配信側は以下のような構成を想定します。
(名前やフォルダ構成はプロジェクトに合わせて調整可)

my-design-system/
├── src/
│   ├── components/
│   │   └── CustomComponent.tsx
│   ├── theme/
│   │   └── theme.ts
│   └── index.ts
├── dist/               # ビルド成果物(最終的に配布)
├── package.json
├── tsconfig.json
├── vite.config.ts
├── .npmrc            # 任意(配信専用)
└── ...               # その他のファイル

package.json の設定

{
  "name": "@your-org/my-design-system",
  "private": false,
  "version": "0.1.0",
  "files": ["dist"],
  "main": "dist/index.js", // CommonJS 用
  "module": "dist/index.es.js", // ESM 用
  "types": "dist/index.d.ts", // 型定義
  "type": "module",
  "publishConfig": {
    "registry": "https://npm.pkg.github.com/"
    // "access": "restricted" // → Private用 (指定しない場合もOK)
  },
  "scripts": {
    "build": "vite build && tsc --emitDeclarationOnly --outDir dist",
    "prepublishOnly": "npm run build"
  },
  "peerDependencies": {
    "react": "^18.0.0",
    "react-dom": "^18.0.0",
    "@mui/material": "^6.0.0"
  },
  "devDependencies": {
    "typescript": "^5.0.0",
    "vite": "^4.0.0",
    "vite-plugin-dts": "^3.7.0"
    // ...
  }
}
  • private: false: npm で公開禁止を回避(GitHub Packages には関係なくパブリッシュ可能)
  • publishConfig.registry: GitHub Packages の URL
  • access: プライベートにしたい場合は "restricted"、一時的にパブリックなら "public"
  • files: dist のみ配布
  • types: dist/index.d.ts へのパス

.npmrc の設定

配信側でローカルから npm publish / pnpm publish する場合は、GitHub Packages 用に .npmrc を設定します。

@your-org:registry=https://npm.pkg.github.com
//npm.pkg.github.com/:_authToken=${GITHUB_TOKEN}
always-auth=true
  • ${GITHUB_TOKEN} はシェルの環境変数として設定
    export GITHUB_TOKEN=ghp_XXXXXXXXXXXXXXXX
    

ビルド & 型定義ファイルの生成

1. Vite + tsc の利用

  • vite.config.ts でライブラリ出力設定 (ESM)
  • tsconfig.jsondeclaration: trueemitDeclarationOnly: falseoutDir: "dist"
  • vite-plugin-dts を利用するとビルド時に .d.ts を自動生成可能

2. エントリーポイント

// src/index.ts
export { theme } from './theme/theme'
export { CustomComponent } from './components/CustomComponent'

プライベートパッケージとして公開 (Publish)

  1. バージョンを更新 (パッチアップなど)

    npm version patch   # or pnpm version patch
    
  2. 公開

    npm publish --registry=https://npm.pkg.github.com
    

    または

    pnpm publish --registry=https://npm.pkg.github.com
    

GitHub Actions で自動化

# .github/workflows/publish.yml
name: Publish Package
on:
  push:
    branches: ['main']

jobs:
  publish:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-node@v3
        with:
          node-version: '18'
          registry-url: 'https://npm.pkg.github.com'
          scope: '@your-org'

      - name: Install
        run: npm ci

      - name: Build
        run: npm run build

      - name: Publish
        run: npm publish
        env:
          NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

パッケージの利用(受信側)

.npmrc の設定 (利用側)

受信側のプロジェクトでも、同様に .npmrc や環境変数を設定します。

@your-org:registry=https://npm.pkg.github.com
//npm.pkg.github.com/:_authToken=${GITHUB_TOKEN}
always-auth=true

ここで export GITHUB_TOKEN=ghp_XXXXXXXX をローカル、または CI/CD 環境変数として指定。

インストール

pnpm add @your-org/my-design-system
# または npm install @your-org/my-design-system

peerDependencies にある MUI や React が未インストールの場合、そちらも合わせてインストールしてください。

React + MUI 6 + Tailwind への導入例

// App.tsx
import React from 'react'
import { createRoot } from 'react-dom/client'
import { ThemeProvider } from '@mui/material/styles'
import { theme, CustomComponent } from '@your-org/my-design-system'

const App = () => {
  return (
    <ThemeProvider theme={theme}>
      <div className="tw-bg-gray-100 tw-p-4">
        <h1>Hello MUI + Tailwind!</h1>
        <CustomComponent label="Click me" variant="contained" />
      </div>
    </ThemeProvider>
  )
}

createRoot(document.getElementById('root')!).render(<App />)
  • tailwind.config.jsprefix: 'tw-' などを設定し、MUI とのクラス名衝突を回避する方法もあります。

Storybook への導入例

// .storybook/preview.ts
import { type Preview } from "@storybook/react";
import { ThemeProvider } from "@mui/material/styles";
import { theme } from "@your-org/my-design-system";

const preview: Preview = {
  decorators: [
    (Story) => (
      <ThemeProvider theme={theme}>
        <Story />
      </ThemeProvider>
    )
  ]
};

export default preview;
// src/stories/CustomComponent.stories.ts
import { type Meta, type StoryObj } from "@storybook/react";
import { CustomComponent } from "@your-org/my-design-system";

const meta: Meta<typeof CustomComponent> = {
  title: "UI/CustomComponent",
  component: CustomComponent
};
export default meta;

type Story = StoryObj<typeof CustomComponent>;
export const Primary: Story = {
  args: {
    label: "Hello Storybook"
  }
};

型定義の解決方法

1. パッケージ側の型定義設定

  • tsconfig.jsondeclaration: true, emitDeclarationOnly: false, outDir: dist
  • package.jsontypes フィールドを "dist/index.d.ts" に設定
  • エントリーポイント (src/index.ts) で export をまとめておく

2. MUI 6 のテーマ型拡張

// src/theme/theme.ts
import { createTheme, Theme as MuiTheme } from '@mui/material/styles'

declare module '@mui/material/styles' {
  interface Theme {
    custom: {
      borderRadius: number
    }
  }
  interface ThemeOptions {
    custom?: {
      borderRadius?: number
    }
  }
}

export const theme = createTheme({
  palette: {
    primary: {
      main: '#1976d2',
    },
  },
  custom: {
    borderRadius: 8,
  },
})

export type CustomTheme = MuiTheme

利用側で ThemeProvider を用いた際に、theme.custom.borderRadius など拡張型が認識されます。

パッチアップデートの自動化戦略

バージョンの自動付与と CI/CD

コミットやプルリクに feat: / fix: / BREAKING CHANGE などを含める Conventional Commits と連携させ、GitHub Actions で自動的にバージョンアップ・リリースノート生成・npm publish を行う仕組みが一般的です。

# 例: semantic-release や changesets を使う
- name: Release
  run: npx changeset publish

Renovate / Dependabot などによる依存関係管理

  • RenovateDependabot を使ってパッケージ依存を自動更新
  • 自社スコープのパッケージ (@your-org/xxx) のバージョンを監視し、プルリクを自動生成

Conventional Commits と変更ログの自動生成

  • feat:, fix:, perf:, refactor:, chore:, docs: など
  • メジャー変更には feat!:BREAKING CHANGE: を含む
  • standard-version / semantic-release により CHANGELOG.md を自動更新

トラブルシューティング

パッケージのインストールに失敗する(401, 404)

npm ERR! 401 Unauthorized: @your-org/my-design-system
# or
npm ERR! 404 Not Found: @your-org/my-design-system

主な原因と対策:

  1. トークンの権限不足: read:packagesrepo がない
  2. .npmrc が正しく設定されていない:
    • @your-org:registry=https://npm.pkg.github.com
    • //npm.pkg.github.com/:_authToken=${GITHUB_TOKEN}
  3. 環境変数 GITHUB_TOKEN が設定されていない:
    • echo $GITHUB_TOKEN で確認

型定義が解決されない

TS2307: Cannot find module '@your-org/my-design-system' or its corresponding type declarations.

原因:

  1. 配信側のビルド設定で .d.ts が生成されていない
  2. package.jsontypes フィールド未指定
  3. 利用側の tsconfig.json でモジュール解決設定 (moduleResolution, esModuleInterop) が不適切

MUI テーマが適用されない

  • ThemeProvider でラップしているか
  • テーマ拡張 (declare module) が正しく行われているか
  • カスタムプロパティを参照している箇所を要チェック

Tailwind スタイルが衝突・適用されない

  • Tailwind と MUI が両方 reset やスタイルを上書きするケース
  • tailwind.config.jsprefix: 'tw-'corePlugins: { preflight: false } を検討
  • MUI コンポーネントに渡す className は最終的な優先度に注意

まとめと参考リンク

本ドキュメントでは、企業内プライベートパッケージを GitHub Packages で作成・配信・受信する流れを、React + Vite + TS + MUI6 + Tailwind + Storybook を例に解説しました。特に以下の点に留意して運用するとスムーズです:

  1. 配信側

    • package.json で適切な publishConfigfiles, types を設定
    • .npmrc とトークン (PAT) 設定
    • 型定義 を含むビルドを行い、pnpm/npm publish → GitHub Packages へアップロード
    • (必要に応じて "access": "restricted" で Private 化)
  2. 利用側

    • 同じく .npmrc と環境変数 (PAT) をセット
    • pnpm add @your-org/my-design-system でインストール
    • ThemeProviderCustomComponent を import して利用
    • Storybook 環境でも同様に設定
  3. パッチアップデート・自動化

    • semantic-releasechangesets, Renovate 等を使い、バージョン管理・リリースを効率化
    • リポジトリ間で型定義やテーマ変更の追従を容易に

参考リンク

以上で、GitHub Packages によるプライベートパッケージの配信から受信までの概説と、MUI6 / Tailwind / Storybook との連携に関するガイドを終わります。各プロジェクトでの実装方針や権限設定にあわせて、適宜アレンジしながらご利用ください。

Discussion