近几个月我一直都在处理公司广告平台前端展示的代码。几个月下来见证着广告前端工程从无到有、从无规律到模块化、从技术架构到业务逻辑,收获颇丰,故此记录一下我与广告的点点滴滴。
一、事件起因:
我所在的房产网站有两条大的业务线(业务线甲、业务线乙 代替),分别由两个大的团队管理,基本没有交集。之前两条业务线都是用的广告方案相同(本文用老代码代替)。2015年初,由于这套老代码由于维护成本过高、与页面耦合高、并且稍一改动频频出bug等问题。广告组和业务线甲共同商议、打算在业务线甲首页改版之后,重构这套前端展示用的代码(本文中称为ad甲.js)并先由首页试用ad甲.js。
二、原来的老代码是什么样的?为什么要重构它?
广告在页面上展示是分广告类型的,每个类型对应多个广告位(实例)。我们通常是在页面布码(默认隐藏),页面加载后再用js动态加载。那么老代码是怎么做的呢?老代码中把向个广告位(id)中加入广告的行为封闭成多了立即执行函数,每个实例单独处理,没有类的概念。如果有相同的广告类型,就ctrl CV ;多人维护代码风格迥异;依赖页面中引入的类库。简单来说,就是以广告位为单位的多个js片段。那么这样的代码怎么使用呢?后台同学根据页面广告位的使用,将这些广告位分别打包成多个js文件,分别引用。对于一些可变的数据。就将js通过script标签吐到页面上,并通过PHP变量的方式修改展示用的数据。
显然,这样的结构对于前端同学来说是很头疼的,pv统计要分别copy到每个实例的js片段中、无法统一修改公用的部分、没有可复用的逻辑、大量使用with和eval函数、不仅js依赖页面环境,而且没有逻辑性、复用性、和可读性和统一性。看来老代码的重构是很难避免了。
三、临危受命、时间紧、任务重。
时间只有一个多月。在leader的指导下,我开始了这段代码的重构,也就是从这一刻起我与广告结下了不解之缘。
当然重构的不仅仅是前端代码。后端的逻辑也要变。原先的后台不仅要给js碎片打包,还要负责吐在页面中的广告数据。这样维护业务线甲的后端就和广告的后端耦合在了一起。新的架构中业务线甲的后端只负责页面相关的逻辑。而广告组的后端只提供一个能访问到对应于页面的Ajax接口。前端也变成一个专门处理广告渲染的js文件。
当然在这么短的时间下重构的代码虽说解决了不少的问题,但仍然有很多的不足之处,下一篇文章会详细说明。
四、前端代码重构之后的结构
1、单一的js文件
重构之后将原有的多个js片段改为一个js文件,业务线甲的每个页面只要引用同一个js文件就可以了。在加上一些config语句。这样js负责根据config中的变量判断是哪个城市以及哪个页面,并根据这些向后台获取广告数据。广告的渲染与广告数据解耦。使得数据与显示分离。每个页面对js的引用方式变得统一。
2、jsonp异步获取数据
在页面的config语句中获取页面的特征参数,异步的获取广告数据。当然这少不了广告组提供的ajax的接口。考虑到业务线甲和广告业务的服务器存在跨域的问题。我们采用jsonp的方式从广告的后端获取数据。通过1、2这两个步骤,广告的后端和业务线甲的后端就解耦了。
3、模块管理
使用requireJS和 对应的r.js打包,一些通用的工具函数也抽象成工具箱模块。将每个广告的类型分别定义成对应的模块。模块间也有了继承关系,我可以在父类处理一些统一的东西(比如pv统计),也可以在子类加入一些特性化的东西。
4、对页面的js库的依赖。
既然使用了requireJS,那么不妨将所需的依赖加入到工程,一同打包。就不需要每个页面都判断一遍了。比如jquery和underscore,相信我会经常用到里面强大的API。但不见得业务线甲上每个宿主页面都有这些东西并且是我想要的版本。
5、复用老代码中的特型逻辑
老代码中还是有很多的特性处理逻辑可以复用,由于时间比较紧,完全的重构也很有风险。我们可以拿来复用一部分,并封装成AMD风格的模块。
总结下来我们这一次还只是代码结构上的重构,很多的广告展示上的代码并没有完全修改,一开始提出的问题被一一解决。但是基本的结构有了,剩下的就一步一步来吧。
五、这条路还在继续
就这样,在短短一个多月的时间里我们的ad甲.js重构完成了。但是它仍有一些的问题需要不断地完善。目前也只是在首页加入ad甲.js,后期就要在业务线甲的全站对接未知的宿主页面环境以及各个页面带来的历史性的布局合理性问题,将不断的考验着我和我的广告前端代码。我与广告的故事还没结束。