前端重构实践(二) —— 模块化开发

简介:
  • 前言:

在上一篇文章中我介绍了我们对N产品性能优化的整个历程,主要偏重优化方法。本篇我将介绍在这一过程中,我们的代码出现了什么样的问题,以及我们是如何通过前端重构来解决掉这些问题,并产生了哪些收益。


  • 痛点

按需加载为我们的页面带来了很大的性能提升,但同时也为代码结构带来了很大的冲击,很多直接调用的方式被改为了模块化的调用形式(先判断模块是否存在,不存在就先加载对应的js,再执行回调)。

 

而js代码本身又不是模块化形式的。就使得代码结构很混乱,各种调用方式都存在,开发人员在写代码的时候不知道该直接调用还是模块化调用。

打包配置混乱,散落在各个目录结构中,经常出现重复打包和漏打包的现象,严重的还造成线上问题。

因为长期的产品策略变更,导致代码不同功能块之间耦合严重,一些关键方法不知道都在哪里被调用过,如果修改的时候有遗漏,就会出现问题。

没有文档。

没办法做自动化测试。

  • 思考

因为以上问题,我们每次产品升级都如履薄冰,需要非常小心谨慎,测试也很耗费精力。为了提高效率,我们必须要重构。

这次重构迫切要解决的问题有三点:

1. 代码调用方式统一,希望加载方式可以对开发人员透明。

2. 模块职责明确、模块之间依赖关系清晰。

3. 按需加载的配置可以统一管理,不影响开发时的效率。

这三点,让我很自然地就想到了JS模块化开发

  • 模块化开发:

关于模块化框架和CommonJS规范,在网上有很多介绍的文章,我就不在这里赘述了。我只说最关键的一点:每个模块都有明确的定义(模块名、输入、输出),模块之间的依赖和调用必须通过require或use的形式。如下图是一个common/pop模块的示例代码:


这种设计带给我们最大的好处是:规范了代码之间的调用方式,开发人员在写use的时候,不用担心这个模块是否已经被加载,所有的加载策略和打包策略都对他是透明的。

  • 模块依赖 & 自定义事件

如上面说到的,按照CommonJS规范,模块之间有require和use两种依赖形式,我们加入了第三种:fire(事件触发)。通过自定义事件的监听和触发,我们实现一种弱依赖的形式。

fire适用于投统计、异常处理等场景,不会触发代码加载。

  • 打包配置:

将以前分散在各个地方的打包策略合并到同一个配置文件中,如下图(示例代码):

它起到两个作用:1. 保证项目编译的时候将模块打包到对应文件;2. 在使用模块的时候,去检测它所在的js文件是否已经加载,如果没有则自动加载。

可以看到,我们对css也做了同样的模块化加载的处理。

  • 文件加载 & CSS模块化

对于按需加载的组织形式而言,文件的加载监控很重要。

早期我们对CSS做延迟加载的时候,碰到一个情况:由于这部分CSS加载是异步的,如果网络状况不好,就可能出现JS已经将页面元素组装好了,但是CSS还没加载完成,这一部分页面就会乱掉。后来我们采用了“先隐藏元素,等CSS加载结束再重写display属性来显示元素”的方法,避免了这种case。不过这毕竟不是一个系统化的解决办法。

如何鉴定文件加载的结束,特别是CSS文件的加载结束是个蛮有学问的事情。在框架中对于文件的下载监控,我们借鉴了SeaJS的思想,对于这块感兴趣的同学可以深入研究一下。

  • 整体架构

基础层是对一些基础模块和session数据的封装,这些方法每个模块都会用到,就不再做单独的require,打包成ctx变量传入每个模块的定义中进行使用。

应用层是具体的产品功能开发,对于数据的处理统一使用view/model/service的形式,由view从模板的textarea(性能优化考虑)中提取数据建立model,由service统一向server端发送异步请求进行持久化。

通用层是业务逻辑无关的组件,很多产品都可以复用,如分页、截字、弹层、类定义等。

物理层:通过config.js来统一配置按需加载的打包策略,并在模板中对编译加戳后的物理文件进行引用。

  • 代码文档:

既然每个模块都有统一的定义方式,模块之间的依赖和调用也有统一的形式,那么我们通过对代码进行自动分析,就生成了类似如下形式的代码文档

每个模块的依赖与被依赖、调用与被调用信息,一目了然。

开发人员利用这个文档可以清楚的知道他的每次修改都可能会影响到哪些模块。

QA人员可以根据每次提测的模块列表,评估出可能会影响到的case范围。

这对于开发和测试的效率提升不言而喻。

最重要的是,这是有生命力的文档,不需要维护,每次代码写完后就可以自动生成。

  • 单元测试:

按照模块化进行重构之后,我们可以针对单个组件写case进行测试。这里用到了Qunit框架。效果如下图:

  • 问题:

当然,模块化框架并非前端开发的银弹。我们在重构过程中也碰到了“不好调试”、“出现循环依赖后不好定位”等问题。这也是我们接下来要尝试解决的方向。

另外,重构后我们发现,框架本身和模块配置打包的代码,合并压缩后也有4-5k,这对于性能优化并没有太大的帮助。

  • 总结:

模块化框架对于按需加载、模块划分、代码复用、自动文档、单元测试、团队合作等都有很大的帮助。

本次重构规范了JS和CSS的模块化使用,让模块划分变得更清晰,让开发变得更单纯,为以后的升级维护奠定了一个很好的基础,提高了测试的效率,并且使得“单元测试”,“自动化测试”,和“敏捷开发持续集成”等 成为了可能。

本次重构还没有对HTML做模块化拆分,所以还没办法做到“模板的独立渲染”。这会是我们团队后续的工作方向之一。

by lizhouquan










本文转自百度技术51CTO博客,原文链接:http://blog.51cto.com/baidutech/1033712,如需转载请自行联系原作者

相关文章
|
7月前
|
存储 消息中间件 前端开发
PHP后端与uni-app前端协同的校园圈子系统:校园社交场景的跨端开发实践
校园圈子系统校园论坛小程序采用uni-app前端框架,支持多端运行,结合PHP后端(如ThinkPHP/Laravel),实现用户认证、社交关系管理、动态发布与实时聊天功能。前端通过组件化开发和uni.request与后端交互,后端提供RESTful API处理业务逻辑并存储数据于MySQL。同时引入Redis缓存热点数据,RabbitMQ处理异步任务,优化系统性能。核心功能包括JWT身份验证、好友系统、WebSocket实时聊天及活动管理,确保高效稳定的用户体验。
434 4
PHP后端与uni-app前端协同的校园圈子系统:校园社交场景的跨端开发实践
|
缓存 前端开发 JavaScript
利用代码分割优化前端性能:策略与实践
在现代Web开发中,代码分割是提升页面加载性能的有效手段。本文介绍代码分割的概念、重要性及其实现策略,包括动态导入、路由分割等方法,并探讨在React、Vue、Angular等前端框架中的具体应用。
|
8月前
|
前端开发 JavaScript 安全
|
10月前
|
JSON 前端开发 API
以项目登录接口为例-大前端之开发postman请求接口带token的请求测试-前端开发必学之一-如果要学会联调接口而不是纯写静态前端页面-这个是必学-本文以优雅草蜻蜓Q系统API为实践来演示我们如何带token请求接口-优雅草卓伊凡
以项目登录接口为例-大前端之开发postman请求接口带token的请求测试-前端开发必学之一-如果要学会联调接口而不是纯写静态前端页面-这个是必学-本文以优雅草蜻蜓Q系统API为实践来演示我们如何带token请求接口-优雅草卓伊凡
517 5
以项目登录接口为例-大前端之开发postman请求接口带token的请求测试-前端开发必学之一-如果要学会联调接口而不是纯写静态前端页面-这个是必学-本文以优雅草蜻蜓Q系统API为实践来演示我们如何带token请求接口-优雅草卓伊凡
|
12月前
|
编解码 前端开发 开发者
探索无界:前端开发中的响应式设计深度实践与思考###
本文将带你领略响应式设计的精髓,一种超越传统页面布局限制的设计策略,它要求开发者以灵活多变的思维,打造能够无缝适应各种设备与屏幕尺寸的Web体验。通过深入浅出的讲解、实际案例分析以及技术实现细节的探讨,本文目的是激发读者对于响应式设计深层次的理解与兴趣,鼓励在实际应用中不断创新与优化。 ###
385 10
|
编解码 前端开发 开发者
前端开发中的响应式设计实践
前端开发中的响应式设计实践
|
编解码 前端开发 UED
探索无界:前端开发中的响应式设计深度解析与实践####
【10月更文挑战第29天】 本文深入探讨了响应式设计的核心理念,即通过灵活的布局、媒体查询及弹性图片等技术手段,使网站能够在不同设备上提供一致且优质的用户体验。不同于传统摘要概述,本文将以一次具体项目实践为引,逐步剖析响应式设计的关键技术点,分享实战经验与避坑指南,旨在为前端开发者提供一套实用的响应式设计方法论。 ####
299 4
|
编解码 前端开发 UED
探索无界:前端开发中的响应式设计哲学与实践####
本文不拘泥于传统摘要的框架,而是以一种对话的方式,引领读者踏入响应式设计的奇妙世界。想象一下,互联网如同一片浩瀚的海洋,而网页则是航行其中的船只。在这片不断变化的海域中,如何让我们的“船只”既稳固又灵活地适应各种屏幕尺寸和设备?这正是响应式设计的魅力所在。通过深入浅出的探讨,我们将一同揭开它背后的哲学思想与实战技巧,让你的网页在任何设备上都能展现出最佳姿态。 ####
127 0
|
前端开发 JavaScript API
现代前端框架中的响应式编程实践
现代前端框架中的响应式编程实践
265 0
|
缓存 监控 前端开发
前端开发中的性能优化:策略与实践
前端开发中的性能优化:策略与实践

热门文章

最新文章

  • 1
    前端如何存储数据:Cookie、LocalStorage 与 SessionStorage 全面解析
  • 2
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(五):背景属性;float浮动和position定位;详细分析相对、绝对、固定三种定位方式;使用浮动并清除浮动副作用
  • 3
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(六):全方面分析css的Flex布局,从纵、横两个坐标开始进行居中、两端等元素分布模式;刨析元素间隔、排序模式等
  • 4
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(一):CSS发展史;CSS样式表的引入;CSS选择器使用,附带案例介绍
  • 5
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(八):学习transition过渡属性;本文学习property模拟、duration过渡时间指定、delay时间延迟 等多个参数
  • 6
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(九):强势分析Animation动画各类参数;从播放时间、播放方式、播放次数、播放方向、播放状态等多个方面,完全了解CSS3 Animation
  • 7
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(二):CSS伪类:UI伪类、结构化伪类;通过伪类获得子元素的第n个元素;创建一个伪元素展示在页面中;获得最后一个元素;处理聚焦元素的样式
  • 8
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(四):元素盒子模型;详细分析边框属性、盒子外边距
  • 9
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(七):学习ransform属性;本文学习 rotate旋转、scale缩放、skew扭曲、tanslate移动、matrix矩阵 多个参数
  • 10
    【面试题】20个常见的前端算法题,你全都会吗?
  • 1
    前端如何存储数据:Cookie、LocalStorage 与 SessionStorage 全面解析
    521
  • 2
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(九):强势分析Animation动画各类参数;从播放时间、播放方式、播放次数、播放方向、播放状态等多个方面,完全了解CSS3 Animation
    195
  • 3
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(八):学习transition过渡属性;本文学习property模拟、duration过渡时间指定、delay时间延迟 等多个参数
    192
  • 4
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(七):学习ransform属性;本文学习 rotate旋转、scale缩放、skew扭曲、tanslate移动、matrix矩阵 多个参数
    147
  • 5
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(六):全方面分析css的Flex布局,从纵、横两个坐标开始进行居中、两端等元素分布模式;刨析元素间隔、排序模式等
    252
  • 6
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(五):背景属性;float浮动和position定位;详细分析相对、绝对、固定三种定位方式;使用浮动并清除浮动副作用
    365
  • 7
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(四):元素盒子模型;详细分析边框属性、盒子外边距
    160
  • 8
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(三):元素继承关系、层叠样式规则、字体属性、文本属性;针对字体和文本作样式修改
    96
  • 9
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(二):CSS伪类:UI伪类、结构化伪类;通过伪类获得子元素的第n个元素;创建一个伪元素展示在页面中;获得最后一个元素;处理聚焦元素的样式
    162
  • 10
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(一):CSS发展史;CSS样式表的引入;CSS选择器使用,附带案例介绍
    228