1.什么是微前端?
1.1 微前端简介
微前端是一种将不同的前端应用聚合到一个整体应用中的方法。 这样的设计思路来源于微服务架构,即将一个大型的后端应用拆分成一系列小型、独立的服务。微前端允许不同的团队独立开发、部署和更新他们各自的应用片段。
1.2 微前端优点
1.技术栈无关
主框架不限制接入应用的技术栈,微应用具备完全自主权
2.独立开发、独立部署
微应用仓库独立,前后端可独立开发,部署完成后主框架自动完成同步更新
3.增量升级
在面对各种复杂场景时,我们通常很难对一个已经存在的系统做全量的技术栈升级或重构,而微前端是一种非常好的实施渐进式重构的手段和策略
4.独立运行时
每个微应用之间状态隔离,运行时状态不共享
2.什么是Monorepo?
2.1 Monorepo简介
Monorepo(Mono Repository)意为单一仓库。它是指在一个项目仓库中管理多个模块/包的策略。
2.2Monorepo优点
1.代码复用。共享代码、组件或工具库变得简单。
2.统一的版本管理。所有的模块和依赖在同一时间点都处于已知且一致的状态。
3.更容易进行大型重构,因为所有相关的改变都在一个提交里。
3.项目背景
3.1 背景
我们目前做的项目从大分类上来说应该属于后台管理系统,最多的就是查询表格页面了。由于是项目制的,目前的前端代码架构就是使用的微前端架构,一个主应用,然后20多个子应用。然后技术栈是统一的,都是React+Redux以及其他的一些库。微前端采用的方案是webpack5的模块联邦的方案。
3.2 问题
1.进行大规模重构改动的时候,测试一次所有的应用都得部署一次,麻烦、耗时、容易出错,每个项目其实都有一套独立的环境,但是使用的时候完全只从主应用进去,那么是不是只需要一套环境就够了
2.新同事进行开发的时候需要把所有的库代码都拉下来,一个一个的拉,效率低(为了解决这个问题,我写了一个脚本,可以将gitlab一个分组下的项目一次性拉下来,不到2分钟就全部搞定了)
3.子应用架构基本一样,依赖基本相同的,依赖如何复用
4.代码调试的时候想看对应的子应用得启动对应的子应用,能不能一次全启动起来或者有没有其他的什么方案
5.应用的eslint、.babelrc等通用配置都是一样的,能不能只要一份
6.新建子应用项目时能不能一键创建好子应用项目和写好对应的主应用的新增代码,然后直接启动起来就能运行
4.Monorepo实践
经过对比和调研,最终选择了适合我们项目的Monorepo方案,pnpm+turborepo。
4.1 通过Turborepo创建Monorepo项目
1.通过turborepo创建一个Monorepo项目
pnpm dlx create-turbo@latest
启动项目:
pnpm dev
启动起来你访问控制台上提示的地址,你就能看见项目apps文件夹下面默认的2个项目都启动起来了,Docs和Web。
4.2 搭建基于Webpack5 模块联邦(Module Federation)的微前端项目
微前端主应用子应用搭建可参照我这篇文章详细步骤:Webpack5模块联邦微前端方案实践
微前端代码demo地址 如果对你有帮助,希望顺手点个Star,你举手之劳的Star是我继续输出的动力,谢谢!
4.3 Monorepo和微前端结合
-
1.将刚才微前端的main项目拷贝到你创建的Monorepo项目下面,在Monorepo项目新建一个micro文件夹,然后将micro1项目和micro2项目拷贝到micro文件夹下面。
-
2.将通过turborepo创建的默认文件夹apps和packages文件夹删掉。
-
3.修改pnpm-workspace.yaml文件
packages:
- "main"
- "micro/*"
- 4.安装依赖
pnpm i
- 5.运行项目
pnpm dev
此时你会发现三个项目同时启动起来了,当然你可以只访问主应用就行。
- 6.打包命令
pnpm build
运行一个打包命令3个项目都会打出对应的包。
这里可以优化一下,将打包的输出路径设置到根目录下,修改每个应用的module.exports.output.path属性即可,我这里的demo已经修改了,build会将输出的文件输出到根目录的dist文件夹下,也就是dist/main、dist/micro1、dist/micro2,然后到时候部署的时候直接部署dist文件即可,修改一下nginx的配置即可:
location / {
try_files $uri $uri/ /index.html;
index index.html;
}
然后这是一个配置段落(block)针对 Nginx 的 location
指令。
-
location / { ... }
: 这定义了一个新的位置块,匹配所有请求的 URI。因为它使用/
,所以这是最基础的匹配,匹配所有进入的请求。 -
try_files $uri $uri/ /index.html;
: 这是一个尝试按顺序查找文件或目录的指令。$uri
: 尝试匹配请求的 URI 到一个实际的文件。例如,如果请求的是/image.jpg
,Nginx 会尝试查找文件系统中的image.jpg
文件。$uri/
: 如果上一个匹配没有找到文件,Nginx 会尝试将 URI 识别为一个目录。例如,如果请求的是/images/
,Nginx 会尝试查找images/
目录。/index.html
: 如果前两个尝试都失败,Nginx 将默认提供index.html
文件作为响应。
-
index index.html;
: 如果请求的 URI 是一个目录(例如/
或/some-directory/
),Nginx 将尝试提供该目录下的index.html
文件作为默认页面。
综上所述,这个配置的目的是尝试按顺序提供 URI 匹配的文件、目录或默认的 index.html
文件。如果所有尝试都失败,Nginx 将返回一个 404 错误。
Tips:也就是说你写代码的时候得注意,访问的时候设置的路由路径要以对应的文件名称开头,例如micro1中的页面路径是:/micro1/xxx,类似于这样。
- 7.项目代码地址:micro-monorepo 如果对你有帮助,希望顺手点个Star,你举手之劳的Star是我继续输出的动力,谢谢!
到这里我们就将微前端项目和monorepo结合起来了,当然我们还能做很多事情,例如将主应用子应用一样的依赖配置等提取出来,提取到根目录,通过配置,只需要用一份配置即可。简化主应用和子应用的代码结构,还有打包配置也可以配置成所有的项目打包到根目录的dist文件夹下,然后部署的时候通过nginx配置可以只部署一次,使用一个域名就可以了。
6.总结
这套架构如果适合你们的项目,可以先进行调研研究,真的适合可以直接使用,然后还可以在这基础上进行针对的优化,对于后续的开发能大大提高效率和有更顺滑的开发体验。
参考资料: