Деградация функциональности

Page.js — это минималистичная библиотека для маршрутизации на стороне клиента в JavaScript, обеспечивающая управление переходами между страницами без перезагрузки. Она использует паттерн single-page application (SPA) и позволяет привязывать обработчики к конкретным маршрутам, управлять параметрами URL и историей браузера через history API.

page('/home', () => {
  console.log('Страница Home загружена');
});
page.start();

Метод page(path, callback) регистрирует маршрут. Метод page.start() запускает прослушивание изменений URL и инициализирует работу маршрутизатора.


Параметры маршрутов

Page.js поддерживает динамические сегменты URL, что позволяет извлекать параметры из маршрута.

page('/user/:id', (ctx) => {
  console.log(ctx.params.id); // выводит ID пользователя
});

Ключевые моменты:

  • :param — обязательный параметр маршрута.
  • * — wildcard для подстановки произвольной части пути.
  • ctx.params — объект с параметрами маршрута.
  • ctx.path — полный путь запроса.
  • ctx.querystring — строка запроса после ?.

Обработка middleware

Page.js поддерживает middleware-подход, аналогичный Express.js. Middleware вызываются последовательно для обработки запросов.

function auth(ctx, next) {
  if (!ctx.user) {
    page('/login');
  } else {
    next();
  }
}

page('/dashboard', auth, (ctx) => {
  console.log('Доступ разрешён');
});

Особенности middleware:

  • Middleware вызываются по порядку регистрации.
  • Для передачи управления следующему middleware вызывается next().
  • Можно использовать глобальные middleware: page('*', middleware).

Навигация и управление историей

Page.js обеспечивает работу с историей браузера через pushState и popState.

page('/about', () => { console.log('О странице'); });
page('/contact', () => { console.log('Контакты'); });

page.show('/about'); // программная навигация
page.back();         // возвращение на предыдущий маршрут

Особенности навигации:

  • page.show(path) инициирует переход без перезагрузки.
  • page.redirect(from, to) позволяет перенаправлять старые маршруты.
  • История браузера полностью синхронизирована с URL.

Работа с query-параметрами и хэшем

Page.js позволяет обрабатывать query-параметры и хэш.

page('/search', (ctx) => {
  const params = new URLSearchParams(ctx.querystring);
  console.log(params.get('q'));
});

Хэш-фрагменты (#section) можно учитывать через middleware:

page('*', (ctx, next) => {
  console.log('Хэш:', ctx.hash);
  next();
});

Деградация функциональности

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

Методы деградации:

  1. Серверная поддержка маршрутов

    • Каждый путь, который используется Page.js, должен корректно обрабатываться сервером.
    • Например, /user/123 на сервере должен возвращать HTML-шаблон с соответствующим контентом.
    • Если JavaScript отключён, браузер всё равно загружает страницу через стандартный GET-запрос.
  2. Универсальные ссылки

    • Все навигационные элементы (<a href="/page">) должны содержать правильный href.
    • Page.js перехватывает клики на этих ссылках, но при отсутствии JS они работают как обычные ссылки.
<a href="/dashboard">Панель</a>
  1. Минимальный функциональный слой

    • Можно добавить серверный рендеринг или статические HTML-страницы для критически важных маршрутов.
    • Page.js будет улучшением UX, а не единственным способом навигации.
  2. Graceful degradation middleware

    • Использовать middleware для проверки состояния приложения и подмены функционала, если определённые возможности браузера недоступны.
page('*', (ctx, next) => {
  if (!window.fetch) {
    ctx.fallback = true;
  }
  next();
});

Сочетание Page.js с Progressive Enhancement

Для поддержания доступности и деградации функциональности Page.js можно интегрировать с подходом Progressive Enhancement:

  • Основной контент рендерится сервером.
  • JavaScript улучшает интерактивность без замены базовой функциональности.
  • Навигация остаётся доступной даже при отключённом JS.

Пример структуры приложения:

<nav>
  <a href="/home">Главная</a>
  <a href="/profile">Профиль</a>
</nav>

<div id="app">
  <!-- базовый HTML-контент -->
</div>

<script src="page.min.js"></script>
<script>
  page('/home', () => { console.log('JS-навигация Home'); });
  page('/profile', () => { console.log('JS-навигация Profile'); });
  page.start();
</script>

В этом случае пользователи без JS видят полноценные страницы, а пользователи с JS получают плавную маршрутизацию и интерактивность.


Практические советы по деградации функциональности

  • Всегда использовать <a> вместо onclick для навигации.
  • Проверять поддержку history.pushState перед вызовом page.start().
  • Обеспечивать серверные маршруты для всех путей, используемых Page.js.
  • Middleware можно использовать для проверки возможностей браузера и подстройки поведения.
if (!window.history.pushState) {
  console.warn('Браузер не поддерживает pushState. Маршрутизация будет деградировать.');
}

Эти приёмы обеспечивают корректное поведение SPA в любых условиях, сохраняя доступность контента и минимизируя риск поломки функционала при ограничениях браузера или отключенном JavaScript.