当前位置: 首页 > news >正文

前端微服务实战:大型应用的拆分与治理

"这个系统已经无法维护了..."周五的架构评审会上,我盯着屏幕上那张错综复杂的依赖关系图发愁。作为一个运行了三年的企业级中后台系统,代码量已经超过 50 万行,构建时间长达 40 分钟,任何修改都可能引发连锁反应。

更让人头疼的是,随着业务的快速发展,不同业务线之间的耦合越来越严重。一个小小的样式修改都可能影响到其他模块的展示。经过团队讨论,我们决定采用微前端架构对系统进行拆分重构。

现状分析

首先梳理了系统目前面临的主要问题:

  • 构建部署效率低下
  • 团队协作成本高
  • 技术栈难以升级
  • 代码复用困难
  • 线上问题难以隔离

就像一座不断扩建的大楼,没有合理的分区和规划,最终变得杂乱无章。我们需要把这座大楼重新规划成一个个独立又互联的空间。

架构设计

经过调研和验证,我们选择了基于 single-spa 的微前端方案:

// 基座应用
import { registerApplication, start } from 'single-spa'// 注册子应用
const registerMicroApp = (name: string, entry: string) => {registerApplication({name,app: async () => {// 动态加载子应用const module = await System.import(entry)return module.default},activeWhen: location => {// 基于路由匹配激活子应用return location.pathname.startsWith(`/${name}`)}})
}// 子应用配置
const microApps = [{name: 'crm',entry: '//localhost:3001/main.js',activeRule: '/crm'},{name: 'erp',entry: '//localhost:3002/main.js',activeRule: '/erp'},{name: 'dashboard',entry: '//localhost:3003/main.js',activeRule: '/dashboard'}
]// 注册所有子应用
microApps.forEach(app => registerMicroApp(app.name, app.entry))// 启动微前端框架
start()

子应用改造

每个子应用需要暴露生命周期钩子:

// 子应用入口
import React from 'react'
import ReactDOM from 'react-dom'
import { createStore } from './store'// 导出生命周期钩子
export async function bootstrap() {console.log('应用启动中...')
}export async function mount(props) {const { container, globalStore } = propsconst store = createStore(globalStore)ReactDOM.render(<Provider store={store}><App /></Provider>,container)
}export async function unmount(props) {const { container } = propsReactDOM.unmountComponentAtNode(container)
}

通信方案

子应用间的通信是一个关键问题,我们实现了一个事件总线:

// utils/eventBus.ts
class EventBus {private events = new Map<string, Function[]>()// 订阅事件on(event: string, callback: Function) {if (!this.events.has(event)) {this.events.set(event, [])}this.events.get(event).push(callback)// 返回取消订阅函数return () => {const callbacks = this.events.get(event)const index = callbacks.indexOf(callback)callbacks.splice(index, 1)}}// 发布事件emit(event: string, data?: any) {if (!this.events.has(event)) returnthis.events.get(event).forEach(callback => {try {callback(data)} catch (error) {console.error(`事件处理错误: ${event}`, error)}})}
}export const eventBus = new EventBus()

样式隔离

为了避免样式冲突,我们采用了 CSS Modules 和动态前缀:

// webpack.config.js
module.exports = {module: {rules: [{test: /\.css$/,use: ['style-loader',{loader: 'css-loader',options: {modules: {localIdentName: '[name]__[local]___[hash:base64:5]'}}},{loader: 'postcss-loader',options: {plugins: [require('postcss-prefix-selector')({prefix: `[data-app="${process.env.APP_NAME}"]`})]}}]}]}
}

性能优化

微前端架构下的性能优化主要从这几个方面入手:

// 预加载策略
const prefetchApps = async () => {const nextPossibleApps = predictNextApps()nextPossibleApps.forEach(app => {const script = document.createElement('link')script.rel = 'prefetch'script.href = app.entrydocument.head.appendChild(script)})
}// 共享依赖
const sharedDependencies = {react: {singleton: true,requiredVersion: '^17.0.0'},'react-dom': {singleton: true,requiredVersion: '^17.0.0'},'react-router-dom': {singleton: true,requiredVersion: '^5.2.0'}
}

实践效果

经过三个月的改造,我们取得了显著的成效:

  • 构建时间从40 分钟减少到 5 分钟
  • 各团队可以独立开发部署
  • 线上问题可以快速定位和修复
  • 新技术栈的尝试变得容易

最让我印象深刻的是一位同事说:"现在终于可以专注于业务开发,不用担心影响到其他团队了。"

经验总结

微前端架构就像城市规划,需要统筹兼顾又要保持灵活。我们的经验是:

合理分层 - 基座应用要足够稳定清晰边界 - 子应用之间要解耦统一规范 - 公共依赖要严格管理持续优化 - 性能问题要重点关注

写在最后

微前端不是银弹,它更像是一把双刃剑。使用得当可以大幅提升开发效率,但也会带来一定的复杂性。关键是要在架构设计时充分权衡,在实施过程中严格把控。

有什么问题欢迎在评论区讨论,让我们一起探讨微前端架构的最佳实践!

如果觉得有帮助,别忘了点赞关注,我会继续分享更多实战经验~

相关文章:

前端微服务实战:大型应用的拆分与治理

"这个系统已经无法维护了..."周五的架构评审会上,我盯着屏幕上那张错综复杂的依赖关系图发愁。作为一个运行了三年的企业级中后台系统,代码量已经超过 50 万行,构建时间长达 40 分钟,任何修改都可能引发连锁反应。 更让人头疼的是,随着业务的快速发展,不同业务线之间…...

Linux shell的七大功能 --- history

1.直接输入“history” 这个命令可以显示出曾经使用过的命令&#xff08;最近时间的500条&#xff09; history 2.“history”命令也可以搭配其他命令一起使用。 例&#xff1a;history | grep "vim"&#xff0c;找出所有包含“vim”的记录&#xff1b; 也可以搭配…...

C++ webrtc开发(非原生开发,linux上使用libdatachannel库)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、libdatachannel库的下载和build二、开始使用 1.2.引入库3.开始使用 总结 前言 使用c开发webrtc在互联网上留下的资料甚少&#xff0c;经过我一段时间的探…...

C语言刷题

1. 题目描述 根据给出的三角形3条边a:b.c(a.b,c<100.000)&#xff0c;计算三角形的周长和面积。 输入描述: 一行&#xff0c;三角形3条边(能构成三角形)&#xff0c;中间用一个空格隔开. 输出描述: 一行&#xff0c;三角形周长和面积保留两位小数&#xff0c;中问用一个空…...

LabVIEW实现RFID通信

目录 1、RFID通信原理 2、硬件环境部署 3、程序架构 4、前面板设计 5、程序框图设计 6、测试验证 本专栏以LabVIEW为开发平台,讲解物联网通信组网原理与开发方法,覆盖RS232、TCP、MQTT、蓝牙、Wi-Fi、NB-IoT等协议。 结合实际案例,展示如何利用LabVIEW和常用模块实现物联网系…...

Linux 网络流量控制 - 实现概述

摘要 Linux 提供了一整套丰富的流量控制(traffic control)功能。本文档概述了相应的内核代码设计&#xff0c;描述了其结构&#xff0c;并通过描述一种新的排队策略来说明新元素的添加。 1 引言 最近的Linux内核提供了多种流量控制功能。Alexey Kuznetsov&#xff08;kuznet…...

分布式 令牌桶算法 总结

前言 相关系列 《分布式 & 目录》《分布式 & 令牌桶算法 & 总结》《分布式 & 令牌桶算法 & 问题》 参考文献 《【算法】令牌桶算法》 概述 简介 TBA Token Bucket Algorithm 令牌桶算法是一种流行于网络通信领域的流量控制/频率限制算法。令牌…...

FFMPEG视频转图片

用FFMPEG视频转图片&#xff0c;并且for循环 import os import subprocess# 输入文件夹和输出文件夹路径 input_folder r"I:\xxx" output_base_folder r"D:\xxx\YOLO\data\video" output_subfolder_name "20240609"# 创建输出子文件夹 output…...

docker入门实践---虚拟机环境配置

文章目录 1.检查内核版本2.确定centos7可以上网3.关闭防火墙4.关闭防火墙5.更换阿里云6.安装gcc7.设置镜像仓库&#xff08;阿里云&#xff09;8更新软件包9.安装docket-ce10.启动docker11.普通用户权限设置 1.检查内核版本 2.确定centos7可以上网 3.关闭防火墙 下面的这个表示…...

java要防止重复序列化的问题JSON.toJSONString转义问题

要防止重复序列化的问题JSON.toJSONString(entity) 20241213 10:29 背景&#xff1a; 我在设计业务实现echart图标渲染&#xff0c;业务接口实时性查询耗时很长&#xff0c;为了提高系统可用性和用户体验&#xff0c;采用中间表的方案——即在中间表中存储大JSON。 但是在自测…...

TS的类型守卫、类型约束实践

类型守卫 // 基础类型判断 const arr [30, 50] console.log(typeof arr) // object const set new Set(arr) console.log(typeof set) // object const map new Map() console.log(typeof map) // objectclass Customer {constructor() {}buy(method:string) {console.log(…...

文件转曲,限制PDF文件编辑的最佳方案!

随着数字化进程的推进&#xff0c;PDF文件凭借其多样化的功能和优越的兼容性已经被广泛使用&#xff0c;成为了现代文档交流和存储的重要工具&#xff0c;满足了不同用户和行业的需求。 虽然PDF格式文件的功能很多&#xff0c;常见的比如阅读、编辑、加密、转换、还可用于印刷…...

MySQL系列之数据授权(安全)

导览 前言Q&#xff1a;如何对MySQL数据库进行授权管理一、MySQL的“特权”1. 权限级别2. 权限清单 二、授权操作1. 查看权限2. 分配权限3. 回收权限 结语精彩回放 前言 看过博主上一篇的盆友&#xff0c;可以Get到一个知识点&#xff1a;数据授权&#xff08;eg&#xff1a;g…...

用 Python 实现经典的 2048 游戏:一步步带你打造属于你的小游戏!

用 Python 实现经典的 2048 游戏&#xff1a;一步步带你打造属于你的小游戏&#xff01;&#xff08;结尾附完整代码&#xff09; 简介 2048 是一个简单而又令人上瘾的数字拼图游戏。玩家通过滑动方块使相同数字的方块合并&#xff0c;目标是创造出数字 2048&#xff01;在这篇…...

Vue vs. React:两大前端框架的深度对比与分析(一)

前言 在当今快速发展的前端领域中&#xff0c;Vue和React作为两个备受瞩目的前端框架&#xff0c;已经成为许多开发者的首选。这两个框架凭借其出色的设计和强大的功能&#xff0c;在构建现代化、高效性能的Web应用方面扮演着重要角色。 Vue和React都以其独特的特点吸引了众多开…...

React 进阶深入理解核心概念与高阶实践

在上一节中&#xff0c;我们学习了 React 的基础知识&#xff0c;包括组件、状态管理和基本操作。接下来&#xff0c;我们将进一步探索 React 的高级功能和实战技巧&#xff0c;例如 组件间通信、高阶组件、Context API、React Router 等。这些内容将帮助你构建更复杂、功能更丰…...

Linux shell的七大功能 ---自动补齐、管道机制、别名

1、自动补齐---TAB 输入命令的前几个字符&#xff0c;按下tab键&#xff0c;会自动补齐完整的字符&#xff0c;若有多个命令、文件或目录的前几个字符相同&#xff0c;按下tab将会全部列举出来 2、管道机制---| 例如&#xff1a;ls -- help |more 将有关ls的帮助内容传递给“|…...

XML 在线格式化 - 加菲工具

XML 在线格式化 打开网站 加菲工具 选择“XML 在线格式化” 输入XML&#xff0c;点击左上角的“格式化”按钮 得到格式化后的结果...

java_多态的应用

多态数组 应用实例:现有一个继承结构如下&#xff1a;要求创建 1 个 Person 对象、2 个 Student 对象和 2 个 Teacher 对象, 统一放在数组中&#xff0c;并调用每个对象 代码 Person类 package com.hspedu.poly_.polyarr_;import javax.swing.*;/*** author:寰愬悏瓒&#xf…...

Python+OpenCV系列:模版匹配

文章目录 1. 模板匹配基本原理2. cv2.matchTemplate() 函数函数原型&#xff1a; 3. 模板匹配步骤4. 单目标模板匹配示例5. 多目标模板匹配多目标模板匹配示例代码解析&#xff1a; 6. 多模板匹配多模板匹配示例代码解析 7. 总结 模板匹配是一种在图像中寻找模板的位置的方法。…...

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?

编辑&#xff1a;陈萍萍的公主一点人工一点智能 未来机器人的大脑&#xff1a;如何用神经网络模拟器实现更智能的决策&#xff1f;RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战&#xff0c;在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…...

Cursor实现用excel数据填充word模版的方法

cursor主页&#xff1a;https://www.cursor.com/ 任务目标&#xff1a;把excel格式的数据里的单元格&#xff0c;按照某一个固定模版填充到word中 文章目录 注意事项逐步生成程序1. 确定格式2. 调试程序 注意事项 直接给一个excel文件和最终呈现的word文件的示例&#xff0c;…...

k8s从入门到放弃之Ingress七层负载

k8s从入门到放弃之Ingress七层负载 在Kubernetes&#xff08;简称K8s&#xff09;中&#xff0c;Ingress是一个API对象&#xff0c;它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress&#xff0c;你可…...

Java - Mysql数据类型对应

Mysql数据类型java数据类型备注整型INT/INTEGERint / java.lang.Integer–BIGINTlong/java.lang.Long–––浮点型FLOATfloat/java.lang.FloatDOUBLEdouble/java.lang.Double–DECIMAL/NUMERICjava.math.BigDecimal字符串型CHARjava.lang.String固定长度字符串VARCHARjava.lang…...

CocosCreator 之 JavaScript/TypeScript和Java的相互交互

引擎版本&#xff1a; 3.8.1 语言&#xff1a; JavaScript/TypeScript、C、Java 环境&#xff1a;Window 参考&#xff1a;Java原生反射机制 您好&#xff0c;我是鹤九日&#xff01; 回顾 在上篇文章中&#xff1a;CocosCreator Android项目接入UnityAds 广告SDK。 我们简单讲…...

NLP学习路线图(二十三):长短期记忆网络(LSTM)

在自然语言处理(NLP)领域,我们时刻面临着处理序列数据的核心挑战。无论是理解句子的结构、分析文本的情感,还是实现语言的翻译,都需要模型能够捕捉词语之间依时序产生的复杂依赖关系。传统的神经网络结构在处理这种序列依赖时显得力不从心,而循环神经网络(RNN) 曾被视为…...

MySQL中【正则表达式】用法

MySQL 中正则表达式通过 REGEXP 或 RLIKE 操作符实现&#xff08;两者等价&#xff09;&#xff0c;用于在 WHERE 子句中进行复杂的字符串模式匹配。以下是核心用法和示例&#xff1a; 一、基础语法 SELECT column_name FROM table_name WHERE column_name REGEXP pattern; …...

【碎碎念】宝可梦 Mesh GO : 基于MESH网络的口袋妖怪 宝可梦GO游戏自组网系统

目录 游戏说明《宝可梦 Mesh GO》 —— 局域宝可梦探索Pokmon GO 类游戏核心理念应用场景Mesh 特性 宝可梦玩法融合设计游戏构想要素1. 地图探索&#xff08;基于物理空间 广播范围&#xff09;2. 野生宝可梦生成与广播3. 对战系统4. 道具与通信5. 延伸玩法 安全性设计 技术选…...

是否存在路径(FIFOBB算法)

题目描述 一个具有 n 个顶点e条边的无向图&#xff0c;该图顶点的编号依次为0到n-1且不存在顶点与自身相连的边。请使用FIFOBB算法编写程序&#xff0c;确定是否存在从顶点 source到顶点 destination的路径。 输入 第一行两个整数&#xff0c;分别表示n 和 e 的值&#xff08;1…...

AI+无人机如何守护濒危物种?YOLOv8实现95%精准识别

【导读】 野生动物监测在理解和保护生态系统中发挥着至关重要的作用。然而&#xff0c;传统的野生动物观察方法往往耗时耗力、成本高昂且范围有限。无人机的出现为野生动物监测提供了有前景的替代方案&#xff0c;能够实现大范围覆盖并远程采集数据。尽管具备这些优势&#xf…...