背景:
此前接手了一个老我的项目(3、4 年前开始的一个我的项目),面临的一个最大的问题是 老旧代码的保护和迭代。保护老旧代码的可选形式并不多:
- 推倒重来,全副进行重构 => 工作量沉重,老本极高
- 按照旧有技术选型进行保护和迭代 => emmmm,一言难尽
- 对于迭代需要采纳新的技术架构和选型,与已有性能解耦,尽量减少对旧代码的依赖和旧逻辑的批改
出于工作量和我的项目后续的可维护性和迭代性相对而言第 3 种计划比拟可行。因而调研了一下微前端计划来进行革新。
调研:
微前端入门
每日优鲜微前端革新
Alibaba-console-os VS Single-Spa
Alibaba-console-os
接入办法
- main.js 导出 Vue 做如下革新
import App from './App.vue'
import {mount} from '@alicloud/console-os-vue-portal'
export default mount({
el: '#app',
render: h => h(App)
})
- vue.config.js 做如下配置,减少 consoleOs 插件,并设定相应 id
module.exports = {
publicPath: 'http://localhost:8080/',
"pluginOptions": {
"consoleOs": {"id": "os-example-vue"}
}
}
- 在 Host App 中通过 manifest.json 文件引入相应子利用
import {start} from "@alicloud/console-os-kernal";
import Application from "@alicloud/console-os-react-app";
function App() {
return (
<div className="App">
<div className="vue">
<Application
id="os-example-vue"
manifest="http://localhost:8080/os-example-vue.manifest.json"/>
</div>
</div> );
}
Single-Spa
Ref: https://www.jianshu.com/p/c0f4b837dbea
Demo
- https://github.com/single-spa/single-spa
- https://juejin.im/post/5d3925615188257f3850de5a
接入办法
- main.js vue 导出文件做如下革新
import Vue from 'vue';
import singleSpaVue from 'single-spa-vue';
import Hello from './main.vue'
const vueLifecycles = singleSpaVue({
Vue,
appOptions: {
el: '#vue',
render: r => r(Hello)
}
});
export const bootstrap = [vueLifecycles.bootstrap,];
export const mount = [vueLifecycles.mount,];
export const unmount = [vueLifecycles.unmount,];
- single-spa.config.js 注册利用
import {registerApplication, start} from 'single-spa'
registerApplication(
'vue',
() => import('./src/vue/main.js'),
() => location.pathname === "/react" ? false : true);
start();
- index.html 配置
<html>
<head></head>
<body>
<div id="react"></div>
<div id="vue"></div>
<script src="/dist/single-spa.config.js"></script>
</body>
</html>
- webpack 配置
module.exports = {
entry: {'single-spa.config': './single-spa.config.js',},
}
Alibaba-console-os | SingleSpa | |
---|---|---|
子利用技术栈 | React、Vue、Angular | React、Vue、Angular |
主利用技术栈 | React、Angular | 不限 |
子利用资源配置模式 | manifest.json | single-spa.config.js |
抉择 SingleSpa 的起因
- Alibaba-console-os 的 Host App 不反对 Vue,咱们团队的主技术栈是 Vue
- Alibaba-console-os 子利用资源配置通过 manifest.json 引入,不实用咱们公司的资源部署形式
Single-Spa 实际:
架构
- 加载器:用来调度子利用,决定何时展现哪个子利用。
- 包装器:对现有的利用包装,使得加载器能够应用它们
- 主利用:个别是蕴含所有子利用公共局部的我的项目,
- 子利用:各个展现在主利用内容区的利用
大略是这样一个流程:用户拜访页面,浏览器运行加载器的 js 文件,加载器去获取配置文件,并注册配置文件中的各个子利用,首先加载主利用(比方菜单导航等),而后通过路由断定去动静加载子利用。
接入流程
- 创立子利用,将 admin 工程拆分为 edu-nav(菜单导航工程)、-old(原有业务性能工程)、edu-mis(新业务性能工程)
-
革新子利用,通过 singleSpa 对子利用进行包装。须要引入 single-spa-vue 以及 systemjs-webpack-interop。
- single-spa-vue 是针对 vue 我的项目的包装器,包导出 4 个生命周期函数:bootstrap、mount、unmount、update。
- systemjs-webpack-interop 能够使 webpack 和 systemjs 一起失常工作
-
创立主利用,充当加载器的性能,有以下几个工作。
- 配置资源 map,用于后续资源 SystemJs 引入
- 通过 SystemJs 引入资源文件
- 挂载 Publisher,用于子利用之间的通信。
- registerApplication 注册子利用,参数顺次为:注册的子利用名称、子利用入口文件(须要是一个函数)、管制利用是否激活的函数。
- singleSpa.start。启动函数。
- 配置资源 map,用于后续资源 SystemJs 引入
通过上述步骤,整个工程 singleSpa 革新实现。
实际中发现的一些问题
- 须要思考隔离 js,防止 css 抵触,并思考按需加载资源
- 专用数据信息的同步:菜单或业务线的切换产生时会通过 Publisher 进行告诉,然而在切换业务线后再从子利用 A 切换到子利用 B 时会呈现子利用 B 未曾接管到 Publisher 业务线切换音讯,导致业务线不精确。因而,须要在菜单工程中非凡解决,对路由进行拦挡判断,并再次进行音讯告诉。
- 要分外留神在原型上挂载一些全局变量或全局函数的行为,容易被后者笼罩。