Route-based code splitting

Route-based code splitting — это метод оптимизации загрузки веб-приложений, при котором код разбивается на отдельные фрагменты (chunks) и загружается динамически только тогда, когда он необходим. В контексте TanStack Router эта техника позволяет загружать компоненты и связанные с ними данные по мере навигации пользователя, что значительно ускоряет начальную загрузку приложения и снижает объем передаваемого JavaScript.

Динамическая загрузка компонентов

В TanStack Router для динамической загрузки компонентов используется стандартный синтаксис JavaScript import(). Вместо того чтобы импортировать все компоненты сразу, их можно подключать через функцию lazy или напрямую внутри конфигурации маршрутов.

Пример создания маршрута с ленивой загрузкой компонента:

import { createRouter, RouterProvider } from '@tanstack/router';
import { lazy } from 'react';

const Home = lazy(() => import('./pages/Home'));
const About = lazy(() => import('./pages/About'));

const router = createRouter({
  routes: [
    {
      path: '/',
      component: Home,
    },
    {
      path: '/about',
      component: About,
    },
  ],
});

function App() {
  return <RouterProvider router={router} />;
}

В этом примере компонент Home и About загружаются только при переходе на соответствующий маршрут. Основной бандл приложения при этом остается минимальным.

Поддержка вложенных маршрутов

TanStack Router позволяет строить сложные и вложенные маршруты с ленивой загрузкой каждого уровня. Для вложенных маршрутов также можно использовать динамический импорт компонентов.

const Dashboard = lazy(() => import('./pages/Dashboard'));
const Settings = lazy(() => import('./pages/dashboard/Settings'));
const Profile = lazy(() => import('./pages/dashboard/Profile'));

const router = createRouter({
  routes: [
    {
      path: '/dashboard',
      component: Dashboard,
      children: [
        {
          path: 'settings',
          component: Settings,
        },
        {
          path: 'profile',
          component: Profile,
        },
      ],
    },
  ],
});

При переходе к /dashboard/settings загружается только Dashboard и Settings, при этом Profile не загружается, пока не произойдет навигация к /dashboard/profile.

Suspense и fallback

Так как ленивые компоненты загружаются асинхронно, их нужно оборачивать в React.Suspense для отображения fallback-интерфейса, пока компонент загружается.

import { Suspense } from 'react';

function App() {
  return (
    <Suspense fallback={<div>Загрузка...</div>}>
      <RouterProvider router={router} />
    </Suspense>
  );
}

Использование Suspense позволяет улучшить пользовательский опыт, предотвращая показ пустого экрана при динамической подгрузке модулей.

Data Fetching с ленивыми маршрутами

TanStack Router поддерживает асинхронную загрузку данных для маршрутов. В сочетании с ленивой загрузкой компонентов это позволяет оптимизировать как JS-бандл, так и сетевой трафик.

const Users = lazy(() => import('./pages/Users'));

const router = createRouter({
  routes: [
    {
      path: '/users',
      component: Users,
      loader: async () => {
        const response = await fetch('/api/users');
        return response.json();
      },
    },
  ],
});

Функция loader выполняется только при активации маршрута /users, данные загружаются по запросу, а компонент Users подгружается динамически.

Code splitting для крупных приложений

В больших приложениях разумно разбивать маршруты по функциональным зонам. Например, отдельные чаты, панели администратора и публичные страницы можно держать в разных чанках. Это позволяет сократить время первой загрузки, ускорить рендеринг и уменьшить потребление памяти.

Пример структуры чанков:

src/
 ├─ pages/
 │   ├─ Home.js
 │   ├─ About.js
 │   ├─ Dashboard/
 │   │   ├─ Dashboard.js
 │   │   ├─ Settings.js
 │   │   └─ Profile.js
 │   └─ Users.js

Каждая директория может быть точкой ленивой загрузки. В конфигурации TanStack Router достаточно указать динамический импорт для соответствующего компонента, и сборщик (Vite, Webpack) создаст отдельный чанк.

Преимущества route-based code splitting

  • Быстрая начальная загрузка: основной бандл минимален, загружается быстрее.
  • Оптимизация трафика: загружается только то, что нужно пользователю.
  • Управляемое кеширование: чанки могут кешироваться браузером независимо друг от друга.
  • Легкость поддержки: структура маршрутов и компонентов остается логичной и модульной.

Важные рекомендации

  • Для ленивой загрузки компонентов использовать React.lazy или аналогичные инструменты.
  • Всегда оборачивать ленивые компоненты в Suspense.
  • Комбинировать ленивую загрузку компонентов с асинхронной загрузкой данных через loader.
  • Разбивать приложение на логические зоны для упрощения управления чанками.
  • Следить за тем, чтобы не создавать слишком мелких чанков, иначе загрузка может стать менее эффективной из-за множества сетевых запросов.

Route-based code splitting в TanStack Router позволяет сочетать динамическую подгрузку компонентов и данных, обеспечивая высокую производительность и масштабируемость React-приложений.