科学工具
科学工具让世界更美好
让世界更美好

京东微前端框架 Micro-App京东微前端框架 Micro-App

Micro-App是京东零售推出的一款微前端框架,基于类WebComponent进行渲染,从组件化的思维实现微前端,能降低前端开发的上手难度、提升工作效率。Micro-App是目前接入微前端成本最低的框架,提供了JS沙箱、样式隔离、元素隔离、预加载、虚拟路由系统、插件系统、数据通信等一系列完善的功能。Micro-App与技术栈无关,不与业务绑定,对前端框架没有限制,任何框架都可以作为基座应用嵌入任何类型的子应用。

微前端由ThoughtWorks在2016年提出,借鉴微服务架构理念,将庞大前端应用拆分为多个独立小型应用,每个应用可独立开发、运行和部署,再融合为完整应用。微前端解决两大问题:

1、迭代应用日益庞大导致的维护困难

2、跨团队协作开发导致的效率低下

许多前端项目经过多年迭代或交接,技术架构落后,新接手者面对冗余项目难以处理。微前端架构减少新旧项目耦合,提升扩展性,前端仓库更小更简单。

常见微前端实现方式包括iframe和微前端框架:

iframe方案

• 创建独立window窗口,完全隔离

• 天然样式和JS隔离特性

• 实现简单稳定

• 存在问题:性能不高、双滚动条、弹窗无法全局覆盖、刷新路由状态丢失

微前端框架

• 较早框架如single-spa,负责多应用融合

• qiankun基于single-spa封装,增加样式隔离、JS沙箱等功能

• 接入难度高于iframe,上限更高

Micro-App 特性

Micro-App未沿袭single-spa思路,而是借鉴WebComponent的思想,通过CustomElement结合自定义ShadowDom,将微前端封装成类WebComponent组件,实现组件化渲染。由于自定义ShadowDom的隔离特性,Micro-App不需要子应用修改渲染逻辑或暴露方法,不需修改webpack配置,是目前接入成本最低的微前端方案。

主要特点:

• 使用方式类似iframe,上手简单

• 对原代码几乎无影响,侵入性低

• 基于webComponents思想实现

• 功能完善:JS沙箱,样式隔离,预加载等

• 体积轻量:约10kb(gzip)

• 零依赖,不依赖第三方库

基础使用示例

主应用配置

1、安装依赖:

npm i @micro-zoe/Micro-App --save

2、入口文件引入并启动:

import microApp from '@micro-zoe/Micro-App'
microApp.start({
  destroy: true
})

3、页面中使用Micro-App组件:

<template>
  <div class="container">
    <Micro-App name="my-app-page1" url="http://localhost:5173/stand" disableSandbox inline></Micro-App>
  </div>
</template>

子应用配置

1、路由配置:

import { createRouter, createWebHashHistory } from "vue-router";

export const routes = [
  {
    path: "/",
    redirect: "/login",
  },
  {
    name: "login",
    path: "/login",
    component: () => import("@/pages/login.vue"),
  }
];

const router = createRouter({
  history: createWebHashHistory(),
  routes,
});

2、修改容器元素id确保唯一性:

<body>
  <div id="my-vite-app"></div>
</body>

3、使用新id渲染:

import { createApp } from "vue";
import App from "./App.vue";
app.mount("#my-vite-app");

4、静态资源使用绝对地址:

new URL('../assets/logo.png', import.meta.url).href

数据通信

主应用向子应用发送消息

通过EventCenterForMicroApp对象:

import { EventCenterForMicroApp } from '@micro-zoe/Micro-App';
window.eventCenterForAppNameVite = new EventCenterForMicroApp(name);

// 发送消息
microZoeApp.setData(name, { path: route.path });

通过data属性:

<Micro-App :url="url" :name="name" :data="data" />

子应用接收消息

监听主应用消息:

if (window.eventCenterForAppNameVite) {
  window.eventCenterForAppNameVite.addDataListener(data => {
    router.replace({ path: data.path })
  })
}

获取data属性值:

window.eventCenterForAppNameVite.getData('app-child-vue3')

子应用向主应用发送消息

通过dispatch方法:

window.eventCenterForAppNameVite.dispatch({
  from: '来自子系统的消息',
  msg: '子应用发送的数据',
});

主应用接收子应用消息

通过datachange事件:

<Micro-App @datachange="dataChange" />
const dataChange = v => {
  console.log(v);
};

路由冲突解决

主应用和子应用都是vue-router4时可能相互冲突,导致浏览器返回按钮路由错误。解决方案:

if (window.__MICRO_APP_ENVIRONMENT__) {
  const realBaseRoute = window.__MICRO_APP_BASE_ROUTE__;
  
  router.beforeEach(() => {
    if (typeof window.history.state?.current === 'string') {
      window.history.state.current = window.history.state.current.replace(
        new RegExp(realBaseRoute, 'g'), '')
    }
  })

  router.afterEach(() => {
    if (typeof window.history.state === 'object') {
      window.history.state.current = realBaseRoute + (window.history.state.current || '')
    }
  })
}

开发环境

克隆并运行项目:

git clone https://github.com/micro-zoe/Micro-App.git
cd Micro-App
yarn bootstrap
yarn start

默认启动主应用main-react16和子应用react16、react17、vue2、vue3、angular11、vite。

单独运行主应用:

yarn start:main-vue2

单独运行子应用:

cd dev/children/react16
yarn start

资源

• 源码地址:http://github.com/micro-zoe/Micro-App

• 官网地址:http://zeroing.jd.com/Micro-App

• iPaaS地址:http://ipaas.jd.com