Skip to content

vitepress-plugin-cross-site-router

Исправляет навигацию и prefetch между несколькими независимо развёрнутыми экземплярами VitePress на одном origin.

Проблема

При хостинге нескольких VitePress-сайтов на одном домене с разными base-путями (например /alt-server/, /alt-workstation/) возникают две проблемы:

  1. Ошибка SPA-навигации - VitePress перехватывает все клики по ссылкам одного origin и пытается выполнить SPA-переход, не находит чанки соседнего сайта и ломается.
  2. Лишние prefetch-запросы - prefetcher VitePress пытается предзагрузить страницы соседних сайтов, получая 404.

Решение

Плагин подменяет логику router'а и prefetch'а:

  1. Перехватывает router.onBeforeRouteChange - если href не принадлежит текущему base, выполняет location.href (полный переход).
  2. Оборачивает window.IntersectionObserver до того, как VitePress создаст prefetch-observer - ссылки на соседние сайты в очередь prefetch не попадают.

Установка

bash
npm install @ampernic/vitepress-plugin-cross-site-router

Использование

Плагин состоит из двух частей: Vite-плагин (опционален, зарезервирован для будущего) и клиентский рантайм.

VitePress config

ts
import { CrossSiteRouterPlugin } from '@ampernic/vitepress-plugin-cross-site-router'

export default defineConfig({
  vite: {
    plugins: [CrossSiteRouterPlugin()],
  },
})

Theme enhanceApp

ts
import {
  installCrossSiteRouter,
  suppressCrossSitePrefetch,
} from '@ampernic/vitepress-plugin-cross-site-router/client'

export default {
  enhanceApp({ router, siteData }) {
    installCrossSiteRouter(router, siteData)
    suppressCrossSitePrefetch(siteData)
  },
}

API

installCrossSiteRouter(router, siteData, isCrossSite?)

Устанавливает хук router.onBeforeRouteChange, сохраняя ранее установленный хук в цепочке. Если целевой href не начинается с siteData.base или отсутствует в __VP_HASH_MAP__ (prod), выполняет location.href вместо SPA-перехода. Необязательный третий аргумент isCrossSite: (href, base) => boolean | undefined позволяет переопределить логику определения (возврат undefined роняет предикат в дефолт).

suppressCrossSitePrefetch(siteData, isCrossSite?)

Подменяет window.IntersectionObserver так, чтобы prefetch-observer VitePress никогда не добавлял в очередь ссылки, ведущие за пределы siteData.base. Третий аргумент такой же, как у installCrossSiteRouter - удобно передавать один и тот же предикат в обе функции.

isCrossSiteHref(href, base)

Утилита для проверки, является ли href межсайтовым относительно данного base. В prod-режиме учитывает __VP_HASH_MAP__ - страницы с общим префиксом base, но отсутствующие в текущей сборке, тоже считаются межсайтовыми (актуально для Forgejo Pages, где несколько распакованных инстансов делят родительский путь).

CrossSiteRouterPlugin(options?)

Vite-плагин. Сейчас пустой маркер ({ name: 'vitepress-plugin-cross-site-router' }) - вся логика живёт на клиенте. Точка входа для будущей build-time интеграции.

ОпцияТипОписание
isCrossSite(href, base) => boolean | undefinedТип предиката определения межсайтовых ссылок. Сейчас плагином не применяется - передавайте его третьим аргументом в installCrossSiteRouter / suppressCrossSitePrefetch.