Search code examples
vue.jspiniaastrojs

Astro/Vue is executing appEntrypoint one time per component


I have few Vue components in an Astro page that are sharing the state via Pinia

I initialised the Pinia plugin as the Astro documentation mentions, via astro.config.mjs:

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

// https://astro.build/config
export default defineConfig({
    // Enable Vue to support Vue components.
    integrations: [vue({
        isProduction: false,
        appEntrypoint: '/src/_app'
    })],
});

And then in /src/_app.ts:

import type { App } from "vue";
import { createPinia } from 'pinia'

export default (app: App) => {
    console.log("Why is initializing one time per component!", app.config)
    app.use(createPinia());
};

The problem is that app.use(createPinia()); is executed one time per component. So looks like because this issue, Pinia creates one Storage per component instead one sharing.

Of course, the problem is happening with all plugins. For example, app.use(InstantSearch); is executed one time per component as well, so it is doing extra calls to the server and creating X searchs plugins instances.

Here a really simple project reproducing the error, and Here the link to the stackblitz running example

Also, I created a bug issue but not sure if it is.

If this is not a bug, how to init Vue plugins per page?


Solution

  • astro is build with the island architecture, which means, that each island will be it's own application. There is no way, except you have one astro component, that runs the full vue application.

    But you can use pinia without the plugin usage which you can find in the SSR guide.

    create a pinia store in a seperate file

    // a file like ./src/store.ts
    import { createPinia } from 'pinia'
    export const appStore = createPinia();
    

    pass the pinia store to the store composable

    whenever you use your store composable (created with defineStore) you need to pass the pinia store to that composable.

    <script setup>
    import { appStore } from '../store.ts';
    const appStore = useAppStore(appStore);
    </script>
    

    Then you are able to use the same state in all different applications.