CI/CD

Knipで不要なexport・依存関係を自動検出する導入ガイド

未使用のexport、依存関係、ファイルを検出・削除するツールKnipの導入方法をステップバイステップで解説

プロジェクトが成長するにつれ、使われなくなったexportや依存関係が蓄積されていきます。Knipは、これらの不要なコードを自動で検出し、プロジェクトをクリーンに保つためのツールです。

Knipとは

Knipは、JavaScript/TypeScriptプロジェクトにおいて以下を検出するツールです:

  • 未使用のファイル: どこからも参照されていないファイル
  • 未使用のexport: エクスポートされているが使われていない関数・変数・型
  • 未使用の依存関係: package.jsonに記載されているが使われていないパッケージ
  • 不足している依存関係: コードで使用されているがpackage.jsonに記載されていないパッケージ

ステップ1: インストール

自動セットアップ(推奨)

最も簡単な方法は、対話型セットアップを使用することです:

# npm
npm init @knip/config

# pnpm
pnpm create @knip/config

# bun
bun create @knip/config

# yarn
yarn create @knip/config

このコマンドは、プロジェクトを分析して適切な設定ファイルを自動生成します。

手動インストール

より細かい制御が必要な場合は、手動でインストールできます:

# npm
npm install -D knip typescript @types/node

# pnpm
pnpm add -D knip typescript @types/node

# bun
bun add -D knip typescript @types/node

# yarn
yarn add -D knip typescript @types/node

ステップ2: 設定ファイルの作成

プロジェクトルートに設定ファイルを作成します。JSON形式またはTypeScript形式が使用できます。

JSON形式(knip.json)

{
  "$schema": "https://unpkg.com/knip@latest/schema.json",
  "entry": ["src/index.ts"],
  "project": ["src/**/*.ts"]
}

TypeScript形式(knip.config.ts)推奨

型安全性と動的な設定が可能です:

import type { KnipConfig } from 'knip';

const config: KnipConfig = {
  entry: ['src/index.ts'],
  project: ['src/**/*.ts'],
};

export default config;

ステップ3: Next.jsプロジェクトの設定

Next.jsプロジェクトでは、Knipが自動的にNext.jsプラグインを有効化します。ただし、カスタムエントリーポイントがある場合は明示的に設定できます:

{
  "$schema": "https://unpkg.com/knip@latest/schema.json",
  "next": {
    "entry": ["next.config.ts", "src/app/**/*.tsx", "src/pages/**/*.tsx"]
  }
}

App Routerを使用している場合

import type { KnipConfig } from 'knip';

const config: KnipConfig = {
  entry: [
    'src/app/**/page.tsx',
    'src/app/**/layout.tsx',
    'src/app/**/loading.tsx',
    'src/app/**/error.tsx',
    'src/app/**/not-found.tsx',
    'src/app/**/route.ts',
  ],
  project: ['src/**/*.{ts,tsx}'],
};

export default config;

ステップ4: package.jsonにスクリプトを追加

{
  "scripts": {
    "knip": "knip",
    "knip:fix": "knip --fix"
  }
}

ステップ5: 実行

基本的な実行

npm run knip

出力例:

Unused dependencies (1)
lodash  package.json

Unused exports (2)
unusedHelper  unknown  src/utils/helpers.ts:15:14
OldComponent  unknown  src/components/old.tsx:8:1

Unused files (1)
src/utils/deprecated.ts

フィルタリング

特定の種類の問題だけを確認する場合:

# 依存関係のみチェック
npx knip --dependencies

# exportのみチェック
npx knip --exports

# ファイルのみチェック
npx knip --files

自動修正

未使用のexportや依存関係を自動で削除できます:

npx knip --fix

注意: 自動修正を実行する前に、必ずgitでコミットしておきましょう。

ステップ6: 高度な設定

特定のファイルを無視する

{
  "ignore": ["src/generated/**", "**/*.d.ts"]
}

特定のexportを無視する

{
  "ignoreExportsUsedInFile": true
}

プラグインの設定

Knipは多くのツール(ESLint、Jest、Tailwindなど)のプラグインを内蔵しています:

{
  "eslint": {
    "config": [".eslintrc.json"]
  },
  "tailwindcss": {
    "config": ["tailwind.config.ts"]
  }
}

モノレポ対応

{
  "workspaces": {
    "packages/*": {
      "entry": ["src/index.ts"],
      "project": ["src/**/*.ts"]
    }
  }
}

ステップ7: CI/CDへの統合

GitHub Actionsでの設定例:

name: Knip Check

on:
  pull_request:
    branches: [main]

jobs:
  knip:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'npm'
      - run: npm ci
      - run: npx knip

トラブルシューティング

エントリーポイントからのexportが報告される

エントリーファイルのexportはデフォルトで除外されますが、明示的にチェックしたい場合:

npx knip --include-entry-exports

解決できないインポートを無視する

仮想モジュールなど、Knipが解決できないインポートがある場合:

{
  "ignoreUnresolved": ["#virtual/*", "@generated/*"]
}

パスエイリアスの設定

TypeScriptのパスエイリアスを使用している場合、tsconfig.jsonから自動的に読み取られますが、明示的に設定することもできます:

{
  "paths": {
    "@/*": ["./src/*"],
    "@components/*": ["./src/components/*"]
  }
}

まとめ

Knipを導入することで:

  1. バンドルサイズの削減: 未使用コードを削除することで、最終的なバンドルサイズを小さくできます
  2. 保守性の向上: 不要なコードがなくなり、コードベースが理解しやすくなります
  3. 依存関係の最適化: 使われていないパッケージを特定し、セキュリティリスクを減らせます

定期的にKnipを実行して、プロジェクトをクリーンに保ちましょう。