乐趣区

关于前端:微前端SingleSpa实践小结

背景:

此前接手了一个老我的项目(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-os SingleSpa
子利用技术栈 React、Vue、Angular React、Vue、Angular
主利用技术栈 React、Angular 不限
子利用资源配置模式 manifest.json single-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. 要分外留神在原型上挂载一些全局变量或全局函数的行为,容易被后者笼罩。
退出移动版