一个XX系统软件,技术栈是React

lxf2023-12-18 16:00:02

序言

我们团队正在进行一个XX系统软件,技术栈是React,由于该系统软件日渐巨大,开发及维护费用增加,且每一次必须将项目整体一起装包,耗时费力。经考虑到最后决定把它拆分成多个项目,由两者组成一个完整系统软件,微前端架构是很好的挑选。

微前端有以下几个优势:

  1. 单项目维护:比如将产品控制模块单拉出产生一个项目,它需要由一个工作组独立维护保养,完成优良耦合
  2. 复杂性减少:不用在所有集成化的巨大系统中开发设计,防止极大代码量,开发设计时编译程序速度更快,提升研发效率
  3. 可扩展性:独立新项目出现错误也不会影响系统运行
  4. 技术栈灵便:vue、react、angular 等包含别的前面技术栈都可以用,会 vue 的无需再学 react

对于我们来说最大的优势是单项目维护

展现

UI示例图

一个XX系统软件,技术栈是React

我们将要全部微前端分两一部分:

  1. 主新项目(Main):红色框一部分,做为项目整体的父级,承担展现菜单栏控制模块、头顶部控制模块
  2. 单项工程(Sub-apps):蓝色框一部分,单项工程作用是实际的项目展现

动态图展现

一个XX系统软件,技术栈是React

仔细看搜索框转变,其中包括 /app1/xxx/app2/xxx,乍一看这是一个工程中2个界面的转换,实际是来源于2个单独项目,app1 和 app2 来自各式各样的 git 库房。

微前端框架

一个XX系统软件,技术栈是React

整个过程大概为:用户访问 index.html, 这时运作控制模块加载器Js,加载器会依据整个系统环境变量(project.config) 去申请注册每个新项目,系统将先载入主新项目(Main),然后就会依据路由器作为前缀动态加载相对应的单项工程

现在这个架构设计也借鉴了网上有很多好文章,在其中关键文章内容可参照 alili.tech/archive/110…

有关 project.config

大约如下所示

[
 {
    isBase: false,
    name: 'app1',
    version: '1.0.0',
    //通过此路由器作为前缀配对载入现阶段通道文档
    hashPrefix: '/app1',
    //通道文档
    entry: 'http://www.xxxx.com/app1/dist/singleSpaEntry.js',
    //顶尖Store
    store: 'http://www.xxxx.com/main/dist/store.js'
  }
  ......
]

这儿 project.config 用于制造自然环境,我们可以把装包后文件传送到 OSS(或CDN),再将现阶段装包的项目配置同步到服务器端,服务器端会把每个项目配置集成到 project.config, 客户在浏览 index.html 的时候会获得 project.config,随后 single-spa 会根据这个配备进行申请并依据路由器载入相匹配新项目。

一个XX系统软件,技术栈是React

关键技术

single-spa

大家找了一个些完成微前端的库房,比照最后决定应用single-spa。

大家技术栈是 react,在单项工程入口中需要用到 single-spa-react 来建立,重要编码如下所示:

import singleSpaReact from 'single-spa-react';

const reactLifecycles = singleSpaReact({
  React,
  ReactDOM,
  rootComponent: Root,
  domElementGetter
});

export function bootstrap(props) {
  return reactLifecycles.bootstrap(props);
}

export function mount(props) {
  return reactLifecycles.mount(props);
}

export function unmount(props) {
  return reactLifecycles.unmount(props);
}

假如你应用 vue,可以用 single-spa-vue

随后在设备通道文档中,把自己的新项目申请注册进去:

import * as singleSpa from 'single-spa';

singleSpa.registerApplication(
    'app1',
    () => SystemJS.import('app1-entry.js'),
    () => location.hash.startsWith(`#/app1`),
    props
  );

实际可参照 single-spa 官方网站 single-spa.js.org 这里有很多事例

Webpack 与 SystemJs

使用 lerna 统一管理每个项目的架包,全部架包版本统一,那样十分方便维护保养。

应用 webpack 的 dll 作用,将每个项目的公共架包抽身,例如 react、react-dom、react-router、mobx等

为了更好地新项目动态加载,大家也参照在网上大佬们的念头,采用了systemjs,大家用的都是 0.20.19 版本号。相互配合 systemjs ,在 Webpack 过程中需要改一下 libraryTarget:

output: {
    publicPath: 'http://www.xxxxx.com/',
    filename: '[name].js',
    chunkFilename: '[name].[chunkhash:8].js',
    path: path.resolve(__dirname, 'release'),
    libraryTarget: 'amd', //留意 这儿应用 amd 规范和标准
    library: 'app1'
  },

大家未使用 umd 标准,采用的是 amd 标准,也未使用 systemjs 中的 Import Maps 作用,而是通过根据 project.config 来动态加载控制模块通道。

app中间通讯

关于那个也看了一些大佬们的计划方案,无非就是每一个新项目里有一个 store,在申请通道时把所有 store 放入序列,必须升级 store 中的的状态下,启用 dispatch 把所有 store 同歩。

我的方法与传统单页应用一样,一个操作系统应当只有一个顶尖 Store,因为顶尖 Store 里存的一般是整个系统公共情况 例如菜单栏、客户信息等,我把它放到 Main新项目里,但装包时这一Store是独立抽身的:

entry: {
    singleSpaEntry: './src/singleSpaEntry.js',
    store: './src/store' //独立一个通道
  },

在创建账户,把这个 Store 传到各个项目中:

//顶尖Store
const mainStore = await SystemJS.import(storeURL);

singleSpa.registerApplication(
    'app1',
    () => SystemJS.import('http://www.x.com/app1/entry.js'),
    hashPrefix('/app1'),
    { mainStore }
);
singleSpa.registerApplication(
    'app2',
    () => SystemJS.import('http://www.x.com/app2/entry.js'),
    hashPrefix('/app1'),
    { mainStore }
);

那样就能达到只管理方法这一个 Store 就能,十分方便。 留意:我采用的是 Mobx 做为状态管理

前面布署

大家部署的方法比较简单,自己写了一个 webpack 软件用以把装包后 dist 传入 OSS 再将项目配置发给服务器端,服务器端(NodeJs)依据传到的项目配置机构成 project.config,随后客户在浏览 index.html 的时候会获得 project.config,这时 single-spa 依据配备申请注册每个项目,再根据路由器来获取相对应的新项目通道文档js文件。

把头工程项目的初始化 DOM 放到 Main 新项目里

我们的需求是 Main 做为项目整体的 Layout,在其中单项工程的初始化 Dom 还在 Main新项目里,这便务必直到 Main 新项目彻底3D渲染结束后,才可以初始化单项工程。我借鉴了在网上有一些微前端的完成,把 domElementGetter 方式参考了来:

function domElementGetter() {
  let el = document.getElementById('sub-module-wrap');
  if (!el) {
    el = document.createElement('div');
    el.id = 'sub-module-wrap';
  }
  let timer = null;
  timer = setInterval(() => {
    if (document.querySelector('#content-wrap')) {
      document.querySelector('#content-wrap').appendChild(el);
      clearInterval(timer);
    }
  }, 100);

  return el;
}

demo

demo详细地址:github.com/Vibing/micr… 该demo会提供一个微前端的依据,具体开发与布署主要看诸位企业情况而定

结语

这就是我们第一次玩微前端,肯定有很多地区有缺憾,敬请各位大佬多多指教

本站是一个以CSS、JavaScript、Vue、HTML为中心的前端开发技术网址。我们的使命是为众多前端工程师者提供全方位、全方位、好用的前端工程师专业知识和技术服务。 在网站上,大家可以学到最新前端开发技术,掌握前端工程师最新发布的趋势和良好实践。大家提供大量实例教程和实例,让大家可以快速上手前端工程师的关键技术和程序。 本站还提供了一系列好用的工具软件,帮助你更高效地开展前端工程师工作中。公司提供的一种手段和软件都要经过精心策划和改进,能够帮助你节约时间精力,提高研发效率。 此外,本站还拥有一个有活力的小区,你可以在社区里与其它前端工程师者沟通交流技术性、交流经验、处理问题。我们坚信,街道的能量能够帮助你能够更好地进步与成长。 在网站上,大家可以寻找你需要的一切前端工程师网络资源,使您成为一名更加出色的网页开发者。欢迎你添加我们的大家庭,一起探索前端工程师的无限潜能!