single-spa 到底是干嘛的
single-spa 仅仅是一个子应用生命周期的调度者。 single-spa 为应用定义了 boostrap, load, mount, unmount 四个生命周期回调
只要写过 SPA 的人都能理解,无非就是生、老、病、死。不过有几个点需要注意一下:
- Register 不是生命周期,指的是调用
registerApplication
函数这一步 - Load 是开始加载子应用,怎么加载由开发者自己实现(等会会说到)
- Unload 钩子只能通过调用
unloadApplication
函数才会被调用
OK,上面 4 个生命周期的回调顺序是 single-spa 可以控制的,我能理解,那什么时候应该开始这一套生命周期呢?应该是有一个契机来开始整套流程的,或者某几个流程的。
契机就是当 window.location.href
匹配到 url 时,开始走对应子 App 的这一套生命周期嘛。所以,single-spa 还要监听 url 的变化,然后执行子 app 的生命周期流程。
到此,我们就有了 single-spa 的大致框架了,无非就两件事:
- 实现一套生命周期,在 load 时加载子 app,由开发者自己玩,别的生命周期里要干嘛的,还是由开发者造的子应用自己玩
- 监听 url 的变化,url 变化时,会使得某个子 app 变成 active 状态,然后走整套生命周期
SingleSpa 实战
构建子应用
- 安装包
vue create spa-vue
npm install single-spa-vue
- 修改main.js
import singleSpaVue from 'single-spa-vue';
const appOptions = {
el: '#vue',
router,
render: h => h(App)
}
// 在非子应用中正常挂载应用
if(!window.singleSpaNavigate){
delete appOptions.el;
new Vue(appOptions).$mount('#app');
}
const vueLifeCycle = singleSpaVue({
Vue,
appOptions
});
// 子应用必须导出 以下生命周期 bootstrap、mount、unmount
export const bootstrap = vueLifeCycle.bootstrap;
export const mount = vueLifeCycle.mount;
export const unmount = vueLifeCycle.unmount;
export default vueLifeCycle;
3.配置子路由基础路径
const router = new VueRouter({
mode: 'history',
base: '/vue',
routes
})
页面路由匹配到/vue就会去加载这个子应用
4.将子模块打包成类库,方便加载
module.exports = {
configureWebpack: {
output: {
library: 'singleVue',
libraryTarget: 'umd'
},
devServer:{
port:10000
}
}
}
构建主应用
1.构建路由和价值root
<div id="nav">
<router-link to="/vue">vue项目</router-link>
<div id="vue"></div>
</div>
2.主应用注册子应用
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
Vue.use(ElementUI);
// 自己构建的
const loadScript = async (url)=> {
await new Promise((resolve,reject)=>{
const script = document.createElement('script');
script.src = url;
script.onload = resolve;
script.onerror = reject;
document.head.appendChild(script)
});
}
import { registerApplication, start } from 'single-spa';
registerApplication(
'singleVue',
async ()=>{
await loadScript('http://localhost:10000/js/chunk-vendors.js');
await loadScript('http://localhost:10000/js/app.js');
return window.singleVue
},
// 当匹配到/vue开头的,开始价值子应用
location => location.pathname.startsWith('/vue')
)
start();
new Vue({
router,
render: h => h(App)
}).$mount('#app')
3.解决资源问题,动态设置子应用publicPath
if(window.singleSpaNavigate){
__webpack_public_path__ = 'http://localhost:10000/'
}
效果展示
写在最后:下一篇将着重使用大量时间给大家详细《微前端从零到剖析qiankun源码 --- singleSpa源码分析》