微前端简介、注意事项及常见技术方案

1 概述

微前端是一种类似于微服务的架构,它将微服务的理念应用于浏览器端,即将 Web 应用由单一的单体应用转变为多个小型前端应用聚合为一的应用,各个前端应用还可以独立运行独立开发独立部署。

实现微前端不管是采用什么方案,本质都是一样的,微前端各个部分之间相互独立、独立部署的能力本质是在允许构建孤立或松散耦合的服务

微前端的一般结构如下:

在这里插入图片描述

2 使用场景

1)治理巨石应用

单体应用不断膨大导致理解和修改的成本上升,代码的提交到实际部署的周期越来越长,并且很容易出现问题。

这时,我们可以把原有功能抽离为单独的子应用,而新的功能模块作为新的子应用嵌入,在逐渐重构的过程中,既要保证中间版本能够平滑过渡,还能持续交付新的功能。

2)应用功能自由组合拆分及定制化开发

在业务方面,经常可能会面临不同特定的定制化需求或者功能组合,那实际上我们可以对每个单独的功能作为一个单独的子系统开发、子系统间的耦合,只需要规定好相应的通讯方式和内容,不需要关注对方的实现,在需要的时候自由组合即可。

3 使用微前端需要关注什么

在实践一个微前端的架构,我们需要关注哪些切实的问题呢?

通讯和状态管理

微前端的实现本质也是一种组合的思想,子应用间的组合跟功能中组件的组合有类似之处,组件之间的组合最重要的就是通讯和状态管理

不同的子应用之间组合而成,无法避免状态管理的问题,无论是全局下的状态管理、几个子应用间的局部状态管理,还是单个子应用间的状态管理,以及状态的上传和下发,都将是我们需要去考虑的问题。

在采用微前端架构的时候,很多时候遇到的问题可以转化成:如果一个 model 的变化会引起另一个 model 变化,那么当 view 变化时,就可能引起对应 model 以及另一个 model 的变化,依次地,可能会引起另一个 view 的变化。

这本质上是两个问题:

  • 子会响应父的状态变化,父会在子初始化之后初始化,子会在父变更后变更,导致子状态必须在子组件内部
  • vue/react 以及状态管理,只有子向父 dispatch 事件的能力,父无法向子 dispatch 事件

实现一个发布订阅模型就能解决这个问题,这也是为什么 qiankun 之类的微前端方案的应用间通讯方式是使用发布订阅的方式进行的,这样 parent 和 child 就可以彼此通过事件传递消息,且独立变化。

工作空间的独立

1)js沙箱

因为每一个子应用都是一个单独的项目和应用,在同一个页面中出现多个子应用是很常见的场景。

出于安全考虑,例如全局变量污染、多版本库等,还有各种复杂场景下的执行问题,我们需要对每个子应用间的 js 的工作空间进行隔离,使每个子应用内的执行自洽,只关注输出和输入,js沙箱的实现成为微前端方案中需要关注的一点

js沙箱是一种安全机制,为 js 代码创建了一个隔离的运行环境,使得在沙箱中运行的代码不会对全局环境产生影响,沙箱环境可以限制代码对某些资源的访问权限,比如全局变量、浏览器 API 等

js沙箱机制相关资料:https://zhuanlan.zhihu.com/p/527437146

2)css沙箱

虽然是微前端的结构,但本质上同一个页面中每个子应用的挂载依旧在同一个 dom 树上,那子应用间的样式自然不应该出现互相干扰的情况,并且在子应用切换时可以自行装载和卸载。

PS:单纯的 iframe 实现微前端的方案虽然有很多问题,但是在 js 和 css 的隔离上无疑是成本最低且较好的实现

路由管理

1)路由劫持

方案原理大致是监听 hashchange 事件,劫持浏览器 history 下的 pushState 和 replaceState

2)主应用控制路由

实现思路是主应用使用现有的路由库(vue-router或react-router),子应用使用 webpack 提供的 import() 函数动态加载子应用的模块

3)子应用的资源加载方式

资源加载方式影响页面加载速度,主要分为 html entry 和 js entry,前者加载是按原来方式打包出来的一个 html 文件,后者是加载子应用打出来的整个 js 文件。

如果将整个微应用打包成一个 js 文件,那常见的打包优化都用不了,例如:按需加载、首屏资源加载优化、css独立打包等

预加载

在微前端的方案中,每个子应用都是独立的,如果不做处理的话,在一个页面存在多个子应用的情况下,每个子应用的加载都是独立的,在这种情况下可能会出现白屏情况,导致用户体验不好。

并且在实际使用中,浏览器大部分是处在空闲的,我们要怎么利用这样的空闲时间,去加载其他子应用的 js 呢?

公共依赖的处理问题

子项目多了之后,公共依赖如果处理不好,会造成各种重复工作,bug风险也会增长,不利于后期维护。

是否支持应用保活

在切换子应用后,之前的状态是否需要保存,事关 keep-alive 之类在微前端的架构中怎么做

子应用之间的互相嵌套

是否支持子应用之间的互相嵌套,子应用组件互相嵌套后的通讯和状态管理又需要怎么做

4 常见技术方案

iframe

通过 iframe 我们可以很方便地将一个应用嵌入到另一个应用中,而且两个应用之间的 css 和 js 是相互隔离的,互不干扰

优点:

  • css 和 js 天然隔离,互不干扰
  • 多个子应用可以并存,不需要对现有应用进行改造
  • 与技术栈无关

缺点:

  • 每次切换应用时,浏览器都需要重新加载页面
  • UI 不同步,DOM 结构不共享
  • 全局上下文完全隔离,内存变量不共享,子应用之间通信、数据同步过程比较复杂

single-spa

在 single-spa 方案中,应用被分为两类:基座应用和子应用,子应用是需要聚合的应用,基座应用是另外一个单独的应用,用于聚合子应用

和单页应用的实现原理类似,single-spa 会在基座应用中维护一个路由注册表,每个路由对应一个子应用。基座应用启动以后,当我们切换路由时,如果是一个新的子应用,会动态获取子应用的 js 脚本,然后执行脚本并渲染出相应的页面;如果是一个已经访问过的子应用,那么就会从缓存中获取已经缓存的子应用,激活子应用并渲染出对应页面

优点:

  • 切换应用时,浏览器不用重载页面,提供和单页应用一样的用户体验
  • 多个子应用可并存
  • 与技术栈无关

缺点:

  • 需对原有应用进行改造,应用要兼容接入 single-spa 和独立使用
  • 使用复杂,子应用加载、隔离、通信等问题,需要自己实现
  • 子应用间相同资源重复加载
  • 启动应用时,要先启动基座应用

qiankun

qiankun 是在 single-spa 的基础上做了二次开发,在框架层面上解决了使用 single-spa 时需要开发人员自己编写子应用加载、通信、隔离等逻辑的问题,是一种比 single-spa 更优秀的微前端方案

优点:

  • 切换应用时,浏览器不用重载页面,提供和单页应用一样的用户体验
  • 相比 single-spa,解决了子应用加载、隔离、通信等问题,使用起来相对简单
  • 多个子应用可并存
  • 与技术栈无关

缺点:

  • 需对原有应用进行改造,应用要兼容接入 qiankun 和独立使用
  • 相同资源重复加载
  • 启动应用时,要先启动基座应用

webpack5:module federation

webpack5 提供了一个新特性:module federation,基于这个特性,我们可以在一个 JavaScript 应用中动态加载并运行另一个 JavaScript 应用的代码,并实现应用之间的依赖共享

通过 module federation,我们可以在一个应用里面动态渲染另一个应用的页面,这样就实现了多个子应用的聚合

优点:

  • 切换应用时,浏览器不用重载页面,提供和单页应用一样的用户体验
  • 相同资源不需要重复加载
  • 应用启动后,无需加载与自己无关的资源
  • 免登友好

缺点:

  • 构建工具只能使用 webpack5
  • 对老项目不友好,需要对 webpack 进行改造
<think>好的,我现在需要帮助用户解决前端项目迁移的技术方案和最佳实践的问题。首先,我要回忆一下用户之前的引用内容,虽然这些引用可能不完全相关,但或许能找到一些有用的信息。 用户提到了Babel的最佳实践、前端简历优化、Vue 3的指南以及Django前端管理界面。其中,Babel的编译原理和配置可能涉及迁移中的代码转换,Vue 3的新特性可能在迁移到新框架时有用,而Django的案例可能帮助理解如何调整前端界面。不过用户的核心需求是迁移的技术方案和最佳实践,所以需要专注于迁移的通用步骤和注意事项。 首先,前端迁移通常包括几个步骤:评估现有项目、技术选型、增量迁移、工具链适配、性能优化、测试验证和文档维护。我需要确保每个步骤都有具体的方法和工具支持。例如,评估阶段需要分析技术栈和依赖,这可能涉及到使用工具如Webpack Bundle Analyzer来分析依赖体积。技术选型方面,可能需要考虑Vue 3、React 18或者新的构建工具如Vite,这些在用户的引用中也有提到。 然后,增量迁移是关键,可以采用微前端架构或条件编译,比如使用Webpack的模块联邦或者动态导入。这里需要确保新旧系统能共存,避免大规模重写。工具链方面,Babel和TypeScript的配置很重要,用户的引用[1]提到Babel的配置实践,可以引用这一点。另外,自动化测试工具如Jest和Cypress能帮助保证迁移后的功能稳定,用户引用[3]中的Vue 3最佳实践也提到了测试的重要性。 性能优化部分,用户引用[2]提到了将加载时间从3秒缩短到1.5秒,这可能涉及到代码分割、懒加载等策略,这些在迁移过程中也是关键点。最后,文档和监控需要持续维护,使用Sentry进行错误监控,这一点在用户的问题中没有提到,但属于最佳实践的一部分。 现在需要检查是否有遗漏的步骤,比如团队协作和培训,这可能涉及代码规范和CI/CD流程,确保团队顺利过渡。另外,验证引用内容是否适用,比如引用[4]中Django的自定义选项可能不直接相关,但可以忽略,因为用户的需求是迁移而非管理界面。 最后,生成相关问题需要考虑用户可能感兴趣的后续步骤,比如工具链选择、旧版本兼容、性能优化、测试策略和团队协作,这些都是迁移过程中常见的挑战。需要确保问题覆盖这些方面,帮助用户深入探索每个环节。</think>### 前端项目迁移技术方案与最佳实践指南 #### 一、迁移前准备阶段 1. **技术栈评估与分析** - 使用依赖分析工具(如$webpack-bundle-analyzer$)生成依赖树状图 - 建立技术债务清单: $$技术债务指数 = \frac{过时依赖数量}{总依赖数} \times 100\%$$ - 统计代码特征(如$jQuery$调用密度:$\frac{出现次数}{代码行数}$) 2. **目标架构设计** 推荐采用渐进式迁移架构: ```mermaid graph LR A[旧系统] --> B[API Gateway] C[新模块] --> B B --> D[用户终端] ``` #### 二、核心迁移技术方案 1. **代码迁移策略** - **增量迁移**:通过动态导入实现新旧模块共存 ```javascript // 旧系统入口 if (isLegacyPath(window.location)) { import('./legacyApp.js') } else { import('./modernApp.js') } ``` - **AST转换**:使用$Babel$插件实现语法转换[^1],例如: ```javascript // 转换前 $.ajax({url: '/data'}) // 转换后 fetch('/data').then(res => res.json()) ``` 2. **样式迁移方案** - 使用$PostCSS$插件自动转换预处理器语法 - 建立设计令牌系统: $$颜色对比度 = \frac{(R1 \times 299 + G1 \times 587 + B1 \times 114)}{1000}$$ #### 三、关键实践要点 1. **性能保障措施** - 实施加载性能监控: $$FCP优化率 = \frac{旧FCP - 新FCP}{旧FCP} \times 100\%$$ - 使用代码分割策略: ```javascript const ProductList = React.lazy(()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值