Edit

+onBeforeRoute() hook

Environment: client, server
Global

The +onBeforeRoute hook provides full control over routing.

It is usually used for internationalization:

// Environment: server & client
 
export function onBeforeRoute(pageContext) {
  const { urlWithoutLocale, locale } = extractLocale(pageContext.urlPathname)
  return {
    pageContext: {
      locale,
      urlLogical: urlWithoutLocale
    }
  }
}
// Environment: server & client
 
import type { PageContext } from 'vike/types'
 
export function onBeforeRoute(pageContext: PageContext) {
  const { urlWithoutLocale, locale } = extractLocale(pageContext.urlPathname)
  return {
    pageContext: {
      locale,
      urlLogical: urlWithoutLocale
    }
  }
}

Vike also calls +onBeforeRoute when it prefetches a link, see also pageContext.isPrefetch.

You can also use it to:

⚠️
For more use cases, create a GitHub ticket: +onBeforeRoute is purposely limited but the limitations can be lifted in order to unlock new capabilities.

throw abort()

You can throw abort() to abort a client-side navigation: the user stays on the current page.

For example, to ask for confirmation before leaving a page with unsaved changes:

// /pages/+onBeforeRoute.client.js
// Environment: client
 
import { abort } from 'vike/abort'
 
export function onBeforeRoute(pageContext) {
  // +onBeforeRoute is also called when Vike prefetches links
  if (pageContext.isPrefetch) return
  if (
    // E.g. a global value set by your UI components
    globalThis.hasUnsavedChanges &&
    // Warn user
    !window.confirm('Leave this page? Your changes will be lost.')
  ) {
    throw abort()
  }
}
// /pages/+onBeforeRoute.client.ts
// Environment: client
 
import type { PageContextClient } from 'vike/types'
import { abort } from 'vike/abort'
 
export function onBeforeRoute(pageContext: PageContextClient) {
  // +onBeforeRoute is also called when Vike prefetches links
  if (pageContext.isPrefetch) return
  if (
    // E.g. a global value set by your UI components
    globalThis.hasUnsavedChanges &&
    // Warn user
    !window.confirm('Leave this page? Your changes will be lost.')
  ) {
    throw abort()
  }
}

This technique is useful because the browser's beforeunload event isn't fired upon client-side navigation.

You can use throw abort() only with +onBeforeRoute, only on the client-side, and only upon client-side navigation (not hydration).

See also