Lazy Loading маршрутов
Lazy Loading маршрутов — техника, при которой JavaScript-код страницы загружается только тогда, когда пользователь переходит на соответствующий маршрут, а не при начальной загрузке приложения.
Зачем нужно
SPA с десятками маршрутов может иметь bundle в несколько мегабайт, если весь код загружается сразу. Lazy Loading делит приложение на chunks: пользователь скачивает только код главной страницы, остальные загружаются по требованию. Это сокращает время первой загрузки и TTI (Time to Interactive), что критично для производительности.
Где используется
- Все крупные React-приложения с react-router
- Next.js App Router (автоматическое разделение по маршрутам)
- Vue Router с
defineAsyncComponent - Angular
loadChildrenв RouterModule
React.lazy + Suspense
import React, { Suspense, lazy } from 'react';
import { BrowserRouter, Routes, Route } from 'react-router-dom';
// Обычный статический импорт — попадает в основной bundle
import Home from './pages/Home';
// Lazy импорт — создаёт отдельный chunk
const About = lazy( => import('./pages/About'));
const Dashboard = lazy( => import('./pages/Dashboard'));
const UserProfile = lazy( => import('./pages/UserProfile'));
function App() {
return (
<BrowserRouter>
{/* Suspense отображает fallback пока chunk загружается */}
<Suspense fallback={<div>Загрузка...</div>}>
<Routes>
{/* Home — не lazy, критичный маршрут */}
<Route path="/" element={<Home />} />
{/* Эти маршруты загрузятся только при переходе */}
<Route path="/about" element={<About />} />
<Route path="/dashboard" element={<Dashboard />} />
<Route path="/users/:id" element={<UserProfile />} />
</Routes>
</Suspense>
</BrowserRouter>
);
}
Группировка в один chunk (magic comments)
// Webpack magic comment — объединяет несколько модулей в один chunk
const UserProfile = lazy(
=> import(/* webpackChunkName: "user-pages" */ './pages/UserProfile')
);
const UserSettings = lazy(
=> import(/* webpackChunkName: "user-pages" */ './pages/UserSettings')
);
// Оба попадут в chunk user-pages.js
Skeleton вместо спиннера
function PageSkeleton() {
return (
<div className="skeleton">
<div className="skeleton__header" />
<div className="skeleton__content" />
</div>
);
}
function App() {
return (
<Suspense fallback={<PageSkeleton />}>
<Routes>...</Routes>
</Suspense>
);
}
Prefetch при наведении (prodвинутый паттерн)
// Загрузить chunk заранее при наведении на ссылку
function NavLink({ to, children }) {
const handleMouseEnter = () => {
// Браузер начнёт скачивать chunk до клика
import(`./pages/${to}`);
};
return (
<Link to={to} onMouseEnter={handleMouseEnter}>
{children}
</Link>
);
}
Частые ошибки
- Lazy Loading для маленьких компонентов — overhead на HTTP-запрос может превышать выигрыш от разделения; делайте lazy только крупные маршруты (> 20 KB).
- Отсутствие Suspense-обёртки —
React.lazyбезSuspenseвыбросит ошибку. - Нет Error Boundary вокруг Suspense — если chunk не загрузился (нет сети), нужно показать fallback с ошибкой.
- Lazy Loading для критических маршрутов — главная страница должна загружаться без дополнительных запросов.
Связанные темы
- _MOC SPA
- Code Splitting -- разделение кода
- Suspense и Concurrent Features
- Error Boundaries
- Клиентский роутинг -- как работает