React: مكتبة مكونات واجهة المستخدم

آخر تحديث: 2026-08-26

بدأ توم من الصفر في تصميم لوحة الإدارة الخاصة بمدونته. وبعد ستة أشهر، أصبح الكود مليئًا بأنماط style={{}} المضمنة المتكررة وأسماء فئات CSS المكتوبة يدويًّا. كان تطوير الميزات الجديدة يتباطأ، وكانت أنماط واجهة المستخدم غير متسقة عبر الصفحات المختلفة. كان يعلم أن الوقت قد حان لاعتماد مكتبة مكونات واجهة مستخدم احترافية، لكنه واجه العديد من الخيارات — مثل Ant Design وMaterial UI وHeadless UI — فوجد توم نفسه في حيرة من أمره.


1. ما ستتعلمه



2. المخططات المفاهيمية

أوجز توم عملية اتخاذ القرار المتعلقة باختيار مكتبة مكونات واجهة المستخدم: استنادًا إلى ثلاثة عوامل — نوع المشروع، وخلفية الفريق، واحتياجات التخصيص — اختار الحل الأنسب من بين مكتبات المكونات. وتتميز الأنواع المختلفة من مكتبات المكونات بمزاياها وقيودها الخاصة في السيناريوهات المختلفة.

تتفرع شجرة القرار أولاً حسب نوع المشروع: فمشاريع «الخلفية» و«الطبقة الوسطى» تعطي الأولوية لاكتمال المكونات، بينما تعطي مشاريع «الواجهة الأمامية» الأولوية للتأثيرات البصرية وإرشادات التصميم. تؤثر خلفية الفريق بشكل مباشر على منحنى التعلم وكفاءة التطوير: تتأقلم فرق React مع Ant Design بشكل أسرع، بينما تجد الفرق التي تركز على التصميم أن استخدام Material UI جنبًا إلى جنب مع إرشادات تصميم Figma أكثر سلاسة. وتتمثل نقطة القرار النهائية في التحميل حسب الطلب وتحسين الأداء — بغض النظر عن المكتبة المختارة، يجب إعداد التكوين المناسب للتحميل حسب الطلب عند دمجها في 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. سيناريو واقعي

تم تصميم لوحة التحكم الإدارية الخاصة بـ«توم» في البداية يدويًّا بالكامل. وبعد ستة أشهر، توسع المشروع ليشمل أكثر من 30 صفحة، لكل منها ملف CSS خاص بها. كانت أنماط الأزرار غير متسقة، وافتقرت مكونات الجداول إلى الوظائف المطلوبة، كما أنه قام بتنفيذ أداة اختيار التاريخ من الصفر ثلاث مرات. وقضى أسبوعًا في البحث عن مكتبات مكونات واجهة المستخدم الشائعة.

في النهاية، اختار توم Ant Design لثلاثة أسباب: أولاً، يقدم Ant Design المجموعة الأكثر شمولاً من المكونات — فالمكونات المخصصة للمؤسسات، مثل الجداول والنماذج وأدوات اختيار التاريخ، جاهزة للاستخدام فورًا دون الحاجة إلى إعدادات إضافية؛ ثانيًا، يدعم التحميل حسب الطلب و«تصفية الشجرة» (tree shaking)، وبالتالي لا يؤدي إلى تضخم حجم المشروع؛ ثالثًا، التكامل مع Next.js راسخ بالفعل، ويحتوي المجتمع على ثروة من الأمثلة العملية. كما استخدم «Headless UI» لتخصيص بعض المكونات الخاصة غير المتوفرة في Ant Design.

تعتبر عملية الاختيار التي اتبعها توم مفيدة للغاية: فقد أمضى أولاً أسبوعاً في دمج ثلاث مكتبات في مشروع تجريبي، وقام بتقييمها بناءً على ثلاثة معايير، وهي: كفاءة التطوير، وتأثير الأداء، ومنحنى التعلم. وتصدرت Ant Design الترتيب في جميع المجالات في سيناريو الخلفية المؤسسية. ويمكن أيضاً تطبيق نهج «الاختبار أولاً، ثم اتخاذ القرار» هذا على عملية اختيار المشاريع الخاصة بك.

(1) مقارنة بين خيارات مكتبات المكونات

للمقارنة Ant Design Material UI واجهة المستخدم بدون واجهة
لغة التصميم البنية الخلفية على مستوى المؤسسة تصميم Google Material بدون أنماط (منطق السلوك)
عدد المكونات 60+ 50+ ~15
تخصيص السمة ConfigProvider + الرمز المميز ThemeProvider + خاصية sx قابل للتخصيص بالكامل (Tailwind/CSS)
خيارات التصميم CSS-in-JS (الإصدار 5) CSS-in-JS (Emotion) بدون أنماط مدمجة
الترجمة إلى اللغات المختلفة أكثر من 50 لغة مدمجة أكثر من 30 لغة مدمجة لا توجد لغات مدمجة
حالات الاستخدام إدارة الخلفية، تطبيقات المؤسسات التطبيقات الموجهة للمستهلكين المشاريع عالية التخصيص
هز الشجرة ✅ تلقائي ✅ تلقائي ✅ تلقائي
منحنى التعلم متوسط متوسط منخفض (يتطلب تصميمًا مخصصًا)

عند اختيار مكتبة مكونات واجهة المستخدم، يجب أن تضع في اعتبارك ثلاثة عوامل رئيسية: شمولية المكونات (ما إذا كانت تغطي احتياجات عملك)، ومرونة التخصيص (ما إذا كانت تلبي متطلبات المصممين)، وتأثيرها على الأداء (ما إذا كانت تبطئ عملية تحميل الشاشة الأولى).

Ant Design (antd) is the most popular React UI library in China, open-sourced by Ant Financial. Its design language is geared toward enterprise-level back-end and middle-tier applications, providing a full suite of components ranging from buttons and tables to date pickers and tree controls. The interaction logic between components has been extensively tested, making them ready for use in complex scenarios—such as pagination, sorting, and filter synchronization in data tables.

Material UI (MUI) is a React implementation of Google’s Material Design guidelines. Its strengths lie in its mature design guidelines, modern visual style, and robust theme system. It is well-suited for consumer-facing front-end applications and designer-led teams.

Headless UI differs from the two categories above—it does not provide any predefined styles, but only provides behavioral logic (accessibility, keyboard navigation, focus management). Developers are entirely responsible for implementing the styling themselves using Tailwind CSS or CSS Modules. It is suitable for projects that require a highly customized visual style.

▶ المثال 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 على واجهات برمجة تطبيقات المتصفح أضف 'use client' في أعلى الملف الذي يستخدم المكون
وميض المحتوى غير المنسق (FOUC) عدم وجود أنماط من جانب الخادم؛ وإدراج متأخر من جانب العميل استخراج ملفات CSS الأساسية أو استخدام المكون App للإدارة المركزية
وميض عند تبديل السمة يتم تحميل رمز السمة على جانب العميل فقط تعيين السمة الافتراضية في ConfigProvider وإدراجها عبر SSR

لتحسين الأداء، ينبغي أن تستخدم المكونات الاستيراد الديناميكي (dynamic) للتحميل حسب الحاجة، وذلك لتجنب تضمين مكتبة المكونات بالكامل في كود جافا سكريبت الموجود في الجزء المرئي من الصفحة. تعمل ميزة «Tree Shaking» في Ant Design تلقائيًا عند البناء باستخدام ES Modules — ما عليك سوى الاستيراد مباشرةً من 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) واجهة مستخدم بدون رأس + تخصيص Tailwind CSS

تقدم «Headless UI» نهجًا مختلفًا تمامًا لمكتبات المكونات — المكونات الخالية من الأنماط. فهي تكشف عن المنطق السلوكي (مثل إغلاق مربع الحوار المفتوح بالضغط على مفتاح Escape، والتنقل باستخدام لوحة المفاتيح في مربعات القائمة المنسدلة، وإدارة الرسوم المتحركة للانتقالات)، بينما تترك مسألة التصميم بالكامل للمطور. وهذا يعني أن واجهة المستخدم الخاصة بك يمكن أن تتطابق تمامًا مع نماذج التصميم دون الحاجة إلى تجاوز الأنماط الافتراضية الخاصة بأطراف ثالثة.

واجه توم بعض الحالات التي لم يغطِّها Ant Design: لوحة تصفية مخصصة تتطلب تفاعلات محددة، ومربع اقتراحات منسدل لنتائج البحث يحتاج إلى تصميم خاص. ويمكن تنفيذ هذين العنصرين بمرونة كبيرة باستخدام Headless UI. وبالاقتران مع فئات الأدوات المساعدة في Tailwind CSS، يمكنك إنشاء واجهة مستخدم تتطابق مع نماذج التصميم دون كتابة سطر واحد من CSS المخصص.

مكونات واجهة المستخدم غير المرتبطة برأس منطق السلوك المُقدَّم الأجزاء التي تتطلب تخصيصًا
مربع الحوار مفتاح Escape: إغلاق، تثبيت التركيز، تعطيل التمرير في الخلفية المظهر، الرسوم المتحركة، نمط القناع
مربع القائمة المنسدلة التنقل باستخدام لوحة المفاتيح، والبحث والتصفية، وتمييز الخيارات حقول الإدخال، والألواح المنسدلة، وأنماط الخيارات
القائمة التنقل باستخدام مفاتيح الأسهم؛ انقر خارجها لإغلاقها عناصر القائمة والأيقونات وأنماط الفواصل
زر التبديل حالة التبديل، ميزات الوصول (ARIA) تبديل المسار، نمط شريط التمرير
مجموعة علامات التبويب التنقل باستخدام مفاتيح الأسهم، ومزامنة اللوحات أنماط تخطيط علامات التبويب واللوحات
الانتقال إدارة الرسوم المتحركة للتلاشي التدريجي عند الظهور/التلاشي التدريجي عند الاختفاء أسماء فئات CSS للرسوم المتحركة

▶ المثال 3: مكونات واجهة المستخدم المخصصة بدون واجهة عرض

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


❓ أسئلة شائعة

س كيف أختار بين Ant Design وMaterial UI وHeadless UI؟
ج هناك ثلاثة مبادئ للاختيار: ضع في اعتبارك نوع المشروع — استخدم Ant Design للأنظمة الخلفية الخاصة بالمؤسسات وMaterial UI للتطبيقات الموجهة للمستهلكين؛ ضع في اعتبارك احتياجات التخصيص — استخدم Headless UI + Tailwind لمستويات عالية من التخصيص؛ ووضع في اعتبارك خبرة الفريق — تميل فرق React إلى اعتبار Ant Design أكثر سهولة في الاستخدام. يمكنك أيضًا استخدام نهج هجين: استخدم Ant Design كمكتبة مكونات أساسية وHeadless UI لتكملها بمكونات مخصصة.
س ما الذي يجب أن أضعه في اعتباري عند استخدام Ant Design في Next.js؟
ج هناك ثلاث نقاط أساسية يجب ملاحظتها: أولاً، يجب استخدام مكونات Ant Design ضمن مكونات العميل (باستخدام 'use client')؛ ولا يمكن استخدامها مباشرةً في مكونات الخادم؛ ثانيًا، استخدم dynamic لاستيراد المكونات ديناميكيًا لتجنب تجميع مكتبة antd بأكملها في جافا سكريبت «فوق الطي»؛ ثالثًا، قم بتكوين السمات والتدويل في ConfigProvider لضمان اتساق الأنماط على المستوى العام. لم يعد Ant Design v5 يتطلب babel-plugin-import، حيث يتم تمكين Tree Shaking تلقائيًا.
س هل ستؤدي مكتبة المكونات إلى تضخم حجم المشروع؟
ج بالتأكيد ستؤدي إلى ذلك إذا ما استُخدمت بشكل غير صحيح. طرق التحسين: استخدم dynamic لتحميل المكونات عند الحاجة (dynamic(() => import('antd').then(m => m.Button)))؛ قم بتكوين optimizePackageImports في next.config.ts؛ استورد المكونات التي تحتاجها فقط (import { Button } from 'antd' بدلاً من استيراد كل شيء)؛ تحليل حجم الحزمة (@next/bundle-analyzer) لتحديد التبعيات غير الطبيعية. بعد التحسين، لا يتجاوز تأثير دمج Ant Design على جافا سكريبت للشاشة الأولى عادةً 30 كيلوبايت.
س عند تخصيص المكونات، هل يجب عليّ تعديل سمة مكتبة المكونات أم كتابة كود CSS خاص بي؟
ج أعطِ الأولوية لتعديل سمة مكتبة المكونات — فكل من Ant Design ConfigProvider وMaterial UI ThemeProvider يوفران أنظمة سمات شاملة تتيح لك تجاوز الرموز (tokens) مثل الألوان، والمسافات، والزوايا الدائرية، والخطوط. استخدم CSS Modules أو Tailwind لتكملة الأنماط التي لا يغطيها نظام السمات الخاص بمكتبة المكونات. تجنب استخدام !important لتجاوز أنماط مكتبة المكونات — يجب أن تحقق ذلك باستخدام رموز السمات أو تجاوز متغيرات CSS.
س ما هي الاختلافات بين Ant Design الإصدار 4 والإصدار 5؟
ج التغيير الأكبر في Ant Design الإصدار 5 هو الانتقال من لغة Less إلى نهج CSS-in-JS (cssinjs)، مما يلغي الحاجة إلى مُركِّب Less وbabel-plugin-import. بالإضافة إلى ذلك، تقدم الإصدارة v5 المكون App (الذي يدير مركزياً الطرق الثابتة مثل message وnotification وmodal)، والكائن theme (لتخصيص الرموز بدقة)، ودعم محسّن لـ SSR. كما أصبحت تعريفات أنواع TypeScript في الإصدار 5 أكثر شمولاً. إذا كنت تقوم بالترقية من الإصدار 4، فتأكد من الانتباه إلى توافق CSS-in-JS والتغييرات التي طرأت على واجهة برمجة تطبيقات السمات (theme API).

📖 ملخص


📝 تمارين

  1. دمج Ant Design في واجهة إدارة المدونة: قم بإنشاء سمة providers.tsx مُهيأة لـ Ant Design والتدويل (مضبوطة على اللغة الصينية)، وقم بتضمينها في التخطيط العام AntdProvider. استخدم مكونات مثل Button وTable وTag وSpace لإعادة تصميم صفحة إدارة المستخدمين في المدونة ضمن واجهة الإدارة.
  2. استخدم المكون Combobox من Headless UI + Tailwind CSS لتنفيذ أداة اختيار البحث عن المستخدمين: استرجاع قائمة بالمستخدمين من واجهة برمجة التطبيقات (API)، ودعم البحث والتصفية باستخدام الكلمات المفتاحية، وعرض معلومات المستخدم عند اختيار أحد المستخدمين. قارن ذلك بمكون Select من Ant Design لتجربة مستوى مرونة التخصيص الذي يوفره Headless UI.
  3. تحسين أداء مكتبة المكونات الخاصة بالمشروع: استخدم @next/bundle-analyzer لتحليل التغيرات في حجم الحزمة قبل وبعد دمج Ant Design. قم بتحويل ثلاثة مكونات كبيرة على الأقل (DatePicker، Table، TreeSelect) إلى التحميل الديناميكي باستخدام dynamic. أضف optimizePackageImports: ['antd', '@ant-design/icons'] إلى next.config.ts وقارن حجم JavaScript للشاشة الأولى ونتائج أداء Lighthouse قبل التحسين وبعده.
Web-Tutorial.com

فريق Web-Tutorial التقني

منصة دروس برمجية يديرها عدة مطورين. كل درس يتم كتابته ومراجعته بواسطة مطورين متخصصين في المجال. نعمل على ضمان دقة وموثوقية المحتوى — إذا لاحظت أي مشكلة، فيرجى إخبارنا.

100%