single-spa-vue is a helper library that helps implement single-spa registered application lifecycle functions (bootstrap, mount and unmount) for for use with Vue.js. Check out the single-spa-vue github.

Starter repo

For a full example, see coexisting-vue-microfrontends.

Live demo

https://coexisting-vue-microfrontends.surge.sh

Installation

Vue CLI

The vue-cli-plugin-single-spa will get everything set up.

  1. vue add single-spa

The CLI Plugin does the following for you:

  1. Modify your webpack config so that your project works as a single-spa application or parcel.
  2. Install single-spa-vue.
  3. Modify your main.js or main.ts file so that your project works as a single-spa application or parcel.
  4. Add a set-public-path.js that will use systemjs-webpack-interop in order to set the public path of your application.

Without Vue CLI

  1. npm install --save single-spa-vue

Alternatively, you can use single-spa-vue by adding <script src="https://unpkg.com/single-spa-vue"></script> to your html file and accessing the singleSpaVue global variable.

Usage

Install systemjs-webpack-interop if you have not already done so.

npm install systemjs-webpack-interop -S

Create a file at the same level as your main.js/ts called set-public-path.js

  1. import { setPublicPath } from 'systemjs-webpack-interop';
  2. setPublicPath('appName');

Change your application’s entry file to be the following.

  1. import './set-public-path';
  2. import Vue from 'vue';
  3. import App from './App.vue';
  4. import router from './router';
  5. import singleSpaVue from 'single-spa-vue';
  6. const vueLifecycles = singleSpaVue({
  7. Vue,
  8. appOptions: {
  9. render: h => h(App),
  10. router,
  11. },
  12. });
  13. export const bootstrap = vueLifecycles.bootstrap;
  14. export const mount = vueLifecycles.mount;
  15. export const unmount = vueLifecycles.unmount;

Note that if you are using the Vue CLI Plugin, your main.ts or main.js file will be updated with this code automatically and the set-public-path.js file will automatically be created with the app name being your package.json’s name property.

If you want to deal with your Vue instance, you can modify the mount method by following this. mount method will return Promise with Vue instance after v1.6.0.

  1. const vueLifecycles = singleSpaVue({...})
  2. export const mount = props => vueLifecycles.mount(props).then(instance => {
  3. // do what you want with the Vue instance
  4. ...
  5. })

Shared dependencies

For performance, it is best to share a single version and instance of Vue, Vue Router, and other large libraries.

To do this, add your shared dependencies as webpack externals. Then you use an in-browser module loader such as systemjs to provide those shared dependencies to each of the single-spa applications. Adding vue and other libraries to your import map. For an example import map that is doing this, checkout coexisting-vue-microfrontends’ index.html file.

Sharing a single instance of Vue and other common libraries is highly recommended. See the recommended setup for single-spa for more details on why.

Shared deps with Vue CLI

  1. // vue.config.js
  2. module.exports = {
  3. chainWebpack: config => {
  4. config.externals(['vue', 'vue-router']);
  5. },
  6. };

Shared deps without Vue CLI

  1. // webpack.config.js
  2. module.exports = {
  3. externals: ['vue', 'vue-router'],
  4. };

Options

All options are passed to single-spa-vue via the opts parameter when calling singleSpaVue(opts). The following options are available:

  • Vue: (required) The main Vue object, which is generally either exposed onto the window or is available via require('vue') import Vue from 'vue'.
  • appOptions: (required) An object which will be used to instantiate your Vue.js application. appOptions will pass directly through to new Vue(appOptions). Note that if you do not provide an el to appOptions, that a div will be created and appended to the DOM as a default container for your Vue application.
  • loadRootComponent: (optional and replaces appOptions.render) A promise that resolves with your root component. This is useful for lazy loading.

To configure which dom element the single-spa application is mounted to, use appOptions.el:

  1. const vueLifecycles = singleSpaVue({
  2. Vue,
  3. appOptions: {
  4. render: h => h(App),
  5. el: '#a-special-container',
  6. },
  7. });

As a single-spa parcel

To create a single-spa parcel, simply omit the el option from your appOptions, since the dom element will be specified by the user of the Parcel. Every other option should be provided exactly the same as in the example above.

Custom Props

single-spa custom props are added to your App component as appOptions.data, and are accessible via vm.$data. See this Vue documentation for more information on appOptions.data.