Destiner's Notes

Using Vue Components inside Astro

30 January 2022

Previously, we learned how to create a blog from scratch. So far, we didn’t use any components in our code. Here, I will show how to create and use Vue components inside Astro files.

Initializing the project

To simplify bootstrapping, let’s use a “Blog” template. You can browse available Astro templates here.

mkdir astro-blog
cd astro-blog
npm init astro -- --template blog
npm install
npm install @astrojs/vue vue

Enabling Vue support

Before we start, we need to enable Vue rendering. In your Astro config (astro.config.mjs), replace an existing renderer with a Vue one:

import vue from '@astrojs/vue';
import { defineConfig } from 'astro/config';

export default defineConfig({
  integrations: [vue()],
});

You don’t need to install the @astrojs/renderer-vue package, it will be bundled with Astro by default.

Creating a Vue component

You can create Vue components in Astro the same way as you do in normal Vue apps. You can use Options API, Composition API, or even <script setup>.

For the purpose of this guide, we will create an info banner component. Create a Banner.vue file inside src/components with the following:

<template>
  <div>{{ message }}</div>
</template>

<script
  setup
  lang="ts"
>
  defineProps({
    message: {
      type: String,
      required: true,
    },
  });
</script>

<style scoped>
  div {
    padding: 8px;
    border: 1px solid #aaa;
    border-radius: 4px;
    background: #eee;
  }
</style>

Using Vue components in Astro files

Let’s now see our component in action. Open src/pages/index.astro to import the component:

---
// Other imports
import Banner from '../components/Banner.vue';
---

And then use it inside the page template:

---
// Frontmatter script
---

<!-- Rest of the template -->
<Banner message="Hello, Vue!" />

You can also use JS expressions when passing prop values:

<Banner message={`2 + 3 is ${2 + 3}`} />

This way, you can use Vue components inside any Astro file. The other way, unfortunately, is not possible: you can’t use Astro components inside the Vue codebase.

Using Vue components in Markdown files

To use Vue components, you will need to use MDX insted of Markdown. See this guide for more information.

Change src/pages/posts/index.md file extension to an MDX document (index.mdx) and open it to import the Banner component:

---
// Frontmatter
---

import Banner from '../../components/Banner.vue';

;

And use it:

---
// Frontmatter
---

<!-- Page content -->

<Banner message="Hello, Vue in Markdown!" />

Building a site with Vue components

Depending on whether your component is static or dynamic, the site build will either include JS or not. In our example, the banner component is static. It doesn’t include any interactive parts, so the output will not include any JS. If we would create an interactive component (e.g. a counter), the output will include the necessary script to run the interactive parts of that component. In any case, the Vue compiler code will not be included.