正常操作,正常分析,你好,我是d1n910。
*因为下面的内容是纯手工输入的,所以可能会有打字错误。如果不是纯手工输入,屏幕截图将直接使用。
微型前端有多种方案。选择“乾坤”的原因是阿里巴巴团队制作的内容。严格地说,我相信这一点(大哥和大姐都有一个好的新年,抱着他们的大腿)。
微前端有很多方案,选择 `qiankun` 的原因是因为阿里团队出的内容。从技术上是比较信任的(大哥大姐过年好,抱大腿来了)。
说下我个人的考虑。
做微前端无非就是因为当网站越做越大,页面上有各种各样的 `服务`。
以下的会产生的困扰不分先后。
项目工程会很大;
构件速度会很慢;
不同核心业务功能放在一起;
不同业务团队会在一个大工程里进行开发工作。
传统用的比较多的方案其实就是——原生的iframe。
为什么不用 `iframe` 呢?
这里手打 `qiankun` 团队 `kuitos` 的 《Why Not Iframe》来作为解释。
Why Not Iframe
为什么不用 iframe,这几乎是所有微前端第一个被 challenge 的问题。但是大部分微前端方案又不约而同放弃了 iframe 方案 ,自然是有原因的,斌不是为了“炫技”或者刻意追求“特例独行”。
如果不考虑体验问题,iframe 几乎是最完美的微前端解决方案了。
iframe 最大的特性就是提供了浏览器原生的硬隔离方案,不论是样式隔离、js隔离这类问题统统都能被完美解决。但他的最大问题也在于他的隔离性无法被突破,导致应用间上下文无法被共享,随之带来的开发体验、产品体验的问题。
1、url 不同步。浏览器刷新 iframe url 状态丢失、后退前进按钮误无法使用。
2、UI 不同步,DOM 结构不同享。想象一下屏幕右下角 1/4 的 iframe 里来一个带遮罩层的弹框,同时我们要求这个弹框要浏览器居中显示,还要浏览器 resize 时自动居中。
3、全局上下完全隔离,内存变量不同享。iframe 内外系统的通信、数据同步等需求,主应用的 cookie 要透传到根域名都不同的子应用中实现免登效果。
4、慢。每次子应用进入都是一次浏览器上下文重建、资源重新加载的过程。
其中有的问题比较好解决(问题1),有的问题我们可以睁一只眼闭一只眼(问题4),但有的问题我们则很难解决(问题3)甚至无法解决(问题2),而这些无法解决的问题恰恰又会给产品带来非常严重的体验问题,最终导致我们舍弃了 iframe 方案。
提出了对于 iframe 难以解决的问题以后,实际上也就是说出了 qiankun 能够实现的事情。
那么继续往下看。
介绍
点击 qiankun 网站右上角的 `指南`,继续看介绍。
qiankun 是一个基于 single-spa 的微前端实现库,旨在帮助大家能更简单、无痛的构建一个生产可用微前端架构系统。- qiankun 介绍
【flag】要对 Micro Frontends 进行翻译
qiankun 孵化自蚂蚁金融科技基于微前端架构的云产品统一接入平台,在经过一批线上应用的充分检验及打磨后,我们将其微前端内核抽取出来并开源,希望能同时帮助社区有类似需求的系统更方便的构建自己的微前端系统,同时也希望通过社区的帮助将 qiankun 打磨的更加成熟完善。- qiankun 介绍
`微前端架构的云产品统一接入平台`,其实类似这样的微前端产品,我也有看过飞冰,也是阿里的(。・ω・。)
目前 qiankun 已在蚂蚁内部服务了超过 200+ 线上应用,在易用性及完备性上,绝对是指的信赖的。
意思是 `qiankun` 已经是蚂蚁内部落地使用很多的产品了,上过生产线。
什么是微前端
微前端是一种多个团队通过独立发布功能的方式来共同构建现代化 web 应用的技术手段及方法策略。- qiankun 介绍 – 什么是微前端
这个也是我想的做微前端的目的,比如在一个移动app上的首页,不同模块划分出来属于不同的业务团队去维护,而这些业务可以放在同一个容器里,同一个域名下,不同通过域名切换就可以用到不同的前端服务。
微前端架构具备以下几个核心价值:
技术栈无关
主框架不限制接入应用的技术栈,微应用具备完全自主权
独立开发、独立部署
微应用仓库独立,前后端可独立开发,部署完成后主框架自动完成同步更新
增量升级
在面对各种复杂场景时,我们通常很难对一个已经存在的系统做全量的技术栈升级或重构,而微前端是一种非常好的实施渐进式重构的手段和策略
独立运行时
每个微应用之间状态隔离,运行时状态不共享
更多关于微前端的相关介绍,推荐大家可以去看这这几篇文章:
– qiankun 介绍 – 什么是微前端
上面的微前端的核心价值,其实也就是咱们之前说的,仔细一看,原生的 `iframe` 就非常好实现。
qiankun 的核心设计理念
简单
由于主应用微应用都能做到技术栈无关,qiankun 对于用户而言只是一个类似 jQuery 的库,你需要调用几个 qiankun 的 API 即可完成应用的微前端改造。同时由于 qiankun 的 HTML entry 及 沙箱的设计,使得微应用的接入像使用 iframe 一样简单。
解耦/技术栈无关
微前端的核心目标是将巨石应用拆解成若干可以自治的松耦合微应用,而 qiankun 的诸多设计均是秉持这一原则,如 HTML entry、沙箱、应用间通信等。这样才能确保微应用真正具备 独立开发、独立运行 的能力。
– qiankun 介绍 – qiankun 的核心设计理念
看完以后连连点头,有一种 `俺也一样` 的感觉。
它是如何工作的
TODO – qiankun 介绍 – 它是如何工作的
回头我看源代码解析一下吧,其实应该是对 `iframe` 这个原生标签做了一层非常丰富的封装。
打脸:学了一段时间,发现其实是用 fetch 下载微服务的应用,然后插入到html元素中!
【flag】要看 qiankun 源代码
特性
???? 基于 single-spa 封装,提供了更加开箱即用的 API。
???? 技术栈无关,任意技术栈的应用均可 使用/接入,不论是 React/Vue/Angular/JQuery 还是其他等框架。
???? HTML Entry 接入方式,让你接入微应用像使用 iframe 一样简单。
???? 样式隔离,确保微应用之间样式互相不干扰。
???? JS沙箱,确保微应用之间 全局变量/事件 不冲突。
⚡️ 资源预加载,在浏览器空闲时间预加载为打开的微应用资源,加速微应用打开速度。
???? umi插件,提供 @umijs/plugin-qiankun 供 umi 应用一键切换成微前端架构系统。
– qiankun 介绍 – 特性
最后一个 `umi` 感觉比较好奥,挺想搞 umi 的了。
Last Update:2020/9/21 下午6:13:24
看完以上偏理论的内容以后,我对微前端以及qiankun概念已经明白了。自己总结的话,从递进式理解就是:
1、微前端就是把不同网站合在一起用,这些网站本身就是互不干扰的,用原生的iframe就很好实现;
2、其中single-spa对 iframe 做了一层封装,使得能够更好地实现一些通用的功能;
打脸:学了一段时间,发现是通过fetch来下载微应用的内容,然后实现了ifram拥有的内容!
3、qiankun是对single-spa做了又一层封装,提供了能多企业级(即生产常用的)开箱即用的API。
快速上手
主应用
1、安装 qiankun
$ yarn add qiankun # 或者 npm i qiankun -S
2、在主应用中注册微应用
import { registerMicroApps, start } from ‘qiankun’
registerMicroApps([
{
name: ‘my-first-micro-app’, // 自定义的name名
entry: ‘//loaclhost:7100’, // 启动的服务的地址
container: ‘#yourContainer’, //
activeRule: ‘/yourActiveRule’ //
}
])
start() // 启动微应用
当微应用信息注册完之后,一旦浏览器的url发生变化,便会触发 qiankun 的匹配逻辑,所有 activeRule 规则匹配上的微应用就会被插入到指定的 container 中,同时依次调用微应用暴露出的生命周期钩子。
如果微应用不是跟路由关 联的时候,比如就是想直接渲染展示的一些UI模块,可以使用手动加载微应用的方式。
// 官方示例
import { loadMicroApp } from ‘qiankun’;
loadMicroApp(
{
name: ‘app’,
entry: ‘//localhost:7100’,
container: ‘#yourContainer’,
}
);
微应用
微应用安装的时候不需要任何依赖
1、导出相应的生命周期钩子
微应用通常要在自己的入口js导出 bootstrap、mount、unmount 三个生命周期钩子,以供主应用在适当的时机调用。
这个入口通常就是你配置的webpack的entry.js,比如在 vue 里的是 main.js,官方的实例是 React 应用。
这三个生命周期钩子都是必须要导出的!
Bootstrap 钩子
bootstrap 只会在微应用初始化的时候调用一次,下次微应用重新进入会直接调用 mount 钩子,不会再重复触发 bootstrap。
通常我们可以在这里做一些全局变量的初始化,比如不会在 unmount 阶段被销毁的应用级别的缓存等
export async function bootstrap() {
console.log(‘bootstrap run’)
}
Mount 钩子
应用每次进入都会调用 mount 方法,通常我们在这里触发应用的渲染方法
export async function mount(props) {
console.log(props);
ReactDOM.render(<APP />, document.getElementById(‘react15Root’));
}
* 这里的渲染方法是对应 React 的render方法,在 Vue 里一般会自定义一个 render 方法来渲染。
/**
* 渲染函数
* 两种情况:主应用生命周期钩子中运行 / 微应用单独启动时运行
*/
function render ({ container } = {}) {
// 在 render 中创建 VueRouter,可以保证在卸载微应用时,移除 location 事件监听,防止事件污染
router = new Router({
…routes,
// 运行在主应用中时,添加路由命名空间 /chaiQiankun1/ffff,这和主应用中注册微应用时的activeRule相互对应
base: window.__POWERED_BY_QIANKUN__ ? ‘/app-vue-history’ : ‘/’,
mode: ‘history’
})
global.router = router
// 挂载应用
instance = new Vue({
router,
render: h => { return h(App) }
}).$mount(container ? container.querySelector(‘#appVueHistory’) : ‘#appVueHistory’)
}
// 独立运行时,直接挂载应用
if (!window.__POWERED_BY_QIANKUN__) {
render()
}
/**
* 应用每次进入都会调用 mount 方法,通常在这里我们会卸载微应用的应用实例
*/
export async function mount(props) {
console.log(‘mscrtApp mount’, props)
render(props)
}
Unmount 钩子
/**
* 应用每次 切出/卸载 会调用的方法,通常在这里我们会卸载微应用的应用实例
*/
export async function unmount() {
ReactDOM.unmountComponentAtNode(document.getElementById(‘react15Root’));
}
在 vue 里,之前存储元素的变量赋值为 null 即可。
export async function unmount() {
console.log(‘mscrtApp unmount’)
instance.$destroy()
instance.$el.innerHTML = ”
instance = null
router = null
}
Update 钩子 * 可选
这是可选的生命周期钩子,仅使用 loadMicroApp 方式加载微应用时生效
export async function update(props) {
console.log(‘update props’, props);
}
*qiankun 基于 single-spa,想要看更多关于微应用生命周期相关的文档说明看这里
没有webpack 等构建工具的应用接入方式 ⬇️
2. 配置微应用的打包工具
除了代码中暴露出相应的生命周期钩子之外,为了让主应用能正确识别微应用暴露出来的一些信息,微应用的打包工具需要增加如下配置:
webpack:
const packageName = require(‘./package.json’).name;
// 这里是为了拿应用的名称,微应用和主应用里引用的name名称要对应上,这里也不一定要package.json,可以是任意的js文件,也可以是直接写的name~
module.exports = {
output: {
library: `${packageName}-[name]`,
libraryTarge: ‘umd’,
jsonpFunction: `wbepackJsonp_${packageName}`,
}
}
在 vue.config.js 中放在 `configureWebpack` 中。
本期 End
真的非常简单易用,很快就能够跑起来了,简历上可以打上微应用三个字了。
我已经把`尊重`达到屏幕上了。
——就是各种遇到的 “BUG” 太多了。
这里再感谢一下龚顺同学,真的,太帅了, 真漂亮!在qiankun群里回答了N个人的问题,而且他的项目也帮了我很大的忙,我爱他。