Documents 🗃

When rendering index pages, it can be convenient to import multiple pages or MDX documents.

Although using import.meta.globEager works well, îles provides a better option.

useDocuments

The useDocuments composable can be used to access all files that are under the specified directory, or match a given pattern.

useDocuments('~/pages/posts')

Provide a glob pattern if you need to narrow down the matched documents:

useDocuments('~/pages/(posts|articles)/*.{md,mdx}')
Great HMR Support 🚀

Changes to each document and its frontmatter are instantly reflected.

It does not require a full page reload when files matching the pattern are added or removed.

Using Data in Documents

You can access each file's frontmatter and meta directly:

<script setup lang="ts">
import { usePosts } from '~/logic/posts'

const posts = useDocuments('~/pages/posts')
</script>

<template>
  <h1>Posts</h1>
  <article v-for="post of posts">
    <time :datetime="post.date.toISOString()">{{ formatDate(post.date) }}</time>
    <h2>
      <a :href="post.href">{{ post.title }}</a>
    </h2>
    <component :is="post" excerpt/>
  </article>
</template>
Rendering each document

You can render each document by passing it directly to <component>.

Typescript 💪🏼

Any frontmatter and meta properties will be typed, including extensions you have declared for PageMeta or PageFrontmatter.

function usePosts () {
  return useDocuments<Post>('~/pages/posts')
}
// typeof usePosts === ComputedRef<Post[]>
post.href // string
post.meta // PageMeta
post.frontmatter // PageFrontmatter

Ref Sugar (experimental in Vue)

Since useDocuments returns a Ref, when accessing documents in a script you would do:

export function usePosts () {
  const posts = useDocuments('~/pages/posts')
  return computed(() => posts.value.sort(byDate))
}

If you want to avoid using value, you can use ref sugar by wrapping it with $():

export function usePosts () {
  const posts = $(useDocuments('~/pages/posts'))
  return computed(() => posts.sort(byDate))
}

Comparison with import.meta.globEager

  • Significantly faster than import.meta.globEager, as it serves a single file
  • Can use any aliases you have defined in Vite, no need to use relative paths
  • Does not reload the page when files are added or removed

Last Updated: