# 前言
single-spa-vue 是一个针对vue项目的初始化、挂载、卸载的库函数,可以实现 single-spa 注册的应用、生命周期函数等功能,详情请查看 single-spa-vue的github (opens new window)。
# 安装
# 使用Vue CLI的项目
vue-cli-plugin-single-spa (opens new window) 将会把所有的事情都做好.
vue add single-spa
这个CLI(控制台命令行接口)插件将会做下面的事情:
- 修改
webpack配置,从而使你的项目适用于一个single-spa项目或是一个子应用。 - 安装
single-spa-vue. - 修改你的
main.js或main.ts文件,从而使你的项目适用于一个single-spa项目或是一个子应用。 - 添加
set-public-path.js,从而有序地使用systemjs-webpack-interop来设置你的应用的public path。
# 没有使用Vue CLI的项目
npm install --save single-spa-vue
你可以通过选择引入
<script src="https://unpkg.com/single-spa-vue">到你的html文件中,就可以得到singleSpaVue全局变量
# 用法
如果没有安装过的话,请安装 systemjs-webpack-interop。
npm install systemjs-webpack-interop -S
在和项目目录同级的位置新建 set-public-path.js 文件作为你的 main.js/ts
import { setPublicPath } from 'systemjs-webpack-interop';
setPublicPath('appName');
将你的应用的入口文件改成如下内容:
请注意,如果您使用的是Vue CLI插件 main.ts or main.js 文件将用此代码自动更新并设置为 set-public-path.js 文件将自动创建应用程序名为您的 package.json 的name属性。
如果您想处理您的Vue实例,可以按照下面的步骤修改mount方法。mount方法将在v1.6.0之后使用Vue实例返回Promise。
const vueLifecycles = singleSpaVue({...})
export const mount = props => vueLifecycles.mount(props).then(instance => {
// 使用 vue 实例做你想做的事情
...
})
# Vue2
对于Vue 2,将应用程序的条目文件更改为:
import './set-public-path';
import Vue from 'vue';
import App from './App.vue';
import router from './router';
import singleSpaVue from 'single-spa-vue';
const vueLifecycles = singleSpaVue({
Vue,
appOptions: {
render(h) {
return h(App);
},
router,
},
});
export const bootstrap = vueLifecycles.bootstrap;
export const mount = vueLifecycles.mount;
export const unmount = vueLifecycles.unmount;
# Vue 3
对于Vue 3,将应用程序的条目文件更改为:
import './set-public-path';
import { h, createApp } from 'vue';
import singleSpaVue from '../lib/single-spa-vue.js';
import App from './App.vue';
const vueLifecycles = singleSpaVue({
createApp,
appOptions: {
render() {
return h(App, {
props: {
// single-spa 属性可以在 this 对象上使用。根据需要将它们转发给您的组件
// https://single-spa.js.org/docs/building-applications#lifecyle-props
name: this.name,
mountParcel: this.mountParcel,
singleSpa: this.singleSpa,
},
});
},
},
});
export const bootstrap = vueLifecycles.bootstrap;
export const mount = vueLifecycles.mount;
export const unmount = vueLifecycles.unmount;
出于性能上的考虑,Vue、Vue Router以及其他较大的库,最好使用相同的版本
# 自定义属性
single-spa 自定义属性可以传递到根组件,如下所示:
// main.js
const vueLifecycles = singleSpaVue({
Vue,
appOptions: {
render(h) {
return h(App, {
props: {
mountParcel: this.mountParcel,
otherProp: this.otherProp,
},
});
},
router,
},
});
// App.vue
<template>
<button>{{ otherProp }}</button>
</template>
<script>
export default {
props: ['mountParcel', 'otherProp'],
}
</script>
# 依赖共享
要实现不同应用间的依赖共享,添加你想要共享的依赖作为 webpack externals (opens new window)。然后使用 一个工作在浏览器中的模块加载工具,比如 systemjs (opens new window),来为 single-spa 中的每个项目提供这些共享的依赖,将 vue 以及其他库添加到 import map (opens new window)中。
如下案例给出一个 import map 的案例,可以作为参考: coexisting-vue-microfrontends (opens new window)的 index.html 文件。
依赖共享是被强烈建议的。详细的原因可以查看 recommended setup for single-spa (opens new window)
# 使用Vue CLI的情况下共享的配置
// vue.config.js
module.exports = {
chainWebpack: config => {
config.externals(['vue', 'vue-router']);
},
};
# 未使用Vue CLI的情况下共享的配置
// webpack.config.js
module.exports = {
externals: ['vue', 'vue-router'],
};
# 选项
当调用 singleSpaVue(opts) 时,所有选项都是通过 opts 参数传入 single-spa-vue 的
- Vue: (必传项) 主Vue对象, 通常暴露在window对象上,或通过
require('vue') ``import Vue from 'vue'获得 - appOptions: (必传项) 类型为Object对象类型,用来实例化Vue应用。appOptions将直接透传为Vue构造函数实例化时的初始化参数
new Vue(appOptions)。需要注意:如果你没有传el选项,插件就会自动创建一个div,并作为一个Vue项目的默认容器附加到DOM中。 - loadRootComponent: (非必传,用于取代
appOptions.render) 在懒加载时有用,一个以root component为成功回调参数的Promise对象。
可以用 appOptions.el 配置 single-spa 要挂载到哪个dom元素上:
onst vueLifecycles = singleSpaVue({
Vue,
appOptions: {
render: h => h(App),
el: '#a-special-container',
},
});
# 作为一个single-spa应用
想要创建一个single-spa应用,只需要从appOptions中去掉el选项,如此一来,dom元素将需要应用的开发者来指定,除此之外的其他选项都应该和上述案例保持一致
# Parcels
# 创建 parcel
parcel 是一个对象,它表示在Vue、React、Angular或任何其他框架中实现的组件
要创建 VueJS single spa parcel 配置对象,只需从appOptions中省略el选项,因为dom元素将由 Parcel 的用户指定。所有其他选项都应与上面的示例完全相同。
const parcelConfig = singleSpaVue({...});
# 渲染 parcel
要在Vue中呈现 parcel 配置对象,可以使用 single-spa-vue's Parcel 组件:
<template>
<Parcel
v-on:parcelMounted="parcelMounted()"
v-on:parcelUpdated="parcelUpdated()"
:config="parcelConfig"
:mountParcel="mountParcel"
:wrapWith="wrapWith"
:wrapClass="wrapClass"
:wrapStyle="wrapStyle"
:parcelProps="getParcelProps()"
/>
</template>
<script>
// For old versions of webpack
import Parcel from 'single-spa-vue/dist/esm/parcel'
// For new versions of webpack
import Parcel from 'single-spa-vue/parcel'
import { mountRootParcel } from 'single-spa'
const Widget =
export default {
components: {
Parcel
},
data() {
return {
/*
parcelConfig (object, required)
parcelConfig是一个对象,或者是一个与parcelConfig对象解析的 promise
对象可以来自当前项目中,也可以通过跨微前端导入来自不同的微前端。它可以表示Vue组件,也可以表示React/Angular组件。
https://single-spa.js.org/docs/recommended-setup#cross-microfrontend-imports
Vanilla js object:
parcelConfig: {
async mount(props) {},
async unmount(props) {}
}
// React component
parcelConfig: singleSpaReact({...})
// 交叉微前端导入如下所示
*/
parcelConfig: System.import('@org/other-microfrontend').then(ns => ns.Widget),
/*
mountParcel (function, required)
mountParcel 函数可以是当前Vue应用程序的 mountParcel 属性,也可以是全局可用的mount RootParcel 函数。更多信息请访问
http://localhost:3000/docs/parcels-api#mountparcel
*/
mountParcel: mountRootParcel,
/*
wrapWith (string, optional)
wrapWith字符串确定将为 parcel 提供哪种dom元素。默认为'div'
*/
wrapWith: 'div'
/*
wrapClass (string, optional)
wrapClass字符串用作提供给 parcel 的dom元素的CSS类。
*/
wrapClass: "bg-red"
/*
wrapStyle (object, optional)
wrapStyle对象作为CSS样式应用于 parcel 的dom元素容器
*/
wrapStyle: {
outline: '1px solid red'
},
}
},
methods: {
// These are the props passed into the parcel
getParcelProps() {
return {
text: `Hello world`
}
},
// Parcels mount 安装,因此 parcel 完成安装后将调用此方法
parcelMounted() {
console.log("parcel mounted");
},
parcelUpdated() {
console.log("parcel updated");
}
}
}
</script>