hi, 大家好, 我是徐小夕, 今天和大家分享一下前端项目重构的一些思考和复盘, 同时也是对自己多年项目研发经验的一个总结.
项目重构是每一家稳定发展的互联企业的必经之路, 就像一个产品的诞生, 会经历产品试错和产品迭代 一样, 随着业务或新技术的不断发展, 已有架构已无法满足更多业务扩展的需求, 所以只有通过重构来让产品“进化”, 才能跟上飞速发展的时代浪潮.
这里我结合自己的实际经验总结一下项目重构的几个原因:
技术因素主要有如下几个方面:
上面是我列出来的比较典型的重构场景, 也是我们未来在设计产品技术架构之前需要考虑的方面. 为了提高自己设计的架构稳定性, 我们需要提前和产品沟通明确, 以降低后期重构和维护成本.
最后总结几条架构设计的经验:
当然做项目重构也是有技术门槛的,不是所有程序员都能做好重构工作, 建议大家具备如下几种技术能力:
接下来我们一起看看常见的几种项目重构场景及其重构方向.
业务系统自身的重构一般可以包含如下几个方面:
业务代码优化主要是针对一些核心业务代码, 进行流程上, 逻辑上的重构, 让它更具可读性和维护性, 同时保证业务操作的兼容性, 具体方案如下:
if else
或者“回调地狱” 可以采用适配器模式或者es6+
语法来优化)js
计算)早期可能由某名研发单独负责的项目, 对代码规范和格式要求不是很高, 但是需要考虑后期团队扩容带来的协作开发问题, 这个时候如果没有统一的规范, 不同研发小伙伴可能写出的代码千奇百怪, 导致后期维护成本巨大, 尤其是涉及到需要维护他人代码时. 所以我们重构的另一个目标就是降低代码理解成本, 保证项目代码在阅读时就像同一个写出来的, 这样对后期逻辑复用, 组件解耦, 问题定位以及业务代码维护将非常有帮助.
常用的措施有:
eslint
)typescript
)当然, 这些都是需要结合自身团队和项目来定的, 这里只做参考.
工程化优化主要有以下几个场景:
接下来我会针对以上场景, 进行一些解决方案的分享.
针对这种情况, 我们可以借助 speed-measure-webpack-plugin
插件,它可以分析 webpack
的总打包耗时以及每个 plugin
和 loader
的打包耗时,从而让我们对打包时间较长的部分进行针对性优化。
同时默认情况react
, react-dom
, react-router
等公共模块在每次构建都会参与打包, 这些实际上是没有必要的, 我们可以将其传到 cdn
上, 从而减少webpack
的打包”工作量“.
我们可以安装 html-webpack-externals-plugin
来实现将指定模块从打包列表中排除, 具体用法如下:
const HtmlWebpackExternalsPlugin = require('html-webpack-externals-plugin');
module.exports = {
// ...其他配置代码
plugins: [
new HtmlWebpackExternalsPlugin({
externals: [
{
module: 'react',
entry: 'https://cdn.dooring.cn/umd/react.production.min.js',
global: 'React',
},
{
module: 'react-dom',
entry:
'https://cdn.dooring.cn/umd/react-dom.production.min.js',
global: 'ReactDOM',
},
],
}),
],
};
为了追求更惊一步的打包效率, 我们可以使用并行的方式构建, 同样 webpack
生态也提供了对应的模块 parallel-webpack
. 具体用法大家可以看文档, 非常简单方便.
其他还有很多优化的方案, 这里我列一下, 大家可以根据实际情况使用:
terser-webpack-plugin
, css-minimizer-webpack-plugin
, html-minimizer-webpack-plugin
等都支持parallel
参数)webpack.DllPlugin
来提前将公共模块打包以便后续直接复用)webpack5
内置的 cache
模块, 或者cache-loader
)webpack-bundle-analyzer
)当然除了对已有构建工具的优化, 我们可以评估一下重构成本, 将构建内核替换vite
等更高效的构建工具.
针对项目代码量的增加导致页面臃肿, 我们可以从项目本身的角度, 对项目进行拆解, 将公共模块抽离为公用业务类库或者组件库:
除了对项目进行可复用性拆分之外, 我们还需要根据系统复杂量级, 近一步拆分项目, 比如将一个巨石工程拆分为多个子工程, 单独运行维护, 或者采用之前热点讨论的微前端的模式, 比如使用 qainkun
, single-spa
, Micro App
, EMP
, Garfish
, Bit
这些优秀的微前端框架.
综上, 我们可以根据项目复杂度, 做如下优化:
当然我们始终需要保持一个理念: 局部最优, 误增繁复.
这种情况主要是在项目发展稳定之后, 需要思考的重构方向, 比如早期由于业务场景单一, 很多公共配置都写在业务代码里的, 随着业务复杂之后, 很多模块都需要使用改配置或者变量, 比如:
// a.js
const publicDomain = 'https://dooring.vip';
const serverUrl = 'https://xxx.cn';
// b.js
const publicDomain = 'https://dooring.vip';
// c.js
const appid = 'xxxxxxxx';
const website_Logo = 'http://h5.dooring.cn/logo.png';
对于这种零散且固定的变量, 未来可能会被多个页面或者模块复用, 所以为了降低成本, 我们可以把这些通用配置提取到外层, 作为公共配置文件, 这样后期新项目也能享受开箱即用的配置体验.
拿我的亲身经验, 比如几年前我开发的低代码项目H5-Dooring
, 有一些零散的配置信息分散在项目的各个角落, 后面经过几次重构优化之后, 整个项目只需要在配置文件中轻松配置内容, 即可一键控制页面的走向, 这里分享一下优化过后的配置文件:
// h5-dooring全局配置文件
define: {
START_ENV,
lang,
// 配置h5端访问的域名
h5Domain: 'h5.dooring.cn',
// 设置当前版本号
curVersion: dooringVersion,
// 备案信息
copyright: 'xxxxx-3',
// 是否显示更新弹窗
showUpdateModal: true,
// 更新日志
updateList: [
"1. 新增表格组件",
"2. 国际化优化",
"3. 表单详情页支持内部滚动",
"4. 个人图片库性能优化",
"5. 下载代码功能优化"
],
// 网站logo地址
logo: 'http://cdn.dooring.cn/dr/logo.ff7fc6bb.png',
// 入口页面是否展示赞助品牌和版权提示
showAdsAndTip: true,
// 登录时获取登录码的二维码
qrcode: 'http://cdn.dooring.cn/dr%2Fcode1.png',
// 友情链接展示
friendLinks: [
{
name: 'V6',
link: 'http://v6.dooring.cn/beta',
title: '可视化大屏编辑器'
},
{
name: 'Power',
link: '/powernice',
title: '文档编辑器'
}
],
// 默认语言
defaultLocale: 'zh-CN',
langMap: langMap
},
这样, 我们的工程化结果就可以让不同的技术小伙伴轻松的享受, 让项目创建的成本和自由度得到极大的提升.
对于这种场景, 我们就需要对脚手架自身有更多的研究和了解, 比如熟悉webpack
设计思想, 熟悉babel
的工作流程, 熟悉 nodejs
开发工具链的一些模式等, 这里分享几个比较成熟的先进脚手架, 大家如果觉得老项目工程比较老旧, 可以往这几个方向重构:
如果大家对以上三种之一比较熟悉, 也可以基于他们二次封装成符合自身业务场景的DIY项目工具.
渲染层优化主要表现在产品的体验上, 比如:
以上是我之前遇到的一些渲染优化的维度, 接下来和大家一一介绍解决思路.
1. 提高首屏加载速度
有很多方法可以帮助我们提高首屏加载速度, 比如:
当然还存在很多客观因素, 比如用户所在区域为弱网环境, 我们可以根据网速提供一个最小化弱网可替代页面, 来保证我们网站的可用性和可访问性.
2. 白屏体验优化
对于白屏优化, 也有很多成熟的例子, 比如采用骨架屏:
如果我们的项目是基于 vue-cli
构建的,那么可以使用比较成熟的的 page-skeleton-webpack-plugin
方案,否则我们仍然可以选择 vue-router
提供的 vue-server-renderer
.
当然你的项目是使用react
的, 也可以轻松使用如 react-content-loader
这样的svg方案来定制自己的骨架屏.
除了骨架屏之外, 我们还可以提供一个模版页面或者加载动画, 以便在页面加载完成之前给用户一个优雅的过渡提示. 比如:
3. 大数据列表渲染优化
对于一些中后台复杂的系统模块, 可能会涉及到一次渲染大量列表项或者多级组织树的情况:
尤其是在大公司或者大集团中出现的频率非常高, 这种情况我们就需要用到虚拟列表或者节点懒加载的方式了. 虚拟列表应用非常广泛, 目前也有几个成熟的方案大家可以直接使用:
如果你的项目目前还好没有使用这种方案, 不妨评估一下, 是否可以用这些方案为自己项目保驾护航.
4. api请求优化
api
请求优化主要正对这种场景: 页面的渲染依赖于某个或者某些请求的完成, 或者由于某个页面请求量过大导致每次重新进入页面都需要造成一定的性能开销.
对于这两种情况, 其实不仅仅是对浏览器渲染有影响, 还会极大的增加服务器的压力, 所以我们需要对请求或者页面进行一定范围的缓存.
比如说我们可以把不长变动的请求数据存在 indexedDB 中, 当第二次访问直接可以从 indexedDB 中拿到请求数据, 这样既降低了服务器压力, 也提高了二次渲染的效率.
其次我们可以对部分页面做路由缓存, 避免每次切换都重新渲染, 当然这只针对于不需要实时更新数据的页面而言. 我之前也分享了一篇浏览器缓存接口实战的文章, 大家感兴趣的可以学习参考, 对于 indexedDB
, 我封装了一个开箱即用的库, 大家可以直接使用:
github地址: https://github.com/MrXujiang/xdb
5. 动画性能优化
这也是个老生常谈的问题, 这里直接分享几个方案:
DOM
结构,合理布局transform
代替 left,top 减少使用引起页面重排的属性transform: translateZ(0)
或者transform: translate3d(0, 0, 0)
)js
动画,如需要,使用性能更友好的requestAnimationFrame
chrome performance
工具调试动画性能由于dom动画有上限很低, 所以对于一些更复杂的动画渲染, 我们可以采用 svg
或者 canvas
来代替, 以降低 dom
对浏览器内存的占用.
6. dom过载导致的页面卡顿优化
一个页面如果dom数量过多, 会产生很多问题, 一方面会使得浏览器内存占用过高, 导致其他不相关的js逻辑操作进行阻塞或者失效, 表现就是页面卡顿或者无响应.
为了解决这个问题我们仍然可以使用虚拟滚动的方案或者懒加载的方案, 保证用户当前屏幕下的dom
在一个合理的范围内, 如果是无法避免必须要展示大段dom
元素, 我们可以用一个单独的页面来承载或者嵌入, 避免页面其他部分宕机. 也可以对复杂dom
进行局部“冷冻”(在非激活状态将其转化为图片, 激活时在逐渐渲染)
产品需求层面导致的重构主要场景比如:
当然还有很到场景这里不一一介绍了. 以上列的场景都是比较常见的, 而且也有很多解决方案, 后期我会一一复盘. 我们在项目重构之前或者立项之前, 这几种情况也是需要重点考虑的, 毕竟都是大工作量的任务.
技术升级带来的重构主要有前端框架的升级, 前端设计模式的升级, 脚手架的升级. 后面两个主要是围绕前端技术的不断演进, 我们采取的程序性升级, 比如从传统的 gulp
升级到 webpack
, 或者从 webpack
升级到vite
等. 前者比较常见的场景是企业中有很多老的系统, 采用的是比较传统的技术方案如 CMD 模式 + jquery
, 但是新项目采用的是 webpack + vue 或者 react
, 此时我们需要更新项目情况来有选择的做重构:
这种情况我们就不需要大刀阔斧的重新用新框架再写一套了, 我们只需要在重构时, 对老项目代码做好足够的注释, 类库的封装即可:
其次我们需要做好js
变量隔离, 因为传统模式我们会在 window
顶层定义大量 var
全局变量, 作为优化的一部分, 我们可以采用闭包自执行和变量约定来规范我的js
变量定义, 以防止全局的变量污染.
这种情况我们需要做评估和拆分, 如果是小模块, 我们可以用 jquery插件
的方式快速爹迭代, 如果是页面级别的迭代, 并且交互比较复杂, 我们可以将老系统的新页面拆离一个子工程, 采用最新的框架(如vue)来开发迭代, 再通过 MPA
的方式和老系统做集成:
3. 老项目和新项目需要相互通信, 嵌套
这种场景下最好的方式就是用iframe + postmessage
, 或者我们可以参考类似微前端的方式来管理组织不同子系统.
对于一个包含很多子系统的复杂的项目系统来说,要想设计一个好的架构,第一步就是合理划分组件,组件的粒度拆成的足够细,这样才能最大限度的复用组件。
对于任何一个复杂系统来说,最重要的就是实现错综复杂的业务功能,但是不同模块或者子系统之间很多业务往往是相通的或者相似的,如果这个时候我们每个页面对于实现类似的业务场景都去重复去写一遍业务代码,那完全是没必要的,对于可维护性来说也是一种打击,所以基于这种场景我们的 业务组件 就很有必要出场了。我们可以把功能或者需求类似的有机体封装成一个业务组件,并对外暴露接口来实现灵活的可定制性,这样的话我们就可以再不同页面不同子系统中复用同样的逻辑和功能了。
同理,不同页面中往往有可能出现视觉或者交互完全相同或者类似的区块,为了提高可复用性和提高开发效率,我们往往会基于基础组件和业务组件再进行一次封装,让其成为一个独立的区块以便直接复用。
通过这样一层层封装,我们就逐渐搭建了一套完整的组件化系统,基于这种模式的开发往往也是一个好的前端架构的开始。但要注意一点就是高层次的组件一定会依赖低层次的组件,但是低层次的组件不可以包含高层次的组件。(听起来有点像rudex的单向数据流法则),他们的关系就好像下图:
所以对组件库的重构需要对我们的项目有一个本质的认知, 并对页面进行有效的拆分, 从而达到局部的最优, 降低后续的维护成本, 并能提高整个系统甚至跨系统的复用.
有关如何从0到1教你搭建前端团队的组件系统 我之前也写过详细的文章, 大家可以参考学习一下.
系统重构是一个持续的过程, 我们不仅要有持续学习的态度, 还需要不断的实践和积累优秀的最佳实践, 这样才能在不断重构中让我们的系统不断适应复杂多变的“社会环境”.
本文由微信公众号前端瓶子君原创,哈喽比特收录。
文章来源:https://mp.weixin.qq.com/s/rKNowEdo1n-kUMy7CWBFiQ
京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。
日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。
据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。
今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。
日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。
近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。
据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。
9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...
9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。
据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。
特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。
据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。
近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。
据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。
9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。
《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。
近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。
社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”
2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。
罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。