Documents 🗃

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

Although using import.meta.glob('./dir/*.mdx', { eager: true }) 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.

Only String Literals

Just like glob imports in Vite.js, you need to provide a string pattern directly, variables are not supported as it wouldn't be possible to perform static analysis and infer which files to build.

Using Data in Documents

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

<script setup lang="ts">
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.glob

  • Significantly faster than import.meta.glob('./dir/*.mdx', { eager: true }), 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: