Using Vue 2 component in Astro, not Vue3 .... is it possible?
ktmouk
Posted on February 11, 2023
Introduction
Recently, I've become interested in Astro and Island Architecture and have started reading its documentation.
As you know, Astro has a great feature called UI Framework Integrations that allows you to write components using popular frameworks such as React!
According to the official documentation, Astro already supports almost all of the popular frameworks: React, Vue3, and Svelte, which is great...... wait, where is Vue2?
Vue2 will reach EOL at the end of 2023
Seriously, I know that it has been announced in the official docs that Vue2 will be EOL, so there is no way Astro will support Vue2 in the future.
However, I am curious if it is technically possible for Astro to support Vue2.
Let's make Vue2 integration myself!
Fortunately, Astro's documentation already covers how to create a new integration and is easy to understand. And surprisingly, only three files need to be created to add a new integration: main.js, client.js, and server.js!
Now let's look into how to create a new integration.
main.js
This file is a sort of configuration file for the integration. When the astro:config:setup hook is called, Astro will add a renderer and update Vite settings according to this file.
The check function simply returns a boolean value indicating whether the given Component is the Vue2 component or not. so I used the staticRenderFns property, which only Vue2 has (although I don't know what the property is for...)
Also, The renderToStaticMarkup function should return a static HTML string based on the given Component. So I use the vue-server-renderer library to get the HTML from the Vue2 component.
client.js
The clientEntrypoint is simpler than the serverEntrypoint! Its role is to hydrate the Vue2 component based on the HTML created at SSR time.
Note that Astro has the client:only option that allows Astro to behave SPA-like. So I need to pass a boolean as the second argument to $mount to tell Vue2 if it should hydrate the component.
Let's use the Vue2 integration!
All done! Now let's try out this integration! Before trying it, I added the Vue2 integration to Astro's configuration in advance. The astro-vue2 package is the same as main.js.
This component is then used in an Astro component. Also, In this astro file, another Astro component is passed to the Vue2 component as a child component.
---// @ts-ignoreimportCounterfrom"../components/Counter.vue";importChildfrom"../components/Child.astro";importLayoutfrom"../layouts/Layout.astro";---<Layouttitle="Astro and Vue2"><main><CounterdefaultValue={10}client:visible><Childname={"Astro component"}/>
</Counter>
</main>
</Layout>
Does this actually work properly...? Of course, it does!
I've created just three files, but all of Astro's functions work surprisingly fine. Also, you can build these components with the astro build command!
This code is on GitHub
All of the code used in the demo is available on GitHub. If you're interested, you can view the code in this repository.
This is the proof of concept if Astro can integrate with Vue 2, not 3. I got curious about whether Astro can support Vue2 technically and I made it. It isn't meant for production use.
How to run
It is easy to run this project, like below.
If you don't install the pnpm, please install it referring to pnpm's installation in advaince.
# Run in dev mode.
pnpm install
pnpm dev
# Or build and look at it in preview mode. it also works fine!
pnpm install
pnpm preview
Folder structure
This repository consists of two packages managed by the pnpm workspace.
/integration
This is the library for Astro can integrate with Vue2.
I made it while referencing Vue3 plugin, which is offical integration.
/astro
This is the Astro project to test above plugin. It uses plugins at astro.config.mjs.