微前端在管理系统中的最佳实践
⽂章⽬录
⼀、业务背景
近期的⼀个业务涉及对管理系统统进⾏重构,涉及业务主要是后端监控,包括服务器的CPU,内存、磁盘、QPS、QPM,JVM监控等,同时也包括⽤户和权限管理模块;前后端未分离,页⾯总数达到50+,整个项⽬加载后将近20M,相当庞⼤,我们要⽀持的既有之前代码的重构,⼜有新业务需求,⼯作量不⼩
⼆、待解决的研发痛点
本次技术选型,主要是解决之前开发时遇到的痛点:
1. ⼯程越来越复杂,打包越来越慢,构建产出物越来越⼤
2. 团队⼈员多,产品功能复杂,代码冲突多、影响⾯⼤
3. 前后端未分离,或分离不彻底
4. 界⾯和逻辑混杂
5. 发布流程耗时、繁琐
核⼼⽬的都是提⾼⽤户体验、理顺开发流程、提⾼⼯程效率;经过筛选,我们最终选择了微前端的开发⽅案。
三、微前端简介和实践
微前端简单地说,就是将⼀个⼤的前端⼯程拆分成⼀个⼀个的⼩⼯程。别⼩看这些⼩⼯程,它们也都是可以独⽴开发、构建、运⾏、发布的;整个系统就是由这些⼩⼯程协同合作,实现整个系统的展⽰与交互。我们运⽤⼀种新技术,并不是因技术新⽼,⽽是因为他们能够真正有效的解决我们当前页⾯遇到的问题,接下来详细讲解⼀下微前端框架icestark在我们项⽬中的应⽤和最佳实践。
原理简介
微前端分为框架应⽤和⼦应⽤,框架应⽤内部维护了所有⼦应⽤的配置信息,包括路由规则、bundle 地址等,同时劫持了 window.history 相关的⼏个跳转事件,当捕获到页⾯跳转事件时,框架会根据跳转的路由获取对应的⼦应⽤信息,然后跟之前的⼦应⽤信息进⾏对⽐,如果是同⼀个⼦应⽤,则什么都不做,如果是不同的⼦应⽤,则将前⼀个⼦应⽤的 bundle 卸载,同时加载新的⼦应⽤ bundle 资源,
加载完成后⼦应⽤ bundle 会执⾏⾃⾝的渲染逻辑。⼀个系统只有⼀个框架应⽤,框架应⽤负责整体的 Layout 以及⼦应⽤的管理与注册;⼦应⽤通常是⼀个单页⾯应⽤,可能包含⼀个或多个页⾯,⼦应⽤负责⾃⾝相关页⾯代码。
整体⽅案
1. 项⽬⽬录
│───dist  ----------------------项⽬打包⽬录
├──package-lock.json
├──package.json
├── src -------------------------开发⽬录
│├── common
││├── components
│├── consolePro
│├── frameIndex ---------------主应⽤
│├── homePro
│├── screenPro  ---------------⼦应⽤
││├── api
│││└── index.js
││├── components  ----------当前⼦应⽤公共组件
│││└── Func
│││├── index.jsx
│││├── index.jsx
│││└── index.scss
││├── index.html -----------html
││├── index.js  ------------⼊⼝js
││├── store    ------------store
││├── action
│││└── index.js
││├── action-types.js
││├── index.js
││└── reducer
││└── index.js
│├── settingPro -------------⼦应⽤
2. 主应⽤
实际项⽬中主应⽤包括整体Layout,Header、Footer、左侧菜单、⼦应⽤的注册。⽐较核⼼的部分是路由注册机制,我们要处理好本地、预发、⽣产不同的环境下的⼦应⽤注册,这⾥应该从构建⾓度统⼀处理,避免打包时到处⼿动修改配置
import React from"react";
import{ AppRouter, AppRoute }from"@ice/stark";
class MainFrame extends Component {
getSubAppResource(app){
let appConfig ={
dashboard:{
development:[
"localhost/js/main.js",
"localhost/css/index.css"
],
beta:[
"beta/css/index.css",
"beta/js/main.js",
],
production:[
"pro/css/index.css",
"pro/js/main.js",
]
}
}
return appConfig[app][v.NODE_ENV]
}好用的前端框架
render(){
return(
<AppRouter
onRouteChange={this.handleRouteChange}
onAppLeave={this.handleAppLeave}
onAppEnter={this.handleAppEnter}
>
<AppRoute
path="/dashboard"
basename="/dashboard"
hashType={true}
title="数据⼤屏"
url={SubAppResource('dashboard')}
/>
<!--其他⼦应⽤-->
</AppRouter>
);
}
}
3. ⼦应⽤
⼦应⽤的划分主要依据业务的归类,例如:设置⼦应⽤,数据⼤屏⼦应⽤、控制台⼦应⽤等,⼦应⽤都会在中间模块展⽰。由于本次
是同⼀团队开发,全部项⽬都放到⼀个⼤的⼯程⾥,如果多团队协作,⼦应⽤也可以分离出去,⼦应⽤⽬录结构和主应⽤⼀致。
4. 共享模块
多个应⽤通⽤模块可独⽴出来,防⽌代码冗余;例如:搜索组件、404页⾯、公⽤⼯具类等
构建优化
1. 整体⽅案
提取公共Webpack配置⽂件common.js,框架和⼦应⽤都有⾃⼰的配置⽂件,⼀⽅⾯继承公共配置,另⼀⽅⾯配置⾃⼰的启动端⼝和publicpath等差异化属性。另外npm script需要针对每个应⽤和各个环境定制,例如主框架本地启动:npm run start;主框架预发环境构建:npm run build-beta;主框架⽣产环境构建:npm run build-pro;其他⼦应⽤也⼀样,核⼼⽬的是通过不同的命令构建适配不同环境的代码,避免发布时⼿动到处修改代码适配各个环境。
2. 构建优化
1. node_modules共享:多个⼦应⽤共享node_modules,较少体积,提⾼效率
2. pre-build cdn + bundless:通过DllPlugin提前打包公共类库并发布到cdn,通过script引⼊,剩余要构建的只包含业务代码,
优化过程中可通过webpack-bundle-analyzer插件分析bundle的结构,我们最终每个⼦应⽤构建后⼤⼩在200kb左右。
作⽤域控制
多个⼦应⽤css和js可能相互影响,我们可通过以下⽅式避免:
1. CSS 隔离
1. 尽量少使⽤基础组件(防⽌⼦应⽤有不同版本造成冲突)
2. 尽量使⽤独有的 class,可以添加统⼀的前缀或者开启 CSS Module
2. js隔离
1. 全局性的变量、函数需要添加统⼀前缀,避免重复
2. 各个应⽤的开发团队之间,确定⼀些开发公约
3. 最后如果是接⼊已有代码且评估影响较⼤,还是建议回退到iframe⽅式接⼊,减少冲突和影响
前后端分离
1. 未分离的痛点
1. 本地开发:强依赖后端,需要启动后端项⽬才能运⾏前端,后端环境搭建复杂。
2. 发布:两端耦合,⼀端发布必须连带另⼀端。
3. 代码管理:某个分⽀到底是处理前端问题还是后端问题?如果是主要处理前端问题但⼜必须携带后端代码,导致git仓库臃肿。
2. 怎样分离
1. 开发分离: 使⽤Mock;后端⽀持cros;使⽤devServer的proxy实现接⼝代理。
2. 发布分离:我们要实现全部分离,包括html、js、css、图⽚等所有静态资源,发布项⽬下包括主框架和各个⼦应⽤,可以分别
分布,互不影响。
3. 延伸
1. 前端发布也是整个前端⼯程化的重要组成部分,我们的⽬标是:a、⾼效发布(预发问题调试⾮常需要频繁改动代码后⽴即编
译、发布、多终端观察效果) b、可随时回滚任意版本 c、线上发布需审批 d、节省资源 e、可⽀持独⽴域名 f、⾼并发。如果使⽤公司发布平台发布⼀个应⽤,预发环境⾄少⼀台2C2G,线上环境双机房⾄少两台4C4G,这样的成本,想想都⼼疼,我们的最佳实践是基于 OSS + Domain Proxy 的⾃研前端发布系统,配合发布脚本可以在预发环境⼀键构建并发布多个项
⽬,Domain Proxy服务器4C4G单台可达3万tps,彻底解决前端发布难题,⾮常适合微前端应⽤发布。
四、总结
以上就是我们使⽤微前端的最佳实践,最终我们追求的⽬标是:
1. 更好的⽤户体验
2. 前后端彻底分离解耦,包括开发阶段 + 发布阶段
3. ⽅便多⼈甚⾄多团队协作
4. 界⾯和逻辑分离
5. 提⾼构建速度,较⼩构建产物
6. 可快速独⽴部署
由于本⼈⽔平有限,希望⼤家多提意见建议,共同探讨微前端最佳实践,推动微前端项⽬的落地。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。