Игнорирование внешних ссылок

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

Чтобы игнорировать внешние ссылки, важно понять два ключевых аспекта: определение внешней ссылки и механизм фильтрации в Page.js.


Определение внешней ссылки

Внешняя ссылка — это ссылка, домен которой отличается от текущего документа. Проверка может выполняться с использованием объекта URL:

function isExternalLink(href) {
    const linkUrl = new URL(href, window.location.origin);
    return linkUrl.origin !== window.location.origin;
}

Здесь window.location.origin возвращает протокол, домен и порт текущего сайта. Если origin ссылки не совпадает с текущим, она считается внешней. Такой подход универсален, учитывает протоколы http, https и порты.


Перехват кликов на ссылках

Page.js перехватывает переходы по ссылкам с помощью делегирования событий на document. Чтобы игнорировать внешние ссылки, необходимо добавить проверку внутри обработчика кликов:

document.addEventListener('click', function(event) {
    const anchor = event.target.closest('a');
    if (!anchor) return;

    if (isExternalLink(anchor.href)) return; // Игнорируем внешние ссылки

    event.preventDefault();
    page(anchor.pathname);
});

Ключевой момент: метод closest('a') позволяет корректно обрабатывать ссылки, вложенные в другие элементы, например кнопки или картинки внутри <a>.


Использование Page.js с фильтрацией ссылок

Page.js предоставляет возможность напрямую подключать фильтры перед вызовом маршрутов. Например, можно создать middleware для игнорирования внешних ссылок:

function ignoreExternal(ctx, next) {
    if (isExternalLink(ctx.path)) return;
    next();
}

page(ignoreExternal);

page('/about', () => {
    console.log('Страница "О нас" загружена');
});

page('/contact', () => {
    console.log('Страница "Контакты" загружена');
});

page();

Особенности работы:

  • Middleware вызывается перед обработкой маршрута.
  • Если ctx.path соответствует внешней ссылке, функция прерывает цепочку, предотвращая вызов next().
  • Для внутренних ссылок маршруты работают как обычно.

Игнорирование ссылок с определёнными атрибутами

Часто внешние ссылки имеют атрибут target="_blank" или класс .external. Page.js позволяет фильтровать их не только по домену, но и по атрибутам:

document.addEventListener('click', function(event) {
    const anchor = event.target.closest('a');
    if (!anchor) return;

    if (anchor.target === '_blank' || anchor.classList.contains('external')) return;

    event.preventDefault();
    page(anchor.pathname);
});

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


Комбинированный подход: домен + атрибуты

Для надёжной фильтрации рекомендуется объединять проверку на внешнюю ссылку и проверку атрибутов:

function shouldHandleLink(anchor) {
    return !isExternalLink(anchor.href) &&
           anchor.target !== '_blank' &&
           !anchor.hasAttribute('data-external');
}

document.addEventListener('click', function(event) {
    const anchor = event.target.closest('a');
    if (!anchor) return;
    if (!shouldHandleLink(anchor)) return;

    event.preventDefault();
    page(anchor.pathname);
});
  • Атрибут data-external позволяет явно маркировать ссылки, которые Page.js игнорирует.
  • Такой метод универсален, гибок и не требует изменения конфигурации самого маршрутизатора.

Обработка переходов с клавиатуры и других событий

Перехват кликов мышью — это не единственный способ навигации. Ссылки могут активироваться клавишей Enter или через скрипты. Page.js предоставляет объект page.start() с опцией click: true/false для включения или отключения глобального делегирования:

page.start({ click: true }); // Включает делегирование кликов

Чтобы полностью контролировать фильтрацию, можно отключить автоматический перехват кликов и обрабатывать их вручную через событие click, как показано выше.


Влияние игнорирования внешних ссылок на SEO и UX

  • Игнорирование внешних ссылок позволяет сохранять стандартное поведение браузера для внешних ресурсов.
  • Не нарушает индексацию сайта поисковыми системами, так как внешние ссылки остаются обычными <a> тегами.
  • Улучшает пользовательский опыт: внешние ресурсы открываются корректно, без ошибок маршрутизатора.

Рекомендации по структуре проекта

  1. Собрать все правила фильтрации в отдельный модуль. Это улучшает читаемость кода и облегчает поддержку.
  2. Использовать единый метод isExternalLink для всех ссылок. Избегается дублирование логики.
  3. Помечать явно ссылки, которые должны игнорироваться Page.js, через классы или data-атрибуты.
  4. Тестировать все варианты навигации: клики, Enter, скриптовые переходы.

Такой подход позволяет Page.js корректно работать с внутренней навигацией, полностью игнорируя внешние ссылки, сохраняя гибкость, контроль и безопасность пользовательского интерфейса.