onBeforePrerenderStart() hook

The onBeforePrerenderStart() hook is executed upon pre-rendering your app.

It's only executed while pre-rendering and, consequently, never executed during development.

It's usually used for:

  • Providing the list of URLs of parameterized routes.

    If you have a pre-rendered page that has a parameterized route such as /movie/@id, then you need to provide a list of URLs such as /movie/1, /movie/2, /movie/3, ...

    Instead of providing a list of URLs, if you want a parameterized route to be resolved dynamically on the client-side, then see the workaround at #1476 - Pre-rendered dynamic routes (static host deployment).

  • Fetching data in bulk, in order to make pre-rendering execute faster.

For providing URLs

Most of the time, the onBeforePrerenderStart() hook is used for providing the URLs of parameterized routes.

// /pages/movie/+route.js
// Environment: Node.js
 
export default '/movie/@movieId'
// /pages/movie/+onBeforePrerenderStart.js
// Environment: Node.js
 
export { onBeforePrerenderStart }
 
async function onBeforePrerenderStart() {
  const movies = await Movie.findAll()
  const moviePageURLs = movies.map(movie => '/movie/' + movie.id)
  return moviePageURLs
}

If you don't have any parameterized route, then you can pre-render your app without defining any onBeforePrerenderStart() hook.

The onBeforePrerenderStart() hooks are called when you run $ vite build and, consequently, are never called in development.

For bulk data fetching

If you have a high number of pages that are to be pre-rendered, then running the command $ vite build may become slow.

You can make pre-rendering significantly faster by providing the pageContext of pages in onBeforePrerenderStart() hooks.

// /pages/movie/+route.js
// Environment: Node.js
 
export default '/movie/@movieId'
// /pages/movie/+onBeforePrerenderStart.js
// Environment: Node.js
 
export { onBeforePrerenderStart }
 
async function onBeforePrerenderStart() {
  const movies = await Movie.findAll()
 
  const moviePages = (
    movies
    .map(movie => {
      const url = '/movie/' + movie.id
      const pageContext = {
        data: {
          movie
        }
      }
      return {
        url,
        // Because we already provide the `pageContext`, Vike will *not* call
        // the `data()` (nor the `onBeforeRender()`) hook for `url`.
        pageContext
      }
      /* We could also only return `url` and not provide `pageContext`. In that case
       * Vike would call the `data()` (and `onBeforeRender()`) hook. But that would be wasteful
       * since we already have all the data of all movies from our `await Movie.findAll()` call.
       * Instead, we provide `pageContext` to make the pre-rendering build step faster.
       */
      // return { url }
    })
  )
 
  // We can also return URLs that don't match the page's route.
  // That way we can provide the `pageContext` of other pages.
  // Here we provide the `pageContext` of the `/movies` page since
  // we already have the data.
  const movieListPage = {
    url: '/movies', // Note how this URL '/movies' doesn't match the page's route /movie/@movieId
    pageContext: {
      data: {
        // We filter out the data we don't need in order to minimize what is sent
        // to the browser. We explain this practice at https://vike.dev/data-fetching
        movieList: movies.map(({id, title}) => ({id, title})
      }
    }
  }
 
  return [movieListPage, ...moviePages]
}

Essentially, the onBeforePrerenderStart() hook allows you to prefetch data for multiple pages at once.

Providing pageContext in onBeforePrerenderStart() hooks should only be used for making pre-rendering faster and we recommend against using onBeforePrerenderStart() hooks for other purposes.

For example, avoid providing additional pageContext values in onBeforePrerenderStart() hooks that wouldn't otherwise exist. Because onBeforePrerenderStart() hooks are never called in development and it's best to keep your app consistent between development and production.

Examples

React Example:

Vue Example:

TypeScript

export { onBeforePrerenderStart }
 
import type { OnBeforePrerenderStartAsync } from 'vike/types'
 
const onBeforePrerenderStart: OnBeforePrerenderStartAsync = async (
): ReturnType<OnBeforePrerenderStartAsync> => {
  // ...
}

Don't omit ReturnType<OnBeforePrerenderStartAsync> otherwise TypeScript won't strictly check the return type.

See API > pageContext > Typescript for more information on how to extend pageContext with your own extra properties.

See also