Динамический импорт маршрутов

TanStack Router предоставляет гибкий способ организации маршрутизации в приложениях на JavaScript и TypeScript. Одной из ключевых возможностей является поддержка динамического импорта компонентов маршрутов, что позволяет загружать части приложения только по мере необходимости, сокращая время первоначальной загрузки и оптимизируя производительность.


Принцип работы динамического импорта

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

Пример базового использования:

import { createRouter, Route } from '@tanstack/router';

const router = createRouter({
  routes: [
    new Route({
      path: '/',
      component: () => import('./pages/HomePage'),
    }),
    new Route({
      path: '/about',
      component: () => import('./pages/AboutPage'),
    }),
  ],
});

В этом примере компонент HomePage и AboutPage не загружаются сразу при инициализации приложения. Они подгружаются только при навигации на соответствующие маршруты.


Асинхронные компоненты и Suspense

Так как динамический импорт возвращает промис, необходимо использовать обертку, которая умеет работать с асинхронными компонентами. В React это стандартный <Suspense>:

import React, { Suspense } from 'react';
import { RouterProvider } from '@tanstack/router';

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

Ключевой момент: fallback отображается, пока компонент загружается, что обеспечивает плавный пользовательский опыт и предотвращает “мерцание” пустых экранов.


Ленивая загрузка вложенных маршрутов

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

const dashboardRoute = new Route({
  path: '/dashboard',
  component: () => import('./pages/DashboardPage'),
  children: [
    new Route({
      path: 'stats',
      component: () => import('./pages/dashboard/StatsPage'),
    }),
    new Route({
      path: 'settings',
      component: () => import('./pages/dashboard/SettingsPage'),
    }),
  ],
});

Каждый дочерний маршрут подгружается отдельно только при переходе на него, что экономит ресурсы и ускоряет начальный рендер страницы.


Использование lazy функций для повторного импорта

Для удобства и снижения дублирования кода часто создают функцию-обертку, которая возвращает ленивый компонент:

import React, { lazy } from 'react';

function lazyLoad(importFn) {
  const Component = lazy(importFn);
  return (props) => <Component {...props} />;
}

const HomePage = lazyLoad(() => import('./pages/HomePage'));
const AboutPage = lazyLoad(() => import('./pages/AboutPage'));

const router = createRouter({
  routes: [
    new Route({ path: '/', component: HomePage }),
    new Route({ path: '/about', component: AboutPage }),
  ],
});

Это позволяет централизованно управлять динамическим импортом и улучшает читаемость маршрутов.


Предзагрузка маршрутов

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

function preloadAboutPage() {
  import('./pages/AboutPage');
}

// вызов перед переходом
button.addEventListener('mouseenter', preloadAboutPage);

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


Советы по организации больших приложений

  1. Разделение маршрутов по функциональным областям Разделение на модули (feature modules) с отдельными динамическими импортами позволяет масштабировать проект и поддерживать читаемость кода.

  2. Использование Suspense на уровне разделов Для крупных разделов можно оборачивать каждый раздел в собственный <Suspense>, чтобы показывать отдельный индикатор загрузки для разных частей приложения.

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

  4. Типизация в TypeScript Для безопасной работы с динамическими компонентами рекомендуется явно указывать типы возвращаемых компонентов, чтобы избежать ошибок в интерфейсах и пропсах.


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