Data Fetching

Preload

Page components can have an optional preload function that will load some data that the page depends on:

<script>
import { fetch } from 'ream/fetch'

export const preload = async (context) => {
  const posts = await fetch(`/blog/posts.json?user=${context.params.user}`)
  return {
    // `props` will be passed to the component as props
    props: {
      posts,
    },
  }
}

export default {
  props: ['posts'],
}
</script>

The context parameter is an object containing the following keys:

  • params contains the route parameters for pages using dynamic routes. For example, if the page name is [id].vue, then params will look like { id: '...' }. To learn more, take a look at the Dynamic Routing documentation.

How does preload work

The preload function is similar to getInitialProps in Next.js and asyncData in Nuxt.js, it's executed on both server-side and client-side before rendering a page.

Server Preload

preload function is also executed in browser which means you can't just query a database there, you'll have to write browser-compatible code and use browser-compatble libraries.

Luckily you can use serverPreload to get rid of that, you can query a database like this:

<script>
import { db } from './path/to/db'

export const serverPreload = async (context) => {
  const posts = await db.findPosts({ user: context.params.user })
  return {
    props: {
      posts,
    },
  }
}

export default {
  props: ['posts'],
}
</script>

You can write anything as if you're writing a Node.js server in the serverPreload function, these code will never be exposed on the client-side.

How does serverPreload work

On the server-side, it behaves the same as preload, on the client-side, instead of executing this function, we send a request to the server to get the result of serverPreload, the function is entirely processed on the server-side. We also automatically eliminate this function and whatever this function depends on from the client bundle.

Static Preload

Ream applies incremental static page generation to pages that don't use preload or serverPreload, meaning that you can dynamically render some pages while pre-rendering the other pages.

In many cases you will still need to use external data on pre-rendered pages, Ream provides staticPreload for such use case:

For example, let's say you are building a static blog, and you want to fetch blog posts from an external API:

<!-- routes/posts/[id].vue -->
<script>
export const staticPreload = async (context) => {
  const post = await fetchPostFromApi({ id: context.params.id })
  return {
    props: {
      post,
    },
  }
}

export default {
  props: ['post'],
}
</script>

staticPreload is actually very similar to serverPreload, both of them are executed on server-side, but staticPreload will pre-render the pages:

  • For dynamic routes (i.e. :id), Ream renders them at request time but will cache the result and subsequent requests will use the cache instead.
  • For static routes, it's rendered at build time.

Static Paths

For dynamic routes, you can also render them at build time by using the staticPaths option, suppose that you have a page that uses dynamic routes named src/pages/posts/[id].vue

<script>
export const staticPreload = async (context) => {
  const post = await fetchPostFromApi({ id: context.params.id })
  return {
    props: {
      post,
    },
  }
}

export const staticPaths = () => {
  return {
    paths: [
      {
        params: {
          /* ... */
        },
      },
    ],
  }
}

export default {
  props: ['post'],
}
</script>

The paths key returned by staticPaths determines which paths will be pre-rendered at build time. For example, if you return following value:

return {
  paths: [{ params: { id: 1 } }, { params: { id: 2 } }],
}

Then Ream will statically generate posts/1 and posts/2 at build time.

Note that if you want to export static website, you don't have to use staticPaths.