背景
最近,工作中遇到一个问题:手头有两个项目,其中有几个模块界面功能都是一模一样的,所以想着是否可以共用一套代码。
发现有一些解决方案:
- 通过iframe嵌套页面;
缺点:遇到iframe高度控制问题,iframe是不能自适应变更的,所以需要在子应用里进行动态改变iframe的高度(包含各种数据渲染及图片加载完成的监听等),方法比较复杂,代码也会很冗杂;浏览器状态不同步,刷新后iframe状态丢失;
优点:但是没有跨域问题,样式和js隔离; - 通过qiankun(使用的是single-spa)配置微应用实现:
缺点:有跨域问题,需要部署在统一的域名下,而且父子应用之间的元素选择器的样式会互相影响;
优点:好处是父子应用里的代码修改不多,子应用中有相应标识能知道当前是子应用还是说独立访问。qiankun基本原理
qiankun框架的原理是使用fetch获取子应用的所有静态资源,然后将子应用的界面内容放入配置好的容器内,父子应用的内容不会互相隔离。基本配置
基本安装和配置点击链接遇到的一些问题
开发问题
基本描述:父应用使用vue技术栈,子应用使用create-react-app创建的项目(react v3.x),并且路由模式是hash模式,使用react-scripts启动。
开发时是在本地启动联调;
- 跨域问题
qiankun通过fetch引入静态资源,父应用和子应用开发环境并不在同一个端口,解决方法有两个:
- 1.1 本地启动nginx在同一个端口下分配不同前缀进行代理转发;
- 1.2 在子应用的启动项里增加允许跨域相关配置(本人子应用是webpack,修改config-overrides.js)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23module.exports = {
webpack: (config) => {
// 微应用的包名,这里与主应用中注册的微应用名称一致
config.output.library = `${name}`;
// 将你的 library 暴露为所有的模块定义下都可运行的方式
config.output.libraryTarget = 'umd';
// 按需加载相关,设置为 webpackJsonp_VueMicroApp 即可
config.output.jsonpFunction = `webpackJsonp_${name}`;
return config;
},
// 支持开发环境跨域
devServer: configFunction => {
return function (proxy, allowedHost) {
const config = configFunction(proxy, allowedHost);
config.headers = {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Headers":"content-type",
"Access-Control-Allow-Methods":"DELETE,PUT,POST,GET,OPTIONS"
};
return config;
};
},
};
- 子应用忽略一些脚本的加载
qiankun默认会加载子应用的所有脚本,如果有不需要在微应用中加载的脚本,可以在script标签加上ignore属性<script src="xxx.js" ignore></script>
- 父子应用polyfill问题
父子应用启动时只能存在一个polyfill,所以在开发时可以去掉其中一个。部署问题
- 部署后的主应用中注册的微应用entry配置需要同步变更为可访问地址;
1
2
3
4
5
6
7
8
9registerMicroApps([
{
name: 'microApp',
entry: '//microApp.xxx.com/microApp/index.html',
activeRule: '/microApp',
props: msg,
container: '#microAppContainer',
},
]);