How to Initialize Pinia Store State with Single-SPA Props & Single-SPA Vue
Context
We're developing a platform using Single-SPA as the micro-frontend framework. This platform integrates multiple applications, and it's common to share state between the App Shell (root-config) and these applications since it enhances re-usability and maintains clean code.
Problem
However, we encountered the challenge of sharing state between the App Shell (root-config) and a top-level Single-SPA Vue application (Header app) utilizing Pinia for state management.
A typical example is countries
. Being a food delivery platform operating in numerous countries, many of our
applications require access to country information. We initially fetch this "country" data from the
backend/authorization during the App Shell initialization and aim to
share it with top-level apps.
We identified two main methods to pass this data from the App Shell to the Header app:
-
Using
window.xxx
as a global variable to pass props; -
Utilizing Single-SPA Props to pass props to the application.
Here's an example using the global variable window._$jetms.availableCountries
within the store definition:
// Original store code snippet
export const useCountryStore = defineStore("country", () => {
const countries = ref<Country[]>([...window._$jetms.availableCountries].sort((a, b) => a.name.localeCompare(b.name)));
const activeCountry = ref<Country>(JETMS.activeCountry);
return {countries, activeCountry};
});
However, I decided against using window.xxx
due to its lack of type safety and instead opted for the more reliable
Single-SPA Props. Here's how I configured it in root-config
and read it in the
Header/main.ts.
const singleSpaGlobalProps = {
...app,
// customProps is the key to pass props to the application
customProps: {
...legacyFrameIntegration,
countries,
},
}
import {createApp, h} from 'vue';
import singleSpaVue from 'single-spa-vue';
import App from './App.vue';
import {createPinia} from "pinia";
const pinia = createPinia();
const vueLifecycles = singleSpaVue({
createApp,
appOptions: {
render() {
return h(App, {
// ...other props
countries: this.countries,
});
},
},
handleInstance(app: any) {
app.use(pinia)
}
});
The challenge then became initializing the Pinia store state with these custom props from Single-SPA.