Разработка · 6 мин чтения

Ant Design Dashboard: как собрать панель управления на React

Смотрю на заявки за последние пару лет и вижу закономерность: заказчики всё чаще просят собрать именно antd dashboard - панель управления на связке React и Ant Design, а не самописный интерфейс с нуля. Причина простая: библиотека закрывает 80% типовых задач админки - таблицы, формы, графики, layout - и экономит недели на вёрстке. Ниже - как я собираю такие панели на практике: структура проекта, компоненты, роли доступа и грабли, на которые наступал сам.

Структура проекта: с чего начинается панель на Ant Design

Для новых проектов беру Vite, а не Create React App - сборка дашборда с десятками страниц на CRA после третьей минуты пересборки начинает раздражать даже терпеливого заказчика. Ставлю antd 5.x, TypeScript и React Router. Папки развожу по фичам, а не по типам файлов: features/orders, features/clients, features/analytics, каждая со своими компонентами, хуками и API-запросами внутри. Общий layout, тема antd и обёртки над Table и Form выношу в shared/ui.

Ant Design 5 переехал на CSS-in-JS вместо less-переменных, и это меняет подход к кастомизации темы. Токены задаются через ConfigProvider и объект theme, а не через файл со стилями:

import { ConfigProvider } from 'antd';

const theme = {
  token: {
    colorPrimary: '#1677ff',
    borderRadius: 6,
  },
  components: {
    Table: { headerBg: '#fafafa' },
  },
};

function App() {
  return (
    <ConfigProvider theme={theme}>
      <AppLayout />
    </ConfigProvider>
  );
}

Если дизайнер прислал макет с фирменными цветами клиента, это закрывает вопрос за 10 минут - без переопределения десятков CSS-классов через !important, как приходилось делать на antd 4.

Layout, Menu и Breadcrumb - каркас интерфейса

Базовый каркас почти всегда один и тот же: Sider с меню слева, шапка с профилем и уведомлениями, контентная область с хлебными крошками. Компонент Layout из коробки даёт нужную разметку, остаётся связать пункты меню с роутами:

import { Layout, Menu } from 'antd';
import { DashboardOutlined, TeamOutlined, BarChartOutlined } from '@ant-design/icons';

const { Sider, Content, Header } = Layout;

const menuItems = [
  { key: '/', icon: <DashboardOutlined />, label: 'Обзор' },
  { key: '/clients', icon: <TeamOutlined />, label: 'Клиенты' },
  { key: '/reports', icon: <BarChartOutlined />, label: 'Отчёты' },
];

function AppLayout({ children }) {
  const navigate = useNavigate();
  return (
    <Layout style={{ minHeight: '100vh' }}>
      <Sider breakpoint="lg" collapsedWidth="0">
        <Menu
          theme="dark"
          mode="inline"
          items={menuItems}
          onClick={({ key }) => navigate(key)}
        />
      </Sider>
      <Layout>
        <Header style={{ background: '#fff', padding: '0 24px' }} />
        <Content style={{ margin: 24 }}>{children}</Content>
      </Layout>
    </Layout>
  );
}

Пункт breakpoint="lg" сворачивает сайдбар на планшетах - без этого на iPad меню съедает половину экрана, и заказчики на приёмке почти всегда просят это поправить, если забыть сразу.

Бесплатный материал

🎁 Полезный скрипт в подарок

Подпишитесь на Telegram - пришлю готовый скрипт по этой теме.

Без спама. Отписка в 1 клик.

Таблицы и формы: связка Table и Form на практике

Основная часть любой админки - это таблицы с фильтрами и формы редактирования. На проекте для логистической компании таблица заказов росла до 40 тысяч строк, и клиентская пагинация antd легла бы на первом же фильтре. Пагинацию, сортировку и фильтры перевёл на сервер:

const columns = [
  { title: 'Клиент', dataIndex: 'name', key: 'name', sorter: true },
  {
    title: 'Статус',
    dataIndex: 'status',
    key: 'status',
    filters: [
      { text: 'В пути', value: 'transit' },
      { text: 'Доставлен', value: 'done' },
    ],
  },
];

function OrdersTable() {
  const [params, setParams] = useState({ page: 1, pageSize: 20 });
  const { data, isLoading } = useOrders(params);

  return (
    <Table
      columns={columns}
      dataSource={data?.items}
      rowKey="id"
      loading={isLoading}
      pagination={{ current: params.page, pageSize: 20, total: data?.total }}
      onChange={(pagination, filters, sorter) =>
        setParams({ page: pagination.current, pageSize: 20, filters, sorter })
      }
    />
  );
}

Для форм связка Form.useForm плюс встроенные правила валидации закрывает 90% случаев без сторонних библиотек вроде Formik. Единственное место, где реально нужен React Query или SWR поверх - кэширование справочников (города СДЭК, статусы заказов, менеджеры), которые дёргаются на каждой форме заново, если не закешировать.

Графики для дашборда: что выбрать

Ant Design не тянет графики в основной пакет - их подключают отдельно. На практике сравнивал три варианта для панелей с аналитикой:

Библиотека Вес бандла Кастомизация Когда беру
@ant-design/charts Средний Готовые пресеты, стиль сразу под antd Типовые графики без глубоких кастомных сценариев
Recharts Небольшой Гибкая композиция через React-компоненты Когда нужен нестандартный вид виджета
ECharts (echarts-for-react) Большой Максимальная, включая карты и 3D BI-дашборды с тепловыми картами и большим объёмом точек

Для обычного дашборда продаж хватает @ant-design/charts - линии, столбцы и Pie собираются за час без танцев со стилями. Если нужен дашборд с географией доставок или тепловой картой активности, беру ECharts - он тяжелее, но по-другому карту с 5000 точек не отрисовать без лагов.

Роли доступа и защита роутов

Меню и роуты в панели почти всегда завязаны на роли: менеджер видит заказы, бухгалтер - отчёты и счета, админ - всё плюс настройки. Пункты меню фильтрую на фронте по массиву прав из токена, но саму защиту данных всегда дублирую на бэкенде - фронтовая проверка ролей это вопрос UX, а не безопасности.

function ProtectedRoute({ roles, children }) {
  const { user } = useAuth();
  if (!user) return <Navigate to="/login" />;
  if (roles && !roles.some((r) => user.roles.includes(r))) {
    return <Navigate to="/403" />;
  }
  return children;
}

Бэкенд под такие панели чаще собираю на Laravel - готовая система прав (Spatie Permission), очереди для экспорта отчётов и стабильный REST API под antd-таблицы связываются без лишних костылей. Если у вас уже есть API на другом стеке, отдельно смотрю на разработку API и бэкенда на Laravel под конкретно ваш дашборд - обычно нужен, когда старый бэкенд не тянет фильтры и агрегации, которые просит фронт.

Персональные данные клиентов - email, телефоны, адреса доставки - храню только на серверах в РФ, без завязки на иностранные облачные таблицы. Для дашборда с клиентской базой это не опция, а требование 152-ФЗ.

Производительность: на что смотрю в первую очередь

Ant Design - библиотека немаленькая, и без внимания к бандлу дашборд начинает грузиться по 4-5 секунд на слабом канале. Что реально экономит время:

  • Импорт иконок точечно, а не пакетом @ant-design/icons целиком - на одном проекте это срезало 300 КБ из бандла;
  • Ленивая загрузка страниц через React.lazy - раздел «Настройки» открывают раз в неделю, незачем грузить его код на старте;
  • Мемоизация колонок Table через useMemo - без неё колонки пересоздаются на каждый рендер и таблица на 1000+ строк подтормаживает при вводе в фильтр;
  • Виртуализация длинных списков - начиная примерно с 500 строк на странице разница в отзывчивости заметна на глаз, даже с серверной пагинацией.

Отдельно слежу за тем, чтобы контекст авторизации не оборачивал весь layout - если AuthContext меняется на каждый тик (например, из-за таймера токена), перерисовывается вся страница целиком, включая тяжёлые графики. Разношу контексты по назначению вместо одного глобального.

Кастомный CRM/админ-интерфейс

Админка / CRM

от 100 000 ₽

Подробнее →

Частые вопросы

Сколько стоит дашборд на Ant Design для React?

ЦРМ или админ-панель на React у меня стоит от 100 000 ₽ - цена зависит от количества разделов, сложности прав доступа и интеграций с внешними системами вроде эквайринга или СДЭК. Простая панель с 3-4 разделами и одной ролью укладывается в нижнюю границу, дашборд с аналитикой, ролями и экспортами - дороже.

Чем Ant Design лучше MUI для панели управления

Ant Design изначально заточен под enterprise-интерфейсы: у Table, Form и Tree больше готовых сценариев из коробки - серверная пагинация, вложенные фильтры, drag-and-drop колонок. MUI даёт больше свободы в дизайне и ближе к Material-гайдлайнам, но типовые вещи вроде сложной таблицы приходится собирать из более простых кубиков. Для внутренней CRM или бэк-офиса обычно беру antd - быстрее по срокам.

Можно ли адаптировать antd dashboard под мобильные устройства

Grid-система antd (Row/Col) и брейкпоинты у Sider и Menu адаптивны сами по себе, но Table на маленьком экране требует отдельной работы - либо горизонтальный скролл с зафиксированной первой колонкой, либо переключение на карточное представление ниже определённой ширины. Для панелей, которыми реально пользуются с телефона (например, курьеры или полевые менеджеры), карточный вид делаю отдельным компонентом, а не пытаюсь ужать таблицу.

Сколько времени занимает разработка админ-панели на antd

Панель на 5-7 разделов с таблицами, формами и одной-двумя ролями доступа обычно занимает от 3 до 5 недель вместе с интеграцией бэкенда. Дашборд с графиками, экспортом отчётов и несколькими ролями - от 6 недель. Сроки сильно зависят от готовности API: если бэкенд уже отдаёт данные в нужном формате, фронтовая часть на antd собирается заметно быстрее.

Есть задача?

Обсудим в мессенджере

Расскажите, что нужно сделать — отвечу в течение 4 часов в рабочее время. Первая консультация бесплатно.

Самозанятый Калинкин Н. А. · работаю с физлицами и юрлицами

Продолжая пользование настоящим сайтом Вы выражаете своё согласие на обработку Ваших персональных данных (файлов куки) с использованием Yandex.Metrika.
Понятно