404 Not Found

404 Not Found


nginx

UIコンポーネントライブラリ

トムは、自分のブログの管理画面のデザインをゼロから手掛け始めた。6か月後、コードは繰り返しの多いstyle={{}}といったインラインスタイルや、手作業で記述されたCSSクラス名で埋め尽くされていた。新機能の開発は遅れがちになり、ページごとにUIのスタイルに一貫性がなくなっていた。彼は、プロ仕様のUIコンポーネントライブラリを導入すべき時が来たと悟ったが、Ant Design、Material UI、Headless UIなど、数多くの選択肢に直面し、途方に暮れていた。


1. 学習内容


2. 概念図

トムは、UIコンポーネントライブラリを選定するための意思決定プロセスについて概説しました。プロジェクトの種類、チームの背景、カスタマイズ要件という3つの要素に基づき、最も適したコンポーネントライブラリソリューションを選定しました。コンポーネントライブラリの種類によって、さまざまなシナリオにおいてそれぞれ独自の利点と制限があります。

決定木はまずプロジェクトの種類によって分岐します。バックエンドおよびミドルティアのプロジェクトではコンポーネントの完成度を優先し、フロントエンドのプロジェクトでは視覚効果やデザインガイドラインを優先します。チームの背景は、学習曲線や開発効率に直接影響します。ReactチームはAnt Designを迅速に習得できますが、デザイン主導のチームは、Figmaのデザインガイドラインと組み合わせてMaterial UIを使用する方がスムーズに進められます。最終的な判断基準は、オンデマンド読み込みとパフォーマンスの最適化です。どのライブラリを選択する場合でも、Next.jsに統合する際には、適切なオンデマンド読み込みの設定を行う必要があります。

100%
flowchart TD
    A[Select UI Component Library] --> B{Project Type?}
    B -->|Backend Management/Enterprise Applications| C[Ant Design<br/>Comprehensive enterprise-level components]
    B -->|Consumer-Facing Front End| D[Material UI<br/>Modern Visual Style]
    B -->|Highly Customized Requirements| E[Headless UI<br/>No style + Customizable]
    C --> F{Team Background?}
    D --> F
    E --> F
    F -->|React Team| G[Ant Design<br/>React Best Ecology]
    F -->|Designer-led| H[Material UI<br/>Mature design specifications]
    F -->|Fully Customizable Design| I[Headless UI<br/>Full Control Over Styles]
    G --> J[Integrated into Next.js]
    H --> J
    I --> J
    J --> K[Load on Demand Tree Shaking]
    K --> L[Theme Customization]
    L --> M[Performance Optimization]

3. 実際の事例

トムの管理ダッシュボードは、当初、すべて手作業でスタイリングされていました。6か月後、プロジェクトは30ページ以上に拡大し、各ページに独自のCSSファイルが割り当てられるようになりました。ボタンのスタイルは統一されておらず、テーブルコンポーネントには機能が不足しており、日付ピッカーは3回も一から実装し直していました。彼は1週間かけて、主流のUIコンポーネントライブラリについて調査を行いました。

結局、トムは3つの理由からAnt Designを選択しました。第一に、Ant Designは最も包括的なコンポーネントセットを提供しており、テーブル、フォーム、日付ピッカーなどのエンタープライズグレードのコンポーネントが、導入直後からすぐに利用可能です。第二に、オンデマンド読み込みとツリーシェイクに対応しているため、プロジェクトの肥大化を防げます。第三に、Next.jsとの統合がすでに確立されており、コミュニティには豊富な実践例があります。また、Ant Designにはない特殊なコンポーネントをカスタマイズするために、Headless UIも使用しました。

トムの選定プロセスは非常に参考になります。彼はまず1週間かけて3つのライブラリをテストプロジェクトに組み込み、開発効率、パフォーマンスへの影響、学習曲線という3つの基準に基づいて評価を行いました。その結果、エンタープライズ向けバックエンドのシナリオにおいて、Ant Designがすべての項目でトップの評価を得ました。この「まずテストを行い、それから判断する」というアプローチは、皆さんのプロジェクト選定プロセスにも応用できます。

(1) コンポーネント・ライブラリの選択肢の比較

比較 Ant Design Material UI Headless UI
デザイン言語 エンタープライズレベルのバックエンド Google Material Design スタイリングなし(動作ロジック)
部品数 60以上 50以上 約15
テーマのカスタマイズ ConfigProvider + トークン ThemeProvider + sx プロパティ 完全カスタマイズ可能(Tailwind/CSS)
スタイリングのオプション CSS-in-JS (v5) CSS-in-JS (Emotion) 組み込みスタイルなし
国際化 50以上の組み込み言語 30以上の組み込み言語 組み込み言語なし
ユースケース バックエンド管理、エンタープライズアプリケーション 消費者向けアプリケーション 高度にカスタマイズされたプロジェクト
ツリーシェーキング ✅ 自動 ✅ 自動 ✅ 自動
習得の難易度 中程度 中程度 低 (カスタムスタイリングが必要)

UIコンポーネントライブラリを選択する際には、3つの重要な要素を考慮する必要があります。それは、コンポーネントの網羅性(ビジネス上のニーズをカバーしているかどうか)、カスタマイズの柔軟性(デザイナーの要件を満たしているかどうか)、そしてパフォーマンスへの影響(ファーストスクリーンの読み込みが遅くなるかどうか)です。

Ant Design(antd)は、Ant Financialによってオープンソース化された、中国で最も人気のあるReact UIライブラリです。そのデザイン言語は、エンタープライズレベルのバックエンドおよびミドルティアアプリケーション向けに設計されており、ボタンやテーブルから日付ピッカー、ツリーコントロールに至るまで、包括的なコンポーネント群を提供しています。コンポーネント間の相互作用ロジックは徹底的にテストされており、データテーブルにおけるページネーション、ソート、フィルタの同期など、複雑なシナリオでもすぐに利用可能です。

Material UI(MUI)は、GoogleのMaterial DesignガイドラインをReactで実装したものです。その強みは、成熟したデザインガイドライン、モダンなビジュアルスタイル、そして堅牢なテーマシステムにあります。一般消費者向けのフロントエンドアプリケーションや、デザイナー主導のチームに最適です。

ヘッドレスUIは、上記の2つのカテゴリとは異なり、あらかじめ定義されたスタイルは一切提供せず、動作ロジック(アクセシビリティ、キーボードナビゲーション、フォーカス管理)のみを提供します。開発者は、Tailwind CSSやCSS Modulesを使用して、スタイリングを自ら実装する責任を全面的に負います。これは、高度にカスタマイズされたビジュアルスタイルが必要なプロジェクトに適しています。

(1) ▶ サンプル:コンポーネントライブラリごとのボタン実装の比較

TSX
// === Ant Design button ===
// Ready to Use Out of the Box,Built-in Styles,Through type Switch Visual Styles by Attribute
import { Button, Space } from 'antd'

function AntDButtons() {
  return (
    <Space wrap>
      <Button type="primary">Main Buttons</Button>
      <Button>Default Button</Button>
      <Button type="dashed">Dotted-line button</Button>
      <Button type="link">Link Button</Button>
      <Button type="primary" danger>Danger Button</Button>
      <Button loading>Loading...</Button>
      <Button type="primary" icon={<SearchOutlined />}>Search</Button>
    </Space>
  )
}

// === Material UI Button ===
// Through variant and  color Combining Properties to Achieve Different Styles
import Button from '@mui/material/Button'
import Stack from '@mui/material/Stack'
import SaveIcon from '@mui/icons-material/Save'

function MUIButtons() {
  return (
    <Stack direction="row" spacing={2}>
      <Button variant="contained">Fill Button</Button>
      <Button variant="outlined">Outline Button</Button>
      <Button variant="text">Text Button</Button>
      <Button variant="contained" color="error">Danger</Button>
      <Button variant="contained" disabled>Disable</Button>
      <Button variant="contained" startIcon={<SaveIcon />}>Save</Button>
    </Stack>
  )
}

// === Headless UI + Tailwind ===
// Unstyled Components + Custom Class
import { Button as HeadlessButton } from '@headlessui/react'

function HeadlessButtons() {
  return (
    <div className="flex gap-2">
      <HeadlessButton className="rounded bg-blue-600 px-4 py-2 text-white hover:bg-blue-500 data-[active]:bg-blue-700">
        Main Buttons
      </HeadlessButton>
      <HeadlessButton className="rounded border border-gray-300 px-4 py-2 text-gray-700 hover:bg-gray-50">
        Default Button
      </HeadlessButton>
      <HeadlessButton className="rounded bg-red-600 px-4 py-2 text-white hover:bg-red-500">
        Danger Button
      </HeadlessButton>
    </div>
  )
}
▶ 試してみよう

(2) Ant DesignとNext.jsの統合

Ant DesignをNext.jsに統合する際には、CSS-in-JSの互換性、オンデマンド読み込み、クライアント側のコンポーネント境界という、いくつかの重要な課題に対処する必要があります。Ant Design v5はCSS-in-JS(cssinjs)アプローチを採用しており、スタイルが正しく注入されるようにするには、Next.jsでの設定が必要です。

統合に関する問題 原因 解決策
CSS-in-JS の SSR との互換性 CSS-in-JS のスタイルはサーバーサイドで注入できない クライアントコンポーネントの境界を AntdProvider で囲む
最初のスクリーンのサイズが大きすぎる antd ライブラリ全体が最初の JS ファイルにバンドルされている dynamic() 動的インポート + optimizePackageImports
サーバーコンポーネントのエラー antd コンポーネントはブラウザ API に依存しています コンポーネントを使用しているファイルの先頭に 'use client' を追加してください
スタイル未適用コンテンツのフラッシュ (FOUC) サーバー側でスタイルを適用せず、クライアント側で遅延挿入 重要なCSSを抽出するか、Appコンポーネントを使用して一元管理する
テーマ切り替え時のちらつき テーマトークンはクライアント側でのみ読み込まれる ConfigProvider でデフォルトのテーマを設定し、SSR 経由で挿入する

パフォーマンスを最適化するには、コンポーネントでは動的インポート (dynamic) を使用してオンデマンドで読み込みを行い、コンポーネントライブラリ全体を「スクロールせずに見える範囲(above-the-fold)」の JavaScript にバンドルしないようにする必要があります。Ant Design の Tree Shaking は、ES モジュールを使用してビルドすると自動的に有効になります。単に antd から直接インポートするだけでよく、babel-plugin-import の設定は不要です。

(2) ▶ サンプル:Ant Design と Next.js の完全な統合

TSX
// app/providers.tsx - Ant Design Themes and Configuration Provider
'use client'
import { useState } from 'react'
import { ConfigProvider, theme, App } from 'antd'
import zhCN from 'antd/locale/zh_CN'

export function AntdProvider({ children }: { children: React.ReactNode }) {
  const [isDark] = useState(false)

  return (
    <ConfigProvider
      locale={zhCN}
      theme={{
        // Switch to Light Mode/Dark Theme
        algorithm: isDark ? theme.darkAlgorithm : theme.defaultAlgorithm,
        // Custom Theme Colors
        token: {
          colorPrimary: '#1677ff',
          borderRadius: 6,
          colorBgContainer: isDark ? '#141414' : '#ffffff',
        },
      }}
    >
      <App>{children}</App>
    </ConfigProvider>
  )
}

// app/layout.tsx - Global Import AntdProvider
import { AntdProvider } from './providers'

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="zh">
      <body>
        <AntdProvider>{children}</AntdProvider>
      </body>
    </html>
  )
}

// app/dashboard/page.tsx - Use dynamic import to load on demand Ant Design Components
// Avoid putting the entire antd Pack into the first screen JS in 
import dynamic from 'next/dynamic'

// Dynamic Import(Load only when needed)
const DataTable = dynamic(() => import('@/components/DataTable'), {
  loading: () => <div>Loading the table......</div>,
})

const DatePicker = dynamic(() => import('antd').then(mod => mod.DatePicker), {
  loading: () => <div>Loading the date picker......</div>,
})

async function DashboardPage() {
  // Analog Data Acquisition
  const data = await fetch('https://api.example.com/table-data').then(r => r.json())

  return (
    <div style={{ padding: 24 }}>
      <h1>Management Dashboard</h1>
      <div style={{ marginBottom: 16 }}>
        <DatePicker />
      </div>
      <DataTable data={data} />
    </div>
  )
}
export default DashboardPage

// components/DataTable.tsx - Complete Table Component
'use client'
import { Table, Tag, Space, Button, Popconfirm } from 'antd'
import type { ColumnsType } from 'antd/es/table'

interface UserData {
  key: number
  name: string
  age: number
  address: string
  status: 'active' | 'inactive'
}

function DataTable({ data }: { data: UserData[] }) {
  const columns: ColumnsType<UserData> = [
    { title: 'Name', dataIndex: 'name', key: 'name', sorter: (a, b) => a.name.localeCompare(b.name) },
    { title: 'Age', dataIndex: 'age', key: 'age', sorter: (a, b) => a.age - b.age },
    { title: 'Address', dataIndex: 'address', key: 'address' },
    {
      title: 'Status',
      dataIndex: 'status',
      key: 'status',
      render: (status: string) => (
        <Tag color={status === 'active' ? 'green' : 'red'}>
          {status === 'active' ? 'Enable' : 'Disable'}
        </Tag>
      ),
    },
    {
      title: 'Operation',
      key: 'action',
      render: (_: any, record: UserData) => (
        <Space>
          <Button type="link" onClick={() => console.log('Edit', record.key)}>Edit</Button>
          <Popconfirm title="Confirm Deletion?" onConfirm={() => console.log('Delete', record.key)}>
            <Button type="link" danger>Delete</Button>
          </Popconfirm>
        </Space>
      ),
    },
  ]

  return (
    <Table
      columns={columns}
      dataSource={data}
      pagination={{ pageSize: 10, showSizeChanger: true, showTotal: (total) => `Total ${total} items` }}
      bordered
      size="middle"
    />
  )
}
export default DataTable
▶ 試してみよう

(3) ヘッドレスUI + Tailwind CSSのカスタマイズ

Headless UIは、コンポーネントライブラリに対してまったく異なるアプローチ、すなわち「スタイルフリーのコンポーネント」を提供します。このアプローチでは、動作ロジック(Escキーを押して開いているダイアログを閉じる機能、コンボボックスのキーボードナビゲーション、遷移時のアニメーション管理など)を公開しつつ、スタイリングは完全に開発者に委ねられます。つまり、サードパーティ製のデフォルトスタイルを上書きすることなく、UIをデザインモックアップと完全に一致させることができます。

トムは、Ant Designでは対応されていないいくつかのケースに直面しました。具体的には、特定の操作を必要とするカスタムフィルターパネルや、特別なスタイリングが必要な検索結果用のドロップダウン候補ボックスなどです。これらはHeadless UIを使えば非常に柔軟に実装できます。Tailwind CSSのユーティリティクラスと組み合わせることで、カスタムCSSを1行も記述することなく、デザインモックアップ通りのUIを構築することができます。

ヘッドレス UI コンポーネント 提供される動作ロジック カスタマイズが必要な部分
ダイアログ Escapeキー:閉じる、フォーカスを固定、背景スクロールを無効化 外観、アニメーション、マスクスタイル
コンボボックス キーボード操作、検索とフィルタ、選択肢のハイライト表示 入力フィールド、ドロップダウンパネル、選択肢のスタイル
メニュー 矢印キーで移動、画面外をクリックすると閉じます メニュー項目、アイコン、区切り線のスタイル
スイッチ 状態の切り替え、アクセシビリティ(ARIA) トラックの切り替え、スライダーのスタイル
タブグループ 矢印キーによる移動、パネルの同期 タブおよびパネルのレイアウトスタイル
遷移 フェードイン/フェードアウトアニメーションの管理 アニメーション用CSSクラス名

(3) ▶ サンプル:カスタムヘッドレス UI コンポーネント

TSX
// components/SearchCombobox.tsx
// Usage Headless UI 's  Combobox Implementing a search suggestion drop-down menu
'use client'
import { useState } from 'react'
import {
  Combobox,
  ComboboxInput,
  ComboboxButton,
  ComboboxOptions,
  ComboboxOption,
  Transition,
} from '@headlessui/react'
import { ChevronDownIcon } from '@heroicons/react/20/solid'

const people = [
  { id: 1, name: 'Alice', role: 'Admin' },
  { id: 2, name: 'Bob', role: 'Editor' },
  { id: 3, name: 'Charlie', role: 'Author' },
  { id: 4, name: 'Diana', role: 'Reader' },
  { id: 5, name: 'Eve', role: 'Admin' },
]

function SearchCombobox() {
  const [selected, setSelected] = useState(people[0])
  const [query, setQuery] = useState('')

  const filtered = query === ''
    ? people
    : people.filter((person) =>
        person.name.toLowerCase().includes(query.toLowerCase())
      )

  return (
    <div className="w-72">
      <Combobox value={selected} onChange={setSelected}>
        <div className="relative">
          <ComboboxInput
            className="w-full rounded-lg border border-gray-300 bg-white py-2 pl-3 pr-10 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500"
            displayValue={(person: any) => person?.name}
            onChange={(event) => setQuery(event.target.value)}
            placeholder="Search Users..."
          />
          <ComboboxButton className="absolute inset-y-0 right-0 flex items-center pr-2">
            <ChevronDownIcon className="h-5 w-5 text-gray-400" />
          </ComboboxButton>
        </div>

        <Transition
          enter="transition duration-100 ease-out"
          enterFrom="transform scale-95 opacity-0"
          enterTo="transform scale-100 opacity-100"
          leave="transition duration-75 ease-out"
          leaveFrom="transform scale-100 opacity-100"
          leaveTo="transform scale-95 opacity-0"
        >
          <ComboboxOptions className="absolute z-10 mt-1 max-h-60 w-72 overflow-auto rounded-lg bg-white py-1 shadow-lg ring-1 ring-black/5">
            {filtered.length === 0 && query !== '' ? (
              <div className="px-3 py-2 text-sm text-gray-500">No matching results found</div>
            ) : (
              filtered.map((person) => (
                <ComboboxOption
                  key={person.id}
                  value={person}
                  className="cursor-pointer px-3 py-2 text-sm data-[focus]:bg-blue-100 data-[selected]:bg-blue-50"
                >
                  {({ selected }) => (
                    <div className="flex justify-between">
                      <span className={selected ? 'font-medium' : ''}>{person.name}</span>
                      <span className="text-gray-400">{person.role}</span>
                    </div>
                  )}
                </ComboboxOption>
              ))
            )}
          </ComboboxOptions>
        </Transition>
      </Combobox>

      {selected && (
        <p className="mt-2 text-sm text-gray-600">
          Selected:{selected.name}({selected.role})
        </p>
      )}
    </div>
  )
}
export default SearchCombobox
▶ 試してみよう

(4) ▶ サンプル:next.config.ts におけるパフォーマンス最適化の設定

TSX
// next.config.ts - Performance Optimization Configuration for the Component Library
import type { NextConfig } from 'next'

const withBundleAnalyzer = require('@next/bundle-analyzer')({
  enabled: process.env.ANALYZE === 'true',
})

const nextConfig: NextConfig = withBundleAnalyzer({
  optimizePackageImports: [
    'antd',
    '@ant-design/icons',
    '@mui/material',
    '@mui/icons-material',
    '@headlessui/react',
  ],
  transpilePackages: ['antd'],
  experimental: {
    optimizeCss: true,
  },
})

export default nextConfig

// package.json scripts:
// "analyze": "ANALYZE=true next build"
// "analyze:server": "ANALYZE=true BUNDLE_ANALYZE=server next build"
// "analyze:browser": "ANALYZE=true BUNDLE_ANALYZE=browser next build"
▶ 試してみよう

(5) ▶ サンプル:複数のコンポーネントライブラリを組み合わせて活用するための戦略

TSX
// components/HybridTable.tsx - Ant Design Table + Headless UI Custom Filters
'use client'
import { useState } from 'react'
import { Table, Tag } from 'antd'
import { Popover, PopoverButton, PopoverPanel } from '@headlessui/react'
import type { ColumnsType } from 'antd/es/table'

interface Product {
  key: string
  name: string
  price: number
  category: string
  status: 'in_stock' | 'out_of_stock'
}

const products: Product[] = [
  { key: '1', name: 'Laptop', price: 999, category: 'Electronics', status: 'in_stock' },
  { key: '2', name: 'Desk Chair', price: 299, category: 'Furniture', status: 'out_of_stock' },
  { key: '3', name: 'Coffee Maker', price: 79, category: 'Kitchen', status: 'in_stock' },
]

function HybridTable() {
  const [categoryFilter, setCategoryFilter] = useState<string>('all')

  const filtered = categoryFilter === 'all'
    ? products
    : products.filter(p => p.category === categoryFilter)

  const columns: ColumnsType<Product> = [
    { title: 'Name', dataIndex: 'name', key: 'name' },
    { title: 'Price', dataIndex: 'price', key: 'price', render: (v: number) => `$${v}` },
    { title: 'Category', dataIndex: 'category', key: 'category' },
    {
      title: 'Status',
      dataIndex: 'status',
      key: 'status',
      render: (s: string) => (
        <Tag color={s === 'in_stock' ? 'green' : 'red'}>
          {s === 'in_stock' ? 'In Stock' : 'Out of Stock'}
        </Tag>
      ),
    },
  ]

  return (
    <div>
      <div className="mb-4 flex items-center gap-2">
        <Popover className="relative">
          <PopoverButton className="rounded border px-3 py-1.5 text-sm">
            Filter: {categoryFilter === 'all' ? 'All' : categoryFilter}
          </PopoverButton>
          <PopoverPanel className="absolute z-10 mt-1 w-40 rounded bg-white py-1 shadow-lg">
            {['all', 'Electronics', 'Furniture', 'Kitchen'].map(cat => (
              <button
                key={cat}
                className="block w-full px-3 py-1.5 text-left text-sm hover:bg-blue-50"
                onClick={() => setCategoryFilter(cat)}
              >
                {cat === 'all' ? 'All Categories' : cat}
              </button>
            ))}
          </PopoverPanel>
        </Popover>
      </div>
      <Table columns={columns} dataSource={filtered} pagination={false} size="small" />
    </div>
  )
}
export default HybridTable
▶ 試してみよう

❓ よくある質問

Q Ant Design、Material UI、Headless UIのどれを選べばいいですか?
A 選択の際の3つの原則:プロジェクトの種類を考慮する――エンタープライズ向けバックエンドにはAnt Designを、一般ユーザー向けアプリケーションにはMaterial UIを使用する;カスタマイズの必要性を考慮する――高度なカスタマイズが必要な場合はHeadless UIとTailwindを組み合わせる;チームの経験を考慮する――ReactチームはAnt Designの方が直感的だと感じる傾向がある。ハイブリッドなアプローチも可能です。Ant Designをベースのコンポーネントライブラリとして使用し、Headless UIでカスタムコンポーネントを補完する方法です。
Q Next.jsでAnt Designを使用する際、どのような点に注意すべきですか?
A 注意すべき重要なポイントは3つあります。まず、Ant Designのコンポーネントはクライアントコンポーネント内('use client'を使用)で使用する必要があります。サーバーコンポーネント内で直接使用することはできません。第二に、dynamicを使用してコンポーネントを動的にインポートし、antdライブラリ全体をページ上部のJavaScriptにバンドルしないようにします。第三に、ConfigProviderでテーマと国際化を設定し、グローバルなスタイルの一貫性を確保します。Ant Design v5では、Tree Shakingが自動的に有効化されるため、babel-plugin-importは不要になりました。
Q コンポーネントライブラリはプロジェクトを肥大化させますか?
A 不適切に使用すれば、間違いなく肥大化します。最適化方法:dynamic を使用してコンポーネントをオンデマンドで読み込む(dynamic(() => import('antd').then(m => m.Button)));next.config.tsoptimizePackageImports を設定する;必要なコンポーネントのみをインポートする(すべてをインポートするのではなく import { Button } from 'antd' を使用する); バンドルサイズを分析し(@next/bundle-analyzer)、異常な依存関係を特定する。最適化後、Ant Designを統合した際のファーストスクリーンのJavaScriptへの影響は、通常30KB以下に抑えられます。
Q コンポーネントをカスタマイズする際、コンポーネントライブラリのテーマを修正すべきか、それとも独自のCSSを書くべきか?
A コンポーネントライブラリのテーマを修正することを優先してください。Ant DesignのConfigProviderもMaterial UIのThemeProviderも、色、余白、角丸、フォントなどのトークンを上書きできる包括的なテーマシステムを提供しています。コンポーネントライブラリのテーマシステムではカバーできないスタイルについては、CSS Modules や Tailwind を使用して補完してください。コンポーネントライブラリのスタイルを上書きするために !important を使用することは避けてください。これを行うには、テーマトークンを使用するか、CSS 変数を上書きする必要があります。
Q Ant Design v4とv5の違いは何ですか?
A Ant Design v5における最大の変更点は、LessからCSS-in-JS(cssinjs)アプローチへの移行であり、これによりLessコンパイラやbabel-plugin-importが不要になりました。さらに、v5ではAppコンポーネント(messagenotificationmodalなどの静的メソッドを一元管理する)、themeオブジェクト(トークンのきめ細かなカスタマイズ用)、およびSSRサポートの改善が導入されています。v5ではTypeScriptの型定義もより包括的になっています。v4からアップグレードする場合は、CSS-in-JSの互換性やテーマAPIの変更点に十分注意してください。

📖 まとめ


📝 練習問題

  1. Ant Designをブログの管理画面に統合する:Ant Designおよび国際化(中国語に設定)に対応したproviders.tsxテーマを作成し、グローバルレイアウトAntdProviderで囲む。ButtonTableTagSpace などのコンポーネントを使用して、管理画面内のブログのユーザー管理ページを再設計する。
  2. Headless UI + Tailwind CSS の Combobox コンポーネントを使用して、ユーザー検索セレクターを実装します。API からユーザー一覧を取得し、キーワード検索とフィルタリングに対応させ、ユーザーが選択された際にユーザー情報を表示します。これを Ant Design の Select コンポーネントと比較し、Headless UI が提供するカスタマイズの柔軟性を実感してください。
  3. プロジェクト向けにコンポーネントライブラリのパフォーマンスを最適化する:@next/bundle-analyzer を使用して、Ant Design を統合する前後のパッケージサイズの変動を分析する。dynamic を使用して、少なくとも 3 つの大規模コンポーネント(DatePicker、Table、TreeSelect)を動的読み込みに切り替える。optimizePackageImports: ['antd', '@ant-design/icons']next.config.tsに追加し、最適化前後のファーストスクリーンのJavaScriptサイズおよびLighthouseのパフォーマンススコアを比較する。
Web-Tutorial.com

Web-Tutorial 技術チーム

複数の開発者によって共同維持されているプログラミングチュートリアルプラットフォーム。各チュートリアルは専門分野の開発者が執筆・レビューしています。正確で信頼性の高いコンテンツを目指しています — 問題を見つけた場合はお知らせください。

100%