项目实战-UmiJS开发(附带qiankun)

前言

Coder 是怎么样提高自己的实力?一件事情做坚持一万遍,唯手熟尔

不知道各位有没有体会,总感觉之前的代码写的很 low 逼,想抽点空来折腾折腾自己还是很有乐趣的。重构还是很有乐趣的。手工狗头镇楼!

搭建基础框架

一般来说,中小型团队的中台项目都是前端自己主导样式,而样式、布局、路由、权限等等一系列的通用性很强的基础框架,自研比较花时间,投入的回报率不高,最好的方法就是在比较成熟的方案上进行一定的个性化定制,性价比会很高,所以我们也采用了 UmiJS + ANT DESIGN PRO 的架构来进行项目升级(之前的老项目基于 Umi2.0 与 ANT DESIGN PRO 3.0 开发)

UmiJS 是什么?

UmiJS,中文可发音为乌米,是可扩展的企业级前端应用框架。Umi 以路由为基础的,同时支持配置式路由和约定式路由,保证路由的功能完备,并以此进行功能扩展。然后配以生命周期完善的插件体系,覆盖从源码到构建产物的每个生命周期,支持各种功能扩展和业务需求。

ANT DESIGN PRO 是什么?

Ant Design Pro 是一个企业级中后台前端/设计解决方案,基于 Ant Design 的设计规范和基础组件的基础上,提炼出典型模板/业务组件/配套设计资源,进一步提升企业级中后台产品设计研发过程中的『用户』和『设计者』的体验。

快速搭建基础框架

我们直接采用 UmiJS 3.0 + Ant Design Pro 4.0 来构建一个基础的模板。

yarn create umi

 Select the boilerplate type (Use arrow keys)
❯ ant-design-pro  - Create project with an layout-only ant-design-pro boilerplate, use together with umi block.
  app             - Create project with a simple boilerplate, support typescript.
  block           - Create a umi block.
  library         - Create a library with umi.
  plugin          - Create a umi plugin.

Ant Design Pro 脚手架将会自动安装,安装完依赖之后,一个基础框架就完成了,此章终结

自定义模块

删除全球化

一般来说,Ant Design Pro 的国际化在大部分团队意义不大,所以可以先删除,后期有需求再进行添加。

先删除 @umijs/plugin-locale 插件,其次删除项目中所有 formatMessage 相关的动态代码,移除 i18n 的相关文件,修改成正常文案即可。

如果你是按照上述的模板下来,再删除 @umijs/plugin-locale 的配置之后,项目就会报错,按照报错的内容修正就行。

添加开发环境

常规开发环境都需要有 3 套,分别是 dev(开发环境),test(测试环境),prod(生产环境)。如果资源富余的话,可以添加 pre(预发环境)。

Umi 通过环境变量 UMI_ENV 可以区分不同环境来指定配置。

// .umirc.js 或者 config/config.js
export default { a: 1, b: 2 };
// .umirc.local.js 或者 config/config.local.js 开发环境
export default { c: 'local' };
// .umirc.test.js 或者 config/config.test.js
export default { b: 'cloud', c: 'cloud' };

在配置多环境文件的时候,切记 config.js 一定要存在,不然会失效

同时修改命令启动命令

"start:dev": "cross-env REACT_APP_ENV=dev MOCK=none umi dev",
"build:test": "cross-env UMI_ENV=test umi build",
"build:prod": "cross-env UMI_ENV=prod umi build",

这样即可在不同的环境,运行不同的命令,生成对应的版本。举个栗子,测试环境与线上环境的接口不一致,或者有些功能是需要在测试环境使用。

毕竟 UmiJS + Ant Design Pro 双双结合之后的基础框架非常成熟,简单加一些功能即可进行业务开发,如果需要定制的话,可以自行增减功能。

qiankun 微前端引入

之前掘金有专门的微前端专题,也有很多掘友发过相关的文章与 demo。这里就结合改造之后的项目来介绍下使用。

在使用微前端之前建议看看之前的博文-传送地址: 你为什么需要微前端。确定你团队确实存在这些情况之后,再根据需要业务的定制与之匹配开发模板。

首先,我们需要将前面的基础模板,改造成 2 套,分别作为主子项目模板。

主应用配置

// 注册子应用
export default {
  qiankun: {
    master: {
      apps: [
        {
          name: 'app1', // 唯一 id
          entry: '//localhost:7001', // html entry
        },
        {
          name: 'app2', // 唯一 id
          entry: '//localhost:7002', // html entry
        },
      ],
    },
  },
};
// 装载子应用
export default {
    routes: [
    {
      path: '/',
      component: '../layouts/index.js',
      routes: [
        {
          path: '/app1',
          component: './app1/index.js',
          routes: [
            {
              path: '/app1/user',
              component: './app1/user/index.js',
            },
          ],
        },
        {
          path: '/',
          component: './index.js',
        },
      ],
    },
  ],
}
image

把 Layout 的模板删删减减,改造一下就如上图的界面。大体就是将导航菜单改成 Nav 模式,将下面的内容模块全部让出给子应用,这样可以将主体发挥空间全部交给各个子应用来管理。

子应用配置

export default {
  qiankun: {
    slave: {}
  }
}

子应用的配置就相对简单,只要加入上述代码注册插件即可。

子应用的模板,将 Header 模块全部删除,保留侧边路由模块,所以子应用单独开发的时候,可以拥有自己最大的自定义性,可以独立开发。

image

子应用在加载到主应用的时候,则如下图所示:

image

主应用加载了子应用之后,后续的界面渲染可以全部交给子应用自己管理。

配置开发、生产环境

既然是微前端,不可能同时启动主子两个系统,那样不符合微前端的概念,所以引入 localhost 肯定是不科学的,但是本地引入项目的时候,有的时候存在跨域问题。


export default {
  qiankun: {
    master: {
      apps: [
        {
          name: 'devops', // 唯一 id
          entry: '/qiankun/devops/index.html', // html entry
        },
      ],
    },
  },
}
proxy: {
  dev: {
    '/qiankun/': {
      target: 'https://www.cookieboty.com',
      changeOrigin: true,
      pathRewrite: { '^': '' },
    },
  },
}

将所有的子应用都发布在 qiankun 网关下面,再加上子应用自己的标识即可通过代理的方式,主应用在本地开发的时候可以正常加载子应用并访问。

至于其他的细节问题,可以参考官网 qiankun 插件去制定符合自己业务的模板,这里就不多阐述,有不清楚的地方欢迎留言讨论。

路由权限改造

UmiJS 自带的路由权限校验是会将不符合用户的权限的页面引导到空白或者其他页面,我们这里稍微改造一下,引入动态路由与菜单,如果用户没有该权限的时候将不会暴露菜单与路由出去。

// app.ts
function Routes(routes, userinfo) {
  let routesObject = {};
  routes.forEach(route => {
    if (route.childs && route.childs.length > 0) {
      routesObject = Object.assign(routesObject, Routes(route.childs, userinfo));
    }
  });
  return routesObject;
}

export async function render(oldRender) {
    window.oldRender();
}

const getRoutes = (routes, newRoutesList) => {
  const routesList = [];
  routes.forEach(route => {
    if (route.routes && route.routes.length > 0) {
      route.routes = getRoutes(route.routes, newRoutesList);
    }
    if (newRoutesList[route.path]) {
      routesList.push(route);
    }
  });
  return routesList;
};

export async function patchRoutes(routes) {
  const userinfoData = await getUserInfo()
  const userinfo = userinfoData.data
  const {data} = await getTree()
  newRoutes = Routes(data.childs, userinfo);
  if (newRoutes) {
    routes[0].routes = getRoutes(routes[0].routes, newRoutes);
    window.g_routes = routes;
  }
}

简单来说就是,动态从后台获取路由然后匹配本身的路由进行一次过滤,筛选出匹配的路由在 patchRoutes 重新修改 g_routes,并非真正意义上的动态路由。也算是一种将就的解决方案吧。

写在最后

同学们看到示例图,有没有联想到 DevOps 系列。

image

没错,我胡汉三又回来了,继续推进,敬请期待

全系列博文目录

后端模块

  1. DevOps - Gitlab Api使用(已完成,点击跳转)
  2. DevOps - 搭建 DevOps 基础平台 基础平台搭建上篇 | 基础平台搭建中篇 | 基础平台搭建下篇
  3. DevOps - Gitlab CI 流水线构建
  4. DevOps - Jenkins 流水线构建
  5. DevOps - Docker 使用
  6. DevOps - 发布任务流程设计
  7. DevOps - 代码审查卡点
  8. DevOps - Node 服务质量监控

前端模块

  1. DevOps - H5 基础脚手架
  2. DevOps - React 项目开发
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,802评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,109评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,683评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,458评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,452评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,505评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,901评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,550评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,763评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,556评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,629评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,330评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,898评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,897评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,140评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,807评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,339评论 2 342

推荐阅读更多精彩内容