Page.js — это легковесная библиотека для маршрутизации на стороне клиента в JavaScript, которая позволяет управлять переходами между страницами без перезагрузки браузера. Одним из ключевых подходов к оптимизации SPA-приложений является отложенная загрузка модулей, или lazy loading, что позволяет загружать части приложения только при необходимости, снижая время начальной загрузки.
Для начала подключаем Page.js:
import page from 'page';
Создание простого маршрута выглядит так:
page('/home', () => {
console.log('Главная страница');
});
page('/about', () => {
console.log('О странице');
});
page();
Метод page(path, callback) регистрирует маршрут, где
callback вызывается при переходе на указанный путь.
Отложенная загрузка позволяет импортировать модули только в момент
обращения к конкретному маршруту. Это достигается с помощью
динамического импорта import():
page('/profile', async () => {
const module = await import('./profile.js');
module.renderProfile();
});
Здесь profile.js загружается только при переходе на
маршрут /profile. Такой подход уменьшает вес основного
бандла и ускоряет первую отрисовку приложения.
Для удобного управления большим количеством маршрутов создается структура, где каждый маршрут описан объектом:
const routes = [
{
path: '/dashboard',
module: () => import('./dashboard.js')
},
{
path: '/settings',
module: () => import('./settings.js')
},
{
path: '/help',
module: () => import('./help.js')
}
];
routes.forEach(route => {
page(route.path, async () => {
const mod = await route.module();
mod.render();
});
});
page();
Такой подход обеспечивает единообразие и облегчает добавление новых страниц.
Важно учитывать, что динамический импорт возвращает промис. Для улучшения UX рекомендуется отображать индикатор загрузки:
page('/reports', async () => {
showLoader(true);
try {
const module = await import('./reports.js');
module.renderReports();
} finally {
showLoader(false);
}
});
Функция showLoader(true/false) может управлять спиннером
или прогресс-баром. Это предотвращает ощущение “заморозки” интерфейса
при загрузке больших модулей.
При использовании сборщиков, таких как Webpack, динамические импорты автоматически разбиваются на отдельные чанки:
page('/analytics', async () => {
const { renderAnalytics } = await import(
/* webpackChunkName: "analytics" */ './analytics.js'
);
renderAnalytics();
});
Опция webpackChunkName позволяет задать читаемое имя
файла для отдельного чанка. Это облегчает диагностику и кеширование
ресурсов.
Необходимо предусмотреть обработку возможных ошибок при динамическом импорте:
page('/reports', async () => {
showLoader(true);
try {
const module = await import('./reports.js');
module.renderReports();
} catch (error) {
console.error('Ошибка загрузки модуля:', error);
showErrorPage();
} finally {
showLoader(false);
}
});
Функция showErrorPage() может отображать страницу с
информацией о проблеме, обеспечивая стабильность приложения даже при
сбоях сети.
Page.js поддерживает промежуточные обработчики (middleware), что позволяет выполнять действия до загрузки модуля:
function authGuard(ctx, next) {
if (!isLoggedIn()) {
page.redirect('/login');
} else {
next();
}
}
page('/dashboard', authGuard, async () => {
const module = await import('./dashboard.js');
module.renderDashboard();
});
Middleware проверяет авторизацию и предотвращает загрузку модуля, если пользователь не имеет доступа.
Маршруты Page.js поддерживают динамические сегменты:
page('/user/:id', async (ctx) => {
const { id } = ctx.params;
const module = await import('./user.js');
module.renderUser(id);
});
Таким образом, один модуль может обслуживать множество пользователей, а сам код загружается только при необходимости.