微前端(一)微前端是什么?为什么要用微前端?

微前端是什么?
参考网站:
https://micro-frontends.org
https://microfrontends.com

微前端就是与多个可以独立发布功能的团队一起构建现代化web应用程序的技术、策略和方法,将大而可怕的事物分割成更小、更易于管理的部分,然后明确它们之间的依赖关系。我们的技术选择,我们的代码库,我们的团队,以及我们的发布过程都应该能够相互独立地操作和进化,而不需要过度的协调。微前端架构是一种类似于微服务的架构,它将微服务的理念应用于浏览器端,即将 Web 应用由单一的单体应用转变为多个小型前端应用聚合为一的应用。

为什么要用微前端?
拆分巨型应用,使应用方便迭代更新
兼容历史应用,实现增量开发

特点:

独立部署
增量迁移
团队自治
松耦合代码
优点:

通过路由进行跨应用程序通信
解决了大型项目如何迭代的问题
解决了多团队技术栈不同的问题,实现react和Vue等框架整合
缺点:

有效载荷大小
环境差异配置难
业务和治理复杂
微前端结构方案
自由组织模式
没有特别形势,类似iframe嵌套、npm包自由发挥
基座模型
类似微服务的注册中心模式,有个基座,其他应用都往里加
去中心模式
webpack5模块联邦,多个应用可以互相嵌套,可以深入到组件导入导出
主流微前端框架
国内使用基座模式偏多
Single-Spa:最早的微前端框架,兼容多种前端技术栈。
Qiankun:基于Single-Spa,阿里系开源微前端框架。

微前端-乾坤

本文将按照下面的顺序逐一讲解:

1)什么是微前端以及为什么使用微前端

2)乾坤框架介绍

3)基于乾坤框架实例

4)开发过程中遇到的问题

一、什么是微前端

微前端的核心思想就是将按照不同功能或不同维度拆分的独立子应用,通过主应用来加载这些子应用,达到子项目可以独立开发、独立部署、不受技术栈影响效果。

二、乾坤框架介绍

下面的地址是乾坤文档地址,详细介绍了微前端的概念、乾坤的核心设计思想
介绍
https://qiankun.umijs.org/zh/guide

三、乾坤框架实例

说明:例子基于三个独立项目,项目都采用了vue框架

1、创建项目

由于是基于项目改造,所以项目已经创建好了,这里就不赘述创建项目的过程了

2、主应用配置

主应用不限技术栈,只需要提供一个容器 DOM,然后注册微应用并 start 即可

1)主应用安装乾坤包

npm i qiankun -S
2)修改App.vue文件,添加微应用挂载节点

3)注册微应用,并启动

首先,配置一些全局变量,用于区分开发环境、测试环境、生产环境的微应用的入口

VUE_APP_UPKEEP_STATIC_HOST是微应用A的域名;VUE_APP_SUB_APP_UPKEEP_PATH是微应用A的路径;

VUE_APP_BRAND_STATIC_HOST是微应用B的域名;VUE_APP_SUB_APP_BRAND_PATH是微应用B的路径。

这里之所以将资源加载的路径写的这么具体,是因为我们的项目都是部署在同一台机器上,只不过是访问路径有些区别,为了防止微应用资源加载错误,所以才写的那么具体。

开发环境配置的一些变量:

测试环境配置的一些变量:

生产环境配置的一些变量:

由于生产环境会区分灰度环境,所以通过变量process.env.IS_GRAY来区分路径。

然后,配置微应用的注册信息、将微应用的注册和启动封装成模块

将微应用的注册信息封装成模块,micros/subApps.js

引进微应用注册信息,将微应用的注册和启动封装成模块,micros/index.js

接着,修改入口文件index.js

注意:一定要先挂载主应用之后,才能注册和启动微应用,否则不会触发微应用的加载,即先执行了mountApp之后,在执行startMicroApp

ThirdMicroPush和ThirdMicroReplace方法用于微应用间跳转,实质是调用了history.pushState和history.replaceState方法,改变浏览器的地址,如果改变后的地址匹配上之前的激活规则activeRule的值,则激活相应的微应用,示例如下:

ThirdMicroReplace('/umc-mall/upkeep/index.html#/home?processNo=tuhu')
4)在webpack.dev.js的devServer属性添加跨域的配置

由于主应用和微应用间的端口号不一样,会存在跨域问题,所以需要配置可跨域信息

至此,主应用的配置已经修改完成,下面说下微应用的改造,微应用不需要额外安装任何其他依赖即可接入 qiankun 主应用。

3、微应用A改造

微应用A的入口文件导出相应的生命周期钩子

微应用需要在自己的入口 js (通常就是你配置的 webpack 的 entry js,这里是根目录下的src/modules/index.js) 导出 bootstrap、mount、unmount 三个生命周期钩子,以供主应用在适当的时机调用,同时兼容微应用独立运行

修改的代码在下面两张图内:

配置微应用A的打包信息

修改webpack.conf.js文件的output配置

如果项目中有用dll 打包输出一些资源,则需要对dll的配置信息进行修改,并且重新打包,如果没有的话,至此子应用的配置就已经修改完成了。

由于我们的项目有用到dll打包输出的资源,所以还需要修改webpack.dll.js

在output对象上添加属性libraryTarget: window

然后需要重新打包dll

注意,确保项目中引进的是新打的dll文件,否则会出现一些异常问题

其他的微应用配置同上。至此,主应用和微应用的改造已经完成,不出问题的话,项目就可以跑起来了

四、开发过程遇到的问题

1、Cannot read property 'range' of null

在src/modules/views/home/index.vue文件中的methods对象下有如下方法,将该方法注释掉,控制台就不报错了

按照webpack官方文档描述,是支持动态路径引进相应文件的,但是这里却报错了,而别的项目也有使用动态引进文件,却没有报错。看下控制台的报错信息,是从eslint-loader抛出来的,于是对比了一下关于eslint包的版本,发现正常跑起来项目安装的babel-eslint版本是7.2.3,而报错项目安装的版本是10.0.3。于是将babel-eslint版本改成7.2.3,重启项目就正常了。

原因:安装babel-eslint版本不对,导致解析动态引进文件语法错误

解决方法:安装7.2.3版本的babel-eslint

2、根目录下的模板文件的ejs语法在浏览器下未被正常解析

效果如下:

原因:html-loader和html-webpack-plugin有冲突。如果用html-loader处理了.html类型文件,会把html模板编译成js模块的字符串,html-webpack-plugin解析时候发现文件已经被编译了,就会直接跳过对其编译

图1:

图2:

解决方法:将图2的配置去掉

3、Utils is not defined

场景:微应用项目都是用统一的cli命令初始化项目的,统一会在window对象下挂载Utils属性。在本地开发过程能正常访问到Utils对象,但是在线上环境,就抛Utils is not defined。

解决思路:之前微应用项目没有配置微应用信息前,作为独立H5项目,线上和本地都可以访问到window.Utils对象。在配置微应用之后,本地可以访问到Utils对象,但是线上访问不到。应该是和修改了webpack配置有关。然后对比了一下修改webpack前后的配置信息,唯一的区别就是:重新打包了dll后,本地开发时候引的是本地dll文件,即重新打的dll文件,而线上引的是cdn地址dll文件,问题就出在这里。

dll文件引进如下:

开发环境的dll引进放在inc-footer-dev.html中

线上环境的dll引进放在inc-footer.html中

根目录下的模板文件index.html

原因:修改了dll打包配置,线上用的不是最新打包出来的dll文件

因为我们修改了dll的配置文件的output内容,即添加了libraryTarget: 'window',本地引用的是重新打包后的dll文件,打包出来的全局变量是挂载在window上,肯定是没有问题,而线上引用的是修改dll配置文件之前打包出来的文件,没有配置libraryTarget,默认是var声明的变量

解决方法:线上环境引用的dll文件改成项目打包出来的dll文件,修改inc-footer.html:

4、微应用A的window.Utils被微应用B的window.Utils覆盖

场景:一起有三个项目:主应用、微应用A、微应用B,微应用A和微应用B都是用同一个脚手架搭的项目,会默认在全局window上添加变量Utils。

问题:现在从链接上直接跳到主应用,在主应用上调接口判断要激活哪个微应用。假如主应用调接口后判断要激活微应用A,这时候Utils对象是微应用A设置的;当在微应用A的某个页面,点击某个按钮时候会激活微应用B,跳转到微应用B的某个页面,这时候Utils对象是微应用B设置的;当从B在回到A上时,Utils对象还是B设置的值。

解决方法:将微应用A和B的Utils对象重新命名,避免重名导致覆盖想象

注意:当调用start方法时,设置sandbox:false,即当关闭沙箱功能时候,检查在主应用和微应用在window对象上挂载的属性是否有重名,避免重名想象

5、主应用线上编译部署时候,抛错:BigInt is not defined

错误信息如下:webpack-cli/bin/cli.js文件抛出来的错误,然后想到项目用的是webpack5的版本,会不会是线上编译的webpack版本不对,然后将线上编译的webpack 的版本打印出来,版本是5.55.0,发现没错。

接着想到webpack5版本对node版本有要求,Webpack 5 对 Node.js 的版本要求至少是 10.13.0 (LTS)会不会是线上编译的node版本不符合要求。接着打印出线上node版本,发现node版本是8.3.0。问题就出在这了。

解决方法:在编译脚本里面,指定node的版本:NODE_VERSION=10.15.3

6、接口请求时候,网关报错

在我们的项目里面,会加载一个网关包,用于对请求数据的加密。在线上访问主应用时,主应用调接口是正常的,但是主应用激活微应用后,微应用中调接口,报如下错误:

问题:请求头中的字段:X-PA-SIGN-V和X-PA-SIGN-ALG的值不对

主应用会去初始化网关信息,微应用在乾坤容器环境内的话不会重新初始化网关信息,但是主应用调接口时候请求头的X-PA-SIGN=v3和X-PA-SIGN-ALG=1,接口请求正常,微应用接口却报值不对的问题。

主应用代码如下:

微应用代码如下:

主应用没有报网关问题,微应用却报了,两者关于网关信息唯一不同的地方就是引进的包名不一致,于是将微应用的网关包名改成和主应用一致,接口就正常了

问题原因:两个项目的网关包不一样

解决方法:项目的网关包改成一致就可以了

7、运行主项目时候,报错:

index.1b2c201fea272d41a704.js:39190 Uncaught QiankunError: application 'umcmallupkeep' died in status NOT_MOUNTED: [qiankun]: Target container with #childContainer not existed after umcmallupkeep mounted!

大致意思是,用于挂载微项目的容器节点childContainer不存在。

先来看下子项目的注册信息,指定的容器节点名是否为childContainer:下图中的container:'#childContainer',值没有配置错误

接着看下主应用的挂载组件App.vue内容:

微应用挂载组件App.vue内容:

法相主应用和微应用的挂载节点的id都是app, 在看下报错图片渲染出来的DOM只有微应用的DOM结构,主应用的DOM节点都没有发现。怀疑是挂载DOM节点的id命名冲突导致的。

将主应用的挂载id由app改成main,项目就不报错了。

正常显示效果如下:

报错原因:主应用和微应用的DOM节点id命名冲突了

解决方法:修改成不一样的就可以了

8、控制台报跨域问题 ,微应用资源获取失败

Access to fetch at 'https://xxx.com.cn/vender/1.0.0/encrypt.min.js' from origin 'http://localhost:5910' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled. Uncaught TypeError: application 'umcmallupkeep' died in status LOADING_SOURCE_CODE: Failed to fetch

报died in status LOADING_SOURCE_CODE: Failed to fetch错误,一般是微应用还没有改造完成导致的。但是我们的项目已经改造完成了,还是报该错误。在看控制台有一个跨域的错误,会不会是该报错导致的呢?

于是将该文件的引用改成项目中的文件地址,果然就不报错了。

报错原因:当主应用发生跨域报错时,会block调微应用的加载和执行

解决方法:解决掉跨域报错问题

注意:如果测试环境有调生产环境资源,也会报跨域问题,导致微应用加载失败

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

推荐阅读更多精彩内容