# WeCube Portal 前端架构原则

## 名词解释

微前端： 微前端是一种类似于微服务的架构，它将微服务的理念应用于浏览器端，即将 Web 应用由单一的单体应用转变为多个小型前端应用聚合为一的应用。各个前端应用还可以独立运行、独立开发、独立部署。

iFrame：HTML 内联框架元素(<iframe>) 表示嵌套的 browsing context。它能够将另一个 HTML 页面嵌入到当前页面中。iFrame 可以创建一个全新的独立的宿主环境，iFrame 的页面和父页面是分开的，作为独立区域而不受父页面的 CSS 或者全局的 JavaScript 影响。

## 背景

WeCube 的产品定位于 IT 系统的管理工具，需要支持插件的动态加载及热插拔, 同时要兼顾具有集成企业原有应用作为插件的能力。

## 分析

基于背景及项目需求，可以考虑“微前端”作为项目架构方向，经过调研以及需求层面考虑，提出以下几种方案：

O - 满足  
X - 不满足

|                        | 动态注册前端路由 | 前端项目不重新编译打包 | 函数作用域 | 遗留系统迁移作为插件 | 新插件 | 优点               | 缺点                                   |
| ---------------------- | ---------------- | ---------------------- | ---------- | -------------------- | ------ | ------------------ | -------------------------------------- |
| iframe 内嵌\+路由代理  | O                | O                      | O          | O                    | O      | 简单容易实现       | 应用通信维护难，功能扩展难，样式控制难 |
| 动态引用静态资源（js） | O                | O                      | O          | X                    | O      | 交互体验，自主可控 | 不限插件前端框架，但是只能是 SPA 框架  |
| Web component          | O                | X                      | O          | X                    | O      | 交互体验           | 兼容性差（只支持 chrome/Opera）        |
| single\-SPA            | O                | X                      | O          | X                    | O      | 交互体验           | 不限插件前端框架，但是只能是 SPA 框架  |
| 脚本合并资源再打包     | O                | X                      | O          | X                    | O      | 交互体验           | 仅限同一个前端框架                     |


## 架构设计

通过动态引用资源来注册插件示意图

![示意图](https://github.com/WeBankOpenPlatform/wecube-platform/blob/master/wecube-wiki/images/微前端架构.png)

插件自己的前端页面分为两种类型： 单页面应用和多页面应用。

在需要满足兼顾企业遗留项目的前提下，需要对插件类型进行区分：  
a) 当插件前端为单页面应用时，可以通过动态引用 js，把插件的 js 文件动态插入到基座主工程中。  
b) 当插件前端为多页面应用时，可给插件页面预留 iframe 插槽，动态加载插件的前端静态资源。

所以初步拟定架构为：WeCube 框架接受两种插件  
a, 当插件为单页面应用时，采用动态引用 js 方式来引入插件；  
b, 当插件为多页面应用时，采用 iframe 方式来引入插件。

```
PS：初期为了减少基座开发量，推荐新插件的前端开发使用Vue + Vue Route来过得更好的兼容支持。
```

流程如下：

1，插件注册到 core 中， 需要声明是单页面应用还是多页面应用，需要的前端路由，需要所在的菜单位置，静态资源路由（单页面模式插件提供 js 静态文件路由，多页面模式插件提供独立运行的网址）等。

2，Portal 初始化时从 core 获取关于插件的配置文件，动态增加路由及创建插槽给插件。

3，去到插件对应路由页面时，通过静态资源路由加载资源。这个过程中，core 会提供 proxy/route 的能力来帮助 portal 加载到正确资源。

![架构流程图](https://github.com/WeBankOpenPlatform/wecube-platform/blob/master/wecube-wiki/images/插件注册前端流程图.jpg)

## 总结：  
初步认为single-spa对目前的情况成本有点高  
尝试替代方案：  
插件需要做的：  
1，修改vue.$mount的元素id，修改app.vue中的元素id，  
2，不要使用```() => import(/* webpackChunkName: "Task" */ './views/Task.vue')```这种懒加载方式，直接import组件  
3，插件在注册时，带有前端页面的插件需提供编译好的静态资源文件（js,css,image 等）  
基座需要做的：  
1，创建插件需要mount的元素，和插件指定的元素id一致  
2，请求插件所有的js和css，并运行  
3，注入插件菜单，并映射到插件对应的路由下  
后端要做的：  
1，需要CORE帮忙把静态资源放到文件服务器（如Nginx服务）的指定路径 或 CORE可以帮忙返回静态资源文件。  
