微前端与常用的微前端解决方案

·  阅读 943

微前端是什么

简单来说 微前端是一个由多个应用组成的应用 或者 由多个微应用组成的一个主应用

换个角度来说:将庞大的整体拆成可控的小块。

微前端架构

满足几个特性:

  1. 技术栈无关
  2. 几个微应用可以使用不同的框架
    • 微应用独立开发,独立部署
  3. 仓库独立,各自部署
    • 微应用之间互不影响,稳定性高
  4. 独立运行
    • 每个微应用之间状态数据隔离,状态不共享

应用场景:

一般微前端还是应用在管理端,移动端应用比较少。

比如:公司内有多个业务部门,业务部门各自都有一个业务管理后台,而管理部门提出 1 个聚合功能需求,需要将各个部门的业务管理后台合并到一个总后台中,加载各个业务管理后台到总后台上。这时候有些管理后台是 vue2 有些是 vue3 有些是 react 有些是 angular,由于技术框架不同,迁移的人力成本和时间成本都会很高。

而如使用微前端架构,则可以利用微前端架构的特性去用较低成本去完成这个需求,将总后台作为主应用,每个业务管理后台作为一个微应用。

几种常见微前端方案

路由跳转分发

image.png

如图,在主应用中,通过 URL 跳转的方式进入到另一个微应用

即通过路由分发到不同的、独立前端应用上。

路由通常可以是应用框架自带的路由来实现,又或者通过服务器的反向代理实现。

iframe

可以创建一个全新的独立的宿主环境,可以友好的在主应用中展示微应用。

介绍一下iframe的通讯方式:

// parent
<body>
    <iframe id="react_iframe" src="http://localhost:3000/"> </iframe>
</body>
<script>
// 父窗口传信息给子窗口
    document.getElementById("react_iframe")
    .contentWindow.postMessage("react", "http://localhost:3000/");
// 父窗口监听子窗口的信息
    window.addEventListener("message", function (e) {
        console.log("form_child_iframe", e);
    });
</script>

// child src:http://localhost:8080/"
// 子窗口监听父窗口传递的信息
window.addEventListener("message", receivePerentMessage, false);
function receivePerentMessage(event) {
    console.log("form_perent_window", event);
}

// 子窗口给父窗口传递信息
window.parent.postMessage("child", "*");
复制代码

缺点:

  1. url 不同步。浏览器刷新时 iframe 数据状态会丢失、导航功能无法使用。
  2. UI 不协调。弹出一个遮罩弹窗只会在 iframe 内出现,Dom 的呈现不能跳出 iframe 的范围,如果要在浏览器居中弹出,需要通过 iframe 通讯在主应用中弹出兼容。
  3. 主应用的 cookie 要透传到根域名都不同的子应用中实现免登效果。
  4. storage 也需要从微应用中透传出给主应用。
  5. 加载速度慢。每次子应用进入都是一次浏览器上下文重建、资源重新加载的过程。

基于缺点,使用 iframe 做微前端,需要考虑:

  1. 设计管理应用机制
    1. 需要考虑主应用与微应用的交互
      1. 窗口中的组件的加载、卸载
      2. 拷贝公用 UI 组件到主应用,比如:浏览器全屏居中弹窗
  2. 设计应用通讯机制
    1. 数据共享
    2. 响应式刷新
    3. 事件监听

微应用化

微应用化即在开发和运行时,应用都是以单一、微小应用的形式存在。

qiankun.js框架

qiankun:qiankun 是一个基于  single-spa  的微前端实现库,旨在帮助大家能更简单、无痛的构建一个生产可用微前端架构系统。

主应用配置配置方式

微应用各框架配置方式

qiankun.js的通讯方式

// 在主应用中
// 主应用传递props属性给微应用
import { loadMicroApp } from 'qiankun';

microApp = loadMicroApp({
    name: 'app1',
    entry: '//localhost:1234',
    container: this.containerRef.current,
    props: { brand: 'qiankun' }, // 这里可以传递props属性给微应用
});
复制代码
// 微应用中就获取到props中携带的brand数据
export async function mount(props) {
  renderApp(props);
}

复制代码

如果微应用和微应用之间需要进行共享数据状态那应该怎么做 image.png

// 在主应用中的入口文件中
import { initGlobalStates } from 'qiankun';

// 初始化 state
const state={}
const actions = initGlobalState(state);
actions.onGlobalStateChange((state, prev) => {
  // state: 变更后的状态; prev 变更前的状态
  console.log(state, prev);
});
复制代码
// 微应用中从生命周期 mount 中获取的props中拿到通信方法
export function mount(props) {
    // 在当前应用监听全局状态,有变更触发 callback
    props.onGlobalStateChange((state, prev) => {
        // state: 变更后的状态; prev 变更前的状态
        console.log(state, prev);
    });
    // set状态API
  props.setGlobalState(state); 
}
复制代码
分类:
前端
标签: