Зачем нужна динамическая загрузка?
Когда приложение становится большим, важно оптимизировать его начальную загрузку. Мы не хотим тянуть весь JavaScript-код сразу, особенно если часть компонентов используется редко (например, модальные окна, графики, панели администрирования).
Ранее мы уже использовали React.lazy, который позволяет загружать компоненты только при необходимости. Но в Next.js, особенно когда вы используете SSR (Server-Side Rendering), React.lazy не работает на сервере.
Решение от Next.js — next/dynamic
Next.js предоставляет специальную функцию dynamic из модуля next/dynamic, которая позволяет вам:
- Загружать компоненты динамически.
- Контролировать SSR: включать или отключать его.
- Добавлять фолбэк-компоненты (индикаторы загрузки).
- Работать с типами и
default/именованными экспортами
Базовое использование next/dynamic
import dynamic from 'next/dynamic';
const HeavyComponent = dynamic(() => import('./HeavyComponent'));
export default function HomePage() {
return (
<div>
<h1>Главная страница</h1>
<HeavyComponent />
</div>
);
}
Этот компонент будет автоматически вынесен в отдельный JavaScript-чанк и загружен при необходимости.
Добавляем loading (fallback)
Чтобы показать, что компонент загружается, можно передать опцию loading:
const HeavyComponent = dynamic(() => import('./HeavyComponent'), {
loading: () => <p>Загрузка компонента...</p>,
});
SSR: включать или нет?
По умолчанию, компоненты через dynamic() будут загружаться и рендериться на сервере. Если вы хотите полностью исключить компонент из SSR, используйте:
const ClientOnlyComponent = dynamic(() => import('./ClientOnlyComponent'), {
ssr: false,
});
Это полезно, если компонент зависит от window, document, или использует только клиентские библиотеки. На сервере браузера нет, так что window, document === null
Пример: лениво подгружаем модальное окно
Компонент EditUserModal.tsx
Это код самого окна:
interface EditUserModalProps {
userId: string;
onClose: () => void;
}
const EditUserModal: React.FC<EditUserModalProps> = ({ userId, onClose }) => (
<div className="modal">
<h2>Редактировать пользователя</h2>
<p>ID: {userId}</p>
<button onClick={onClose}>Закрыть</button>
</div>
);
export default EditUserModal;
Использование с next/dynamic
Код компонента UsersPage в который мы вставляем наше лениво подгружаемое окно:
import dynamic from 'next/dynamic';
import { useState } from 'react';
const EditUserModal = dynamic(() => import('./EditUserModal'), {
loading: () => <div>Загрузка...</div>,
ssr: false,
});
export default function UsersPage() {
const [selectedUserId, setSelectedUserId] = useState<string | null>(null);
return (
<div>
<h1>Пользователи</h1>
<button onClick={() => setSelectedUserId('1')}>Редактировать пользователя</button>
{selectedUserId && (
<EditUserModal
userId={selectedUserId}
onClose={() => setSelectedUserId(null)}
/>
)}
</div>
);
}
Теперь модальное окно не будет загружено на сервере и будет подгружаться только при необходимости.
Дополнительно: динамическая загрузка именованных экспортов
Если компонент экспортируется не по умолчанию (не имеет export default):
// components/Charts.tsx
export const Chart = () => <div>График</div>;
Можно загрузить его так:
const Chart = dynamic(() =>
import('./Charts').then(mod => mod.Chart)
);
Плюсы next/dynamic:
- Работает с SSR.
- Простая настройка загрузки.
- Контроль над фолбэком.
- Подходит для сложных и тяжёлых компонентов.
На что обратить внимание
| Риск | Решение |
|---|---|
| Компонент не виден при SSR | Используйте ssr: false |
| Большой TypeScript-файл | Разделяйте на меньшие части |
| Ошибки в типах | Проверяйте экспорт компонента и пропсы |
loading не отображается |
loading работает только с ssr: false |
Типичные ошибки
React.lazyв SSR → будет ошибка, потому чтоimport()не работает на сервере- Не указали
ssr: falseдля клиентских компонентов →ReferenceError: window is not defined dynamic()без fallback → пользователь может не понять, что компонент загружается
Если вы работаете с Next.js, особенно с SSR, то next/dynamic — обязательный инструмент для оптимизации вашего приложения. Это более мощная и гибкая замена React.lazy, идеально встроенная в экосистему Next.js.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ