背景

公司一个开发迭代两年的我的项目因前期须要扩大更多的业务板块须要进行拆分,一是要满足前期一直新增板块业务不对现有业务产生影响,再者就是目前存在单我的项目业务量过大,开发保护难度极大,于是不得不思考将现有业务板块进行微服务化拆分,以满足前期的需要。

此文是对题目采纳技术栈实现过程的技术分享,同时也是对该技术计划的摸索和实际,感兴趣的同学请留步!


lerna

一个用于治理带有多个包的 JavaScript 我的项目的工具。

次要用于微服务生产阶段公共依赖的治理。能够解决的问题:开发阶段多服务同时启动,子项目不必放在同一个 git 我的项目中,企业中局部 npm 私服包能够更便捷的更新到各个子项目等,将局部公共依赖装置在lerna根目录能够节俭一部分存储空间。

疾速上手

PS:这里须要先新建一个空的我的项目目录,以下示例均为umi-qiankun-explore
倡议将lerna装置在全局,当然也能够装置在我的项目部分

npm i lerna -g

初始化

lerna init --independent //装置在全局
npx lerna init --independent //装置在部分

次要办法,既能够给某个我的项目独自装置依赖,也能够给所有子项目装置公共依赖,具体反对的参数见lerna bootstrap

lerna bootstrap <--options>

初始化后的 lerna 我的项目目录如下

umi-qiankun-explore/|--packages/ //这里是寄存微服务各模块等目录,前面已更改为project,对应须要调整的配置见下方lerna.json▼|--package.json|--lerna.json

umi-qiankun-explore/lerna.json

{  "packages": ["project/*"],  "workspaces": ["project/*"],  "version": "0.0.0"}

umi-qiankun-explore/package.json

{  "name": "root",  "private": true,  "scripts": {    "clone:all": "bash ./cli/clone-all.sh", // 这里用来能够依据设施写一个clone所有子项目的脚本    "boots": "lerna bootstrap --hoist", // 装置子项目所有公共的依赖    "start": "lerna run --parallel  start " //启动所有子项目  },  "devDependencies": {}}

这里批改目录次要是在命令行下切换目录pTab会把 package.json 也带进去,就不太不便

umi

应用umi创立子项目,在project目录下创立依据微服务理论状况划分的我的项目模块,以下将采纳同一种形式别离创立app-container,app-device,app-common三个我的项目。
其中app-container作为主我的项目,用于微服务的容器,个别只具备页面布局、登录受权、根底数据散发等根底业务性能。
app-common次要作为我的项目公共业务模块,个别具备账户信息管理、利用设置等与具体业务无关或无强关联的根底性能。
其余子项目依据我的项目理论状况进行划分即可。

新建完三个我的项目目录后,通过官网工具创立我的项目

yarn create @umijs/umi-app / npx @umijs/create-umi-app

⚠️ 留神:创立完我的项目后,须要做两件最根底的事件,很重要

  • 将各我的项目 package.json 中的 name 属性改为我的项目对应的名称
  • 各我的项目原start启动命令须要指定一下端口号,形如以下

此示例我的项目 container 对应 8000,common 对应 8002,device 对应 8001

 "start": "PORT=8001 umi dev set"

自此lerna就派上用场了,在 umi-qiankun-explore/package.json 内新增各个 umi 我的项目具备的公共依赖

"dependencies": {    "@ant-design/pro-layout": "^6.5.0",    "@umijs/plugin-qiankun": "^2.27.0",    "react": "17.x",    "react-dom": "17.x",    "redux-thunk": "^2.3.0",    "umi": "^3.5.15"  },  "devDependencies": {    "@types/react": "^17.0.0",    "@types/react-dom": "^17.0.0",    "@umijs/preset-react": "1.x",    "@umijs/test": "^3.5.15",    "lint-staged": "^10.0.7",    "prettier": "^2.2.0",    "typescript": "^4.1.2",    "yorkie": "^2.0.0"  }

此时应用npm run boots即可实现各子项目公共依赖的装置,装置完我的项目依赖后,咱们便能够应用npm start将各个我的项目同时启动起来,不过此时我的项目还没有起来。实现上述步骤后能够取得的我的项目目录构造如下:

目录构造(要害局部)

umi-qiankun-explore├── project│ ├── app-common│ │ ├── mock│ │ ├── src│ │ ├── .umirc.ts│ │ ├── package.json│ │ └── ...│ ├── app-container│ │ ├── config│ │ ├── mock│ │ ├── src│ │ ├── README.md│ │ ├── package-lock.json│ │ ├── package.json│ │ ├── tsconfig.json│ │ ├── typings.d.ts│ │ └── yarn.lock│ ├── app-device│ │ ├── mock│ │ ├── src│ │ ├── .umirc.ts│ │ ├── package.json│ │ └── ...├── lerna-umi-qiankun 搭建微服务过程.md├── lerna.json├── package-lock.json└── package.json

plugin-qiankun

采纳 umi 官网举荐形式,将 qiankun 引入各我的项目

yarn add @umijs/plugin-qiankun -D

主我的项目 app-container

这里先采纳路由绑定的形式引入子项目,MicroApp组件形式见应用 <MicroApp /> 组件的形式

.umirc.ts中新增如下配置

export default defineConfig({  qiankun: {    master: {      // 注册子利用信息      apps: [        {          name: 'app-common', // 公共服务          entry: '//localhost:8002',          // 子利用通过钩子函数的参数props能够拿到这里传入的值          props: {            token: 'XXXXXXX',          },        },        {          name: 'app-device', // 设施服务          entry: '//localhost:8001',          // 子利用通过钩子函数的参数props能够拿到这里传入的值          props: {            token: 'XXXXXXX',          },        },      ],      jsSandbox: true, // 是否启用 js 沙箱,默认为 false      prefetch: true, // 是否启用 prefetch 个性,默认为 true    },  },})

假如咱们页面布局次要依附主我的项目的前提下,引入子项目路由的形式如下

export default defineConfig({  routes: [    {      exact: false,      path: '/',      component: '@/layouts/index',      routes: [        {          path: '/home',          component: '@/pages/home/index',          meta: { title: '首页' },        },        // 公共服务模块        {          name: 'app-common', //⚠️留神这里须要与下面qiankun配置的name绝对应          path: '/common',          microApp: 'app-common',        },        // 设施服务模块        {          name: 'app-device',          path: '/device',          microApp: 'app-device',        },      ],    },  ],})

子项目 app-common

.umirc.ts中新增用于反对 qiankun 的配置

import { defineConfig } from 'umi'export default defineConfig({  nodeModulesTransform: {    type: 'none',  },  routes: [{ path: '/', component: '@/pages/index' }],  // 新增配置  qiankun: {    slave: {},  },})

还须要将子项目生命周期导出,umi@3.5版本初始化曾经没有app.tsx文件,所以咱们须要手动新建一个,

/src/app.tsx

export const qiankun = {  // 利用加载之前  async bootstrap(props: any) {    console.log('子利用[app-common] bootstrap', props)  },  // 利用 render 之前触发  async mount(props: any) {    console.log('子利用[app-common] mount', props)  },  // 利用卸载之后触发  async unmount(props: any) {    console.log('子利用[app-common] unmount', props)  },}

app-deviceapp-common办法雷同,如此便初步实现微服务项目的根底构造了。
以上只是以后技术栈下微服务的第一步,至于 qiankun 的实际利用局部还有很多存在,例如款式隔离、数据共享、数据上移和下移等 qiankun 目前解决的不算全面的问题,还是得依据我的项目的理论状况进行问题排除和降级革新。

至此已实现整体技术栈的初步实际,当然对于lerna,umi.jsqiankun还有更多的高阶业务场景没有波及到,次要还是每个我的项目本身的特点对于这些技术利用的切入点不同,因而此文只做疏导后续更简单的场景还是须要咱们去具体问题具体解决

留图示意依照上述所有步骤能够实现微前端的实现,哈哈哈!

感兴趣的同学能够移步 github 去拉一下我的我的项目 demo,前面会欠缺更多理论场景的简单问题。
github

文章不是 cv 来的哈,如果对你有帮忙请不要悭吝下方点个赞 ,在此谢过!

参考文章

  • lerna 中文文档
  • @umi/plugin-qiankun
  • umi