吐槽一次qiankun微前端的框架
背景
心血来潮,想在自己的个人网站中体验一下微前端的魅力,其实也是为了满足我自己多个应用便于统一查看,而不需要跳来跳去的打开n多标签页,
不过微前端出来的主要目的:还是为了解决,真正使用中,多个团队协作共同维护同一个项目的不同模块,而互不影响上线流程,以及前端由于一个应用中n多模块导致的臃肿问题
目的
解决掉我现在的问题,以及体验微前端的框架使用
选型
qiankun
: 毕竟这几年沸沸扬扬的微前端理念使用,大多都是用它,它底层一直是基于single-spa
而封装的适合业务形态使用的框架。
qiankun官网
npm i -S qiankun
个人觉得文档还是比较糙,在使用中,很多时候还是要看源码 痛苦面具
- 主应用:react项目
- 微应用:原生的js项目(本文的例子)、vue项目、react项目、agular项目
说明
什么是主应用? 它就是让别的应用嵌入进入的宿主
什么是微应用? 它就是嵌入到别人应用的寄生虫
可以理解,就是宿主和寄生虫的关系!
简单的使用
解决两个问题:
- 主应用(宿主)怎么加载微应用(寄生虫)?
- 微应用(寄生虫)满足什么条件可以在主应用加载?(什么样的寄生虫可以进入宿主)
问题1
两种方式:(看这里)
- 批量加载微应用–适合作为一个路由,也就是一整个页面 registerMicroApps
- 单个加载微应用–适合作为单个组件,在某个页面的一部分 loadMicroApp
我是按照第二种方式使用的,如下
import React, { useRef, useEffect } from "react";
import { loadMicroApp, type MicroApp } from "qiankun";
const musicUrl = "xxx";
/**
* @abstract https://qiankun.umijs.org/zh/api#loadmicroappapp-configuration
*/
function MicroAppComp() {
const microAppRef = useRef<HTMLDivElement>(null);
const microApp = useRef<MicroApp>();
useEffect(() => {
const init = () => {
if (!microAppRef.current) return;
microApp.current = loadMicroApp(
{
name: "music",
entry: musicUrl,
container: microAppRef.current,
});
};
init();
return () => {
microApp.current?.unmount();
};
}, []);
return <div ref={microAppRef} />;
}
export default MicroAppComp;
随便当作一个组件使用即可,跟其他react组件没区别的。
问题2
满足的条件,这里以原生的js项目为例
/**
* 这段代码后续会在qiankun加载的时候,源码中读取的
*
*/
((global) => {
global['music'] = {
bootstrap: () => {
return Promise.resolve();
},
mount: () => {
console.log('music mount');
// render不需要写,页面所有的渲染都已用原声写完了,这里只是用来qiankun框架在运行loadApp 的时候,读取微应用的这个方法
},
unmount: () => {
console.log('music unmount');
return Promise.resolve();
}
};
})(window);
以上就是按照qiankun的设计方案,我们使用的微应用要添加的生命周期的钩子函数,当然你不加入,也会给你友好的报错 信息类似于:You need to export lifecycle functions in XXX entry
吐槽点
按照以上配置之后,可以使用
但是,
不完美的点在于,当我切换左侧的tab,在此点回来之后,对应的音乐组件不会重新加载,就像是这样
我歌词数据呢,然后发现是再次进来不加载了(估计设置了缓存)
查看源码,果不其然,发现qiankun项目开发团队,设置了缓存memorizedLoadingFn;
当我想通过配置去掉缓存,可是源码中根本不支持配置,很难受,希望可以加上配置!
当然我知道设计者的初衷是为了让我们用mount
这个钩子函数去触发渲染render
逻辑,但是有些时候,就是有这种情况存在,可以搞个配置让使用者关闭缓存的 (当然开发者会去承担没缓存导致页面每次加载应用过慢的后果呀)
诉求
加个配置项,让用户可以自己启用或者禁用缓存 (默认禁用)
暴力解决
直接通过脚本,在npm i之后,将源码的某一个文件替换掉,主要是为了屏蔽设置缓存的那段代码
这里会有三种方式的引入目录dist、es、lib
run.sh
# 我使用的是esmodule模块,大家根据自己的实际情况哈
# 比如你用外部引入 <link>标签 那就改dist中的index.umd.js代码了 require那就是lib目录下面要替换了
cp myown/apis.js node_modules/qiankun/es/apis.js
package.json
"scripts": {
"start": "npm run pre:run && node scripts/start.js",
"pre:run": "sh ./scripts/run.sh"
}
注释代码232-236行
- 为了更好的兼容是否开启缓存,我们也可以这样,(最好是锁住你的qiankun依赖的版本)如下
将注释的代码替换为这样的:
if (container) {
if ($$cacheLifecycleByAppName) {
appConfigPromiseGetterMap.set(
name,
parcelConfigObjectGetterPromise,
);
}
}
使用的时候,传入配置{ $$cacheLifecycleByAppName: false }
:
loadMicroApp(
{
name: "music",
entry: musicUrl,
container: microAppRef.current,
},
{ $$cacheLifecycleByAppName: false }, // 禁用缓存
);
效果如下
有缓存的时候
开启缓存之后
没有缓存
禁用缓存之后
写在最后
如果博主这篇文章,有帮助到大家,记得给博主点个赞,多多支持!