蚂蚁金服微前端框架
qiankun 是一个基于 single-spa 的微前端实现库,旨在帮助大家能更简单、无痛的构建一个生产可用微前端架构系统。官方文档
核心设计理念
- 简单:由于主应用微应用都能做到技术栈无关,qiankun 对于用户而言只是一个类似 jQuery 的库,你需要调用几个 qiankun 的 API 即可完成应用的微前端改造。同时由于 qiankun 的 HTML entry 及沙箱的设计,使得微应用的接入像使用 iframe 一样简单。
- 解耦/技术栈无关:微前端的核心目标是将巨石应用拆解成若干可以自治的松耦合微应用,而 qiankun 的诸多设计均是秉持这一原则,如 HTML entry、沙箱、应用间通信等。这样才能确保微应用真正具备 独立开发、独立运行 的能力。
架构特点/特性
- 基于 single-spa 封装,提供了更加开箱即用的 API。
- 技术栈无关,任意技术栈的应用均可 使用/接入,不论是 React/Vue/Angular/JQuery 还是其他等框架。
- HTML Entry 接入方式,让你接入微应用像使用 iframe 一样简单。
- 样式隔离,确保微应用之间样式互相不干扰。
- JS 沙箱,确保微应用之间 全局变量/事件 不冲突。
- 资源预加载,在浏览器空闲时间预加载未打开的微应用资源,加速微应用打开速度。
在项目中的实践
- 新建项目qianguan_demo[或者借助vue-cli 来构建工程]
F:\learn>mkdir qianguan_demo
F:\learn>cd qianguan_demo
F:\learn\qianguan_demo>npm init -y
F:\learn\qianguan_demo>code .
- 安装qiankun依赖
F:\learn\qianguan_demo>npm install -S qiankun
整体工程图下
- 在主应用中注册微应用: 编辑工程中的main.js文件
注册路由
registerMicroApps([{
name: 'dfms',
entry: '//localhost:8081',
renderHtml,
activeRule: activeRule('/dfms')
}, {
name: 'apiaudit',
entry: '//localhost:8082',
renderHtml,
activeRule: activeRule('/apiaudit')
}, {
name: 'ddm',
entry: '//localhost:7040',
renderHtml,
activeRule: activeRule('/ddm')
}])
tips: qiankun是通过registerMicroApps(apps, lifeCycles)API来注册子应用的,监听当浏览器 url 发生变化时,自动加载相应的子应用的功能,更多api
registerMicroApps(apps, lifeCycles?))
参数
- apps - Array - 必选,微应用的一些注册信息
- lifeCycles - LifeCycles - 可选,全局的微应用生命周期钩子
RegistrableApp 参数
- entry: 子应用的 entry 地址,比如我们现在有两个子应用A和B,那么这里配置的就是他们的资源访问域名或ip
- render:应用的容器节点的选择器或者 Element 实例。如container: ‘#root’ 或 container: document.querySelector(’#root’)
- activeRule:微应用的激活规则,支持直接配置字符串或字符串数组和支持配置一个 active function 函数或一组 active function
- more
渲染函数和绑定dom根节点
function renderHtml (appContent) {
if (global_app) {
global_app.content = appContent
} else {
global_app = new Vue({
el: "#app",
data () {
return {
content: appContent
}
},
render: h => h(App, {
props: {
content: this.content
}
})
})
}
}
规则处理
function activeRule (prefix) {
return location => location.pathname.startsWith(prefix)
}
tips: 生命周期钩子
/**
* bootstrap 只会在微应用初始化的时候调用一次,下次微应用重新进入时会直接调用 mount 钩子,不会再重复触发 bootstrap。
* 通常我们可以在这里做一些全局变量的初始化,比如不会在 unmount 阶段被销毁的应用级别的缓存等。
*/
export async function bootstrap() {
console.log('react app bootstraped');
}
/**
* 应用每次进入都会调用 mount 方法,通常我们在这里触发应用的渲染方法
*/
export async function mount(props) {
console.log(props);
ReactDOM.render(<App />, document.getElementById('react15Root'));
}
/**
* 应用每次 切出/卸载 会调用的方法,通常在这里我们会卸载微应用的应用实例
*/
export async function unmount() {
ReactDOM.unmountComponentAtNode(document.getElementById('react15Root'));
}
/**
* 可选生命周期钩子,仅使用 loadMicroApp 方式加载微应用时生效
*/
export async function update(props) {
console.log('update props', props);
}
- 修改app.vue
<div id="main">
<button @click="changeView('/dfms')">子应用dfms</button>
<button @click="changeView('/apiaudit')">子应用apiaudit</button>
<button @click="changeView('/ddm')">子应用ddm</button>
<div id="main-view" v-html="content"></div>
</div>
name: 'App',
methods: {
changeView(who){
window.history.pushState(null, who, who)
}
},
props: {
content: String
}
- 配置跨域代理
devServer: {
https: false,
port: 7001,
headers: {
'Access-Control-Allow-Origin':'*'
}
}
- 运行三个项目
- ddm: 在ddm 工程下 yarn run serve
- dfms: 在dfms 工程下 yarn run serve
- apiaudit: 在apiaudit 工程下 yarn run serve