125k

Monorepo

モノリポジトリでの shadcn/ui コンポーネントと CLI の使用。

これまで、モノリポジトリで shadcn/ui を使用するのは少し面倒でした。CLI を使ってコンポーネントを追加することはできましたが、コンポーネントのインストール先を自分で管理し、インポートパスを手動で修正する必要がありました。

CLI の新しいモノリポジトリ サポートにより、モノリポジトリで shadcn/ui を使うのがずっと簡単になりました。

CLI はモノリポジトリの構造を理解し、コンポーネント、依存関係、レジストリ依存関係を正しいパスにインストールし、インポートの処理も行います。

はじめる

新しいモノリポジトリ プロジェクトを作成する

新しいモノリポジトリ プロジェクトを作成するには、--monorepo フラグを指定して init コマンドを実行します。

pnpm dlx shadcn@latest init --monorepo

次に、使用するテンプレートを選択します。

? Select a template ›
❯   Next.js
    Vite
    TanStack Start
    React Router
    Astro

これにより、web と ui という 2 つのワークスペースを持ち、ビルド システムとして Turborepo を使用する新しいモノリポジトリ プロジェクトが作成されます。

すべてがセットアップされるので、プロジェクトへのコンポーネントの追加を開始できます。

プロジェクトにコンポーネントを追加する

プロジェクトにコンポーネントを追加するには、アプリのパスで add コマンドを実行します。

cd apps/web
pnpm dlx shadcn@latest add [COMPONENT]

CLI は、追加しているコンポーネントのタイプを判断し、 正しいファイルを正しいパスに移動します。

たとえば、npx shadcn@latest add button を実行すると、CLI は packages/ui の下にボタン コンポーネントをインストールし、apps/web 内のコンポーネントのインポート パスを更新します。

npx shadcn@latest add login-01 を実行すると、CLI は button、label、input、および card コンポーネントを packages/ui にインストールし、login-form コンポーネントを apps/web/components にインストールします。

コンポーネントのインポート

次のように、@workspace/ui パッケージからコンポーネントをインポートできます。

import { Button } from "@workspace/ui/components/button"

@workspace/ui パッケージからフックとユーティリティをインポートすることもできます。

import { useTheme } from "@workspace/ui/hooks/use-theme"
import { cn } from "@workspace/ui/lib/utils"

ファイル構造

新しいモノリポジトリ プロジェクトを作成すると、CLI は次のファイル構造を作成します。

apps
└── web         # Your app goes here.
    ├── app
    │   └── page.tsx
    ├── components
    │   └── login-form.tsx
    ├── components.json
    └── package.json
packages
└── ui          # Your components and dependencies are installed here.
    ├── src
    │   ├── components
    │   │   └── button.tsx
    │   ├── hooks
    │   ├── lib
    │   │   └── utils.ts
    │   └── styles
    │       └── globals.css
    ├── components.json
    └── package.json
package.json
turbo.json

要件

  1. すべてのワークスペースに components.json ファイルが必要です。 package.json ファイルは、依存関係をインストールする方法を npm に指示します。 components.json ファイルは、コンポーネントをインストールする方法と場所を CLI に指示します。

  2. components.json ファイルは、ワークスペースのエイリアスを適切に定義する必要があります。これにより、コンポーネント、フック、ユーティリティなどをインポートする方法が CLI に指示されます。

apps/web/components.json
{
  "$schema": "https://ui.shadcn.com/schema.json",
  "style": "base-nova",
  "rsc": true,
  "tsx": true,
  "tailwind": {
    "config": "",
    "css": "../../packages/ui/src/styles/globals.css",
    "baseColor": "neutral",
    "cssVariables": true
  },
  "iconLibrary": "lucide",
  "aliases": {
    "components": "@/components",
    "hooks": "@/hooks",
    "lib": "@/lib",
    "utils": "@workspace/ui/lib/utils",
    "ui": "@workspace/ui/components"
  }
}
packages/ui/components.json
{
  "$schema": "https://ui.shadcn.com/schema.json",
  "style": "base-nova",
  "rsc": true,
  "tsx": true,
  "tailwind": {
    "config": "",
    "css": "src/styles/globals.css",
    "baseColor": "neutral",
    "cssVariables": true
  },
  "iconLibrary": "lucide",
  "aliases": {
    "components": "@workspace/ui/components",
    "utils": "@workspace/ui/lib/utils",
    "hooks": "@workspace/ui/hooks",
    "lib": "@workspace/ui/lib",
    "ui": "@workspace/ui/components"
  }
}
  1. 両方の components.json ファイルに同じ style、iconLibrary、および baseColor があることを確認します。

  2. Tailwind CSS v4 の場合、components.json ファイル内の tailwind 設定を空のままにしておきます。

これらの要件に従うことで、CLI は ui コンポーネント、ブロック、ライブラリ、フックを正しいパスにインストールし、インポートを処理できるようになります。

package.json#imports の使用

パッケージインポートを使用し、tsconfig.json の paths に依存しないモノリポジトリの場合は、次を使用します:

  • 各ワークスペース内のファイル用のローカル #... エイリアス
  • @workspace/ui/components などの共有インポート用のワークスペース パッケージ exports

たとえば、アプリのワークスペースはローカル パッケージのインポートを使用できます。

apps/web/package.json
{
  "name": "web",
  "private": true,
  "type": "module",
  "imports": {
    "#components/*": "./src/components/*.tsx",
    "#lib/*": "./src/lib/*.ts",
    "#hooks/*": "./src/hooks/*.ts"
  },
  "dependencies": {
    "@workspace/ui": "workspace:*"
  }
}
apps/web/components.json
{
  "aliases": {
    "components": "#components",
    "ui": "@workspace/ui/components",
    "lib": "#lib",
    "hooks": "#hooks",
    "utils": "@workspace/ui/lib/utils"
  }
}

また、共有 UI パッケージは、exports を使用してインストール ターゲットを公開できます。

packages/ui/package.json
{
  "name": "@workspace/ui",
  "private": true,
  "type": "module",
  "imports": {
    "#components/*": "./src/components/*.tsx",
    "#lib/*": "./src/lib/*.ts",
    "#hooks/*": "./src/hooks/*.ts"
  },
  "exports": {
    "./globals.css": "./src/styles/globals.css",
    "./components/*": "./src/components/*.tsx",
    "./lib/*": "./src/lib/*.ts",
    "./hooks/*": "./src/hooks/*.ts"
  }
}
packages/ui/components.json
{
  "aliases": {
    "components": "#components",
    "ui": "#components",
    "lib": "#lib",
    "hooks": "#hooks",
    "utils": "#lib/utils"
  }
}

この設定では:

  • アプリから共有 UI パッケージに追加されたファイルは、@workspace/ui/... を経由してルーティングされます
  • packages/ui 内に追加されたファイルは、パッケージローカルの #... エイリアスを使用します。
  • 共有パッケージは、別のワークスペースによって参照されるパスをエクスポートする必要があります

フレームワーク固有のパッケージ インポートの設定については、パッケージ インポート ガイド を参照してください。