umi+qiankun+gitsubmodel 完成项目微前端重构

写在前面

本次例子是简化版的真实项目,从零到一,包括最后的nginx配置都有。并且配上效果图,至于文件目录结构,因为和umi官网命令搭建的一样就不会贴出来了。主应用,子应用全都是用umi进行开发,没有和网上大部分例子一样嵌套了vue等其他框架。全程使用了umi全家桶开发,cv大法,若想了解微前端更多原理之类的,网上很多讲解,这里不涉及,因为本人也是一知半解。只会使用,不会搭建构造。

项目背景

公司有个C端项目,简单概括就是一个基础商城,会售卖给很多个甲方,同时会根据甲方的要求进行特殊化处理。比如每个甲方的登录方式不一样,首页布局不一样等等。项目之前的处理方式是利用git分支功能做管理,一个甲方一个分支。但这样会出现不好维护的情况,比如共有的代码出现了一个问题,我需要修改其他分支并且重新打包,这样非常不友好。并且随着业务的越来越庞大,功能模块越来越多,里面好几个业务都可以当作是一个项目来进行开发了。这时候微前端这几个字就走进了我的眼球,并且决定对项目进行重构。

开始工作

经过搜索,我把目光锁定了qiankun,并且使用umi开发,别问,问就是底层原理不会,而umi刚好有qiankun一条龙服务。具体参考文档。跟着文档,一步步生成了两个项目,main和home,main就是主应用,相当于一个容器,用于登录和通用的基础应用。而home顾名思义就是首页,相当于一个子应用。如下图:

X89RV}E9%(M2FCR}E3VJRJQ.png
`KZ_OQM)EMMQ_L7$63EOT.png

然后根据文档所写,安装qiankun 两个应用都要:

yarn add  @umijs/plugin-qiankun
复制代码

main/.umirc.ts 下的 defineConfig 增加

 // 注册主应用
  qiankun: {
    master: {},
  },
复制代码

home/.umirc.ts 下的defineConfig增加

 // 注册子应用
  qiankun: {
    slave: {},
  },
复制代码

main/src/app.ts的配置加上:

export const qiankun = () => {
  return {
    apps: [
      {
        name: 'home', // 唯一 id 
        entry: '//xxx.xxx.xx.xxx:8000', // home的运行地址  
      },
      // 若有多个子应用往下增加
    ],
    lifeCycles: {
      afterMount: (props: any) => {
        console.log('qiankun---', props)
      },
    },
  }
}
复制代码

经过这一波操作,再次重启项目发现竟然ok,如下截图:

){6H4$GD}@%`[(A]}D$$BK7.png

看到这我心里只有两个字,芜湖~但是!但是!但是!到这里还没完,因为真正用于开发上线还有几个问题:

  1. 如何隔离
  2. 如何数据传递
  3. 怎么在子应用跳转主应用的路由,比如子应用/home 要跳去/mine 页面(mine属于父级应用路由)
  4. 如何使用公共的组件,方法等
  5. 怎么打包通过正式的url访问

如何隔离

这点其实很好办,官网本身有给出沙盒api,而且再不济就不要用重名咯~(半开玩笑)

如何数据传递

这点也很好解决,官网也有例子,但不得不吐槽一下,使用官网的例子,主应用注册不能写在.umirc.ts,需写在app.ts里(按照我上面的配置就好),不多说,上代码:

// main  app.ts
import { history } from 'umi'
export function useQiankunStateForSlave() {
  const [qiankunGlobalState, setQiankunGlobalState] = useState<any>({
    masterHistory: history,
    test:'hello',
  })
  // 可以挂载到window下  这里需要注意,如果window获取,修改内容时需要及时修改window
  window.masterHistory = history
  window.qiankunGlobalState = qiankunGlobalState
  return {
    qiankunGlobalState,
    setQiankunGlobalState,
  }
}
复制代码

这时候不管主应用还是子应用,都可以使用useModel获取qiankunGlobalState,并且通过setQiankunGlobalState来对数据进行更新,修改等

// 主/子应用的test.tsx  不一定test.tsx哈,哪里想用就去哪里
import { IRouteComponentProps, useModel } from 'umi'
import React, { useEffect } from 'react'

export default function Text() {
  const { setQiankunGlobalState, qiankunGlobalState } = useModel(
    '@@qiankunStateForSlave',
  )
  console.log('qiankunGlobalState', qiankunGlobalState)
  useEffect(() => {
    setTimeout(() => {
      setQiankunGlobalState({
        ...qiankunGlobalState,
        userName: '我是js',
      })
    }, 2000)
  }, [])
  }
复制代码

到这里一部分涨的帅/漂亮的同志就会说,怎么我ts一使用window.xxx就会报红线呀

这时候需要在目录下增加window.d.ts 名字任意哈,.d.ts结尾即可。内容如下:

// window.d.ts
import { History } from 'umi'

declare global {
  interface Window {
    masterHistory: History
    qiankunGlobalState: {
      projectName: string
    }
  }
}
复制代码

如何维护公共的组件,方法

一开始我是想到npm这种方式,但是开发阶段各种改很不方便,于是后面使用了git submodel,创建一个libs的项目进行管理维护。

  1. 首先创建一个libs文件,里面存放各种公用的方法,组件,图片等,并且同步到gitlab上

image.png

2.各应用到src下关联该模块

// main  home src目录
git submodule add 项目git地址/libs.git  src/
// 执行完后会发现目录下多了个.gitmodules,并且src下有libs的文件了,这时候不管是哪个应用,都可以对libs进行开发维护,而libs维护和普通项目git一样。 记得libs切换到分支再进行开发!!!因为一开始默认是某次提交
复制代码

怎么打包,通过正式的url访问

我司是用k8s进行项目打包的,经百度在ci文件加上以下配置:

.gitlab-ci.ymi文件
variables:
  GIT_SUBMODULE_STRATEGY: recursive # 拉取 Submodule 内容
复制代码

正当我兴致勃勃准备开瓶82年的旺仔牛奶庆祝的时候,发现后台打包显示报错,报错信息如下

image.png
通过报错信息大体得知,下载失败,但是为什么失败呢,怎么成功呢,我一脸懵逼,百度查了好久好久都没有答案,自己也折腾了无数遍,换账号,ssh等等都没折腾成功,后来想起,git submodule gitlab介绍中的配置于是我屁颠屁的修改.gitmodules里的url路径为相对路径,果然成功了!

image.png

nginx配置

这里的配置各项目大同小异,具体根据实际来即可。

image.png

配置完后兴致勃勃的打开,效果不错

image.png

最后打包成功后,记得修改以下app.ts里的entry值,目前我是配合cross-env配置了本地开发环境local、测试环境dev、生产环境prod,分别对应不同的url。这样就方便多了。到这里还有两个小问题目前暂未解决,

未解决的小问题

  1. 主应用的路由不能动态生成,每有一个页面,需要手动到.umirc.ts的router里增加,挺不方便的
  2. .gitmodules打包时候需要用相对路径,这样的话本地初始化开发就不太方便了

若有知道的大神希望告诉下解决方案。

总结

到这里可能会有疑问,怎么在子应用跳转主应用的路由 这个问题还没解决呀。对于这个问题一些细心的朋友就发现了,我把 main 的 history 当作参数传进了 qiankunGlobalState ,那么只要在子应用调用 qiankunGlobalState.masterHistory 这个方法就可以跳转main组件的路由,其他子应用路由同理。

总体来说开发还是相对顺滑的,果然是前人栽树后人乘凉。不得不佩服开发这些框架的大佬们真的强。目前我花费最多时间就是公共模块的维护与开发,总体打包,以及nginx配置那一块。但是目前来说,对于移动端项目,网上好像没有微前端例子公布。我这个真实的项目目前也在最后开发阶段,准备进入提测环节,并未真正发布使用,所以微前端合适不合适移动端,暂时未知,发布投入使用后,我会抽空再总结一下。

另外本人是个离开了百度、谷歌就活不下去的cv菜鸡,写的不好不对的地方欢迎指正~

感谢大家!

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享