先了解一下2个api:
singleSpa.registerApplication
: 这是注册子项目的方法。参数如下:
appName
: 子项目名称applicationOrLoadingFn
: 子项目注册函数,用户需要返回 single-spa
的生命周期对象。后面我们会介绍single-spa
的生命周期机制activityFn
: 回调函数入参 location
对象,可以写自定义匹配路由加载规则。singleSpa.start
: 这是启动函数。
我们新建一个 single-spa-config.js
,并在main.js
内引入。
// main.js
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import Ant from 'ant-design-vue';
import './single-spa-config.js'
import 'ant-design-vue/dist/antd.css';
Vue.config.productionTip = false;
Vue.use(Ant);
new Vue({
router,
render: h => h(App)
}).$mount('#app')
single-spa-config.js
:
// single-spa-config.js
import * as singleSpa from 'single-spa'; //导入single-spa
/*
* runScript:一个promise同步方法。可以代替创建一个script标签,然后加载服务
* */
const runScript = async (url) => {
return new Promise((resolve, reject) => {
const script = document.createElement('script');
script.src = url;
script.onload = resolve;
script.onerror = reject;
const firstScript = document.getElementsByTagName('script')[0];
firstScript.parentNode.insertBefore(script, firstScript);
});
};
singleSpa.registerApplication( //注册微前端服务
'singleDemo',
async () => {
await runScript('http://127.0.0.1:3000/js/chunk-vendors.js');
await runScript('http://127.0.0.1:3000/js/app.js');
return window.singleVue;
},
location => location.pathname.startsWith('/vue') // 配置微前端模块前缀
);
singleSpa.start(); // 启动
与官方文档不同的是,这里使用了远程加载。父项目就处理完毕了,接下来处理子项目。
single-spa-vue
在 main.js
中引入 single-spa-vue
,传入Vue
对象和vue.js
挂载参数,就可以实现注册。它会返回一个对象,里面有single-spa
需要的生命周期函数。使用export
导出即可
import singleSpaVue from "single-spa-vue";
import Vue from 'vue'
const vueOptions = {
el: "#app",
router,
store,
render: h => h(App)
};
if (!window.singleSpaNavigate) { // 如果不是single-spa模式
delete vueOptions.el;
new Vue(vueOptions).$mount('#app');
}
// singleSpaVue包装一个vue微前端服务对象
const vueLifecycles = singleSpaVue({
Vue,
appOptions: vueOptions
});
// 导出生命周期对象
export const bootstrap = vueLifecycles.bootstrap; // 启动时
export const mount = vueLifecycles.mount; // 挂载时
export const unmount = vueLifecycles.unmount; // 卸载时
export default vueLifecycles;
子项目路由需要设置非history
,base
设置为父项目的一级路由。
const router = new VueRouter({
// mode: 'history',
base: '/vue/',
routes
})
只是导出了,还需要挂载到window
在项目目录下新建 vue.config.js
, 修改我们的webpack
配置。我们修改webpack output
内的 library
和 libraryTarget
字段。
output.library
: 导出的对象名output.libraryTarget
: 导出后要挂载到哪里同时,因为我们是远程调用,还需要设置 publicPath
字段为你的真实服务地址。否则加载子chunk
时,会去当前浏览器域名的根路径寻找,有404问题。
因为我们本地的服务启动是localhost:3000
,所以我们就设置 //localhost:3000
。
module.exports = {
publicPath: "//localhost:3000/",
// css在所有环境下,都不单独打包为文件。这样是为了保证最小引入(只引入js)
css: {
extract: false
},
configureWebpack: {
devtool: 'none', // 不打包sourcemap
output: {
library: "singleVue", // 导出名称
libraryTarget: "window", //挂载目标
}
},
devServer: {
contentBase: './',
compress: true,
}
};
执行 vue-cli-service serve --port 3000
后,就可以看到一直等待的界面了