背景:

此前接手了一个老我的项目(3、4年前开始的一个我的项目),面临的一个最大的问题是老旧代码的保护和迭代。保护老旧代码的可选形式并不多:

  1. 推倒重来,全副进行重构 => 工作量沉重,老本极高
  2. 按照旧有技术选型进行保护和迭代 => emmmm,一言难尽
  3. 对于迭代需要采纳新的技术架构和选型,与已有性能解耦,尽量减少对旧代码的依赖和旧逻辑的批改

出于工作量和我的项目后续的可维护性和迭代性相对而言第3种计划比拟可行。因而调研了一下微前端计划来进行革新。

调研:

微前端入门
每日优鲜微前端革新

Alibaba-console-os VS Single-Spa

Alibaba-console-os

接入办法

  1. 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)  })  
  1. vue.config.js 做如下配置,减少 consoleOs插件,并设定相应id
module.exports = {      publicPath: 'http://localhost:8080/',      "pluginOptions": {          "consoleOs": {              "id": "os-example-vue"          }      }  } 
  1. 在 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

接入办法

  1. 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,  ];
  1. single-spa.config.js 注册利用
import { registerApplication, start } from 'single-spa'  registerApplication(      'vue',      () => import('./src/vue/main.js'),      () => location.pathname === "/react" ? false : true);  start();
  1. index.html 配置
<html>      <head></head>      <body>          <div id="react"></div>          <div id="vue"></div>          <script src="/dist/single-spa.config.js"></script>      </body>  </html> 
  1. webpack配置
module.exports = {      entry: {          'single-spa.config': './single-spa.config.js',      },  }
Alibaba-console-osSingleSpa
子利用技术栈React、Vue、AngularReact、Vue、Angular
主利用技术栈React、Angular不限
子利用资源配置模式manifest.jsonsingle-spa.config.js

抉择SingleSpa的起因

  1. Alibaba-console-os 的Host App不反对Vue,咱们团队的主技术栈是Vue
  2. Alibaba-console-os子利用资源配置通过manifest.json引入,不实用咱们公司的资源部署形式

Single-Spa实际:

架构

  1. 加载器:用来调度子利用,决定何时展现哪个子利用。
  2. 包装器:对现有的利用包装,使得加载器能够应用它们
  3. 主利用:个别是蕴含所有子利用公共局部的我的项目,
  4. 子利用:各个展现在主利用内容区的利用

大略是这样一个流程:用户拜访页面,浏览器运行加载器的js文件,加载器去获取配置文件,并注册配置文件中的各个子利用,首先加载主利用(比方菜单导航等),而后通过路由断定去动静加载子利用。

接入流程

  1. 创立子利用,将admin工程拆分为edu-nav(菜单导航工程)、-old(原有业务性能工程)、edu-mis(新业务性能工程)
  2. 革新子利用,通过singleSpa对子利用进行包装。须要引入single-spa-vue以及systemjs-webpack-interop。

    • single-spa-vue是针对vue我的项目的包装器,包导出4个生命周期函数:bootstrap、mount、unmount、update。
    • systemjs-webpack-interop能够使webpack和systemjs一起失常工作

  1. 创立主利用,充当加载器的性能,有以下几个工作。

    1. 配置资源map,用于后续资源SystemJs引入
    2. 通过SystemJs引入资源文件
    3. 挂载Publisher,用于子利用之间的通信。
    4. registerApplication注册子利用,参数顺次为:注册的子利用名称、子利用入口文件(须要是一个函数)、管制利用是否激活的函数。
    5. singleSpa.start。启动函数。

通过上述步骤,整个工程singleSpa革新实现。

实际中发现的一些问题

  1. 须要思考隔离js,防止css抵触,并思考按需加载资源
  2. 专用数据信息的同步:菜单或业务线的切换产生时会通过Publisher进行告诉,然而在切换业务线后再从子利用A切换到子利用B时会呈现子利用B未曾接管到Publisher业务线切换音讯,导致业务线不精确。因而,须要在菜单工程中非凡解决,对路由进行拦挡判断,并再次进行音讯告诉。
  3. 要分外留神在原型上挂载一些全局变量或全局函数的行为,容易被后者笼罩。