这是个后续的故事,讲述的是一名电竞玩家转行程序历程与开发感悟。。。。。。
五,第3个电商项目(上)
家里的事情解决后,我又得重新找工作。当然,技术和经验又涨了一点点,同时一些互联网求职的经验也涨不少,不再向以前那样白痴痴地不调研市场行情就傻乎乎地投简历。我学会了通过内推或猎头的方式找项目,至少行情比自己投简历要好很多(大家别笑话,可能还有很多人木有意识到这点,特别是像我这种半路出家没有在很像样的互联网公司呆过的同学,这方面的意识是比较滞后的)。
2014年6月底,经过猎头推荐来到了一家化妆品起家的互联网电商。这个公司的业务规模很大,我进入的是一个会包含PC、H5、APP(安卓和IOS)等多端并行开发的海淘项目,进去的时候是以其前端开发主管的身份进去的。创始人是化妆品电商行业比较有名的,而且一直做的是电商,所以这家公司的互联网氛围还是比较浓厚,但也意味着快速开发迭代的节奏。我进入的时候项目的第一期已经上线,并且已经获得了千万美金级别的风投。
进去那天,上午是比较轻松的入职培训,下午熟悉项目,第2天上午就来了一个紧急需求——3个专题活动页面需要快速上线,隔天就得见到东西,因为项目投放了一个演唱会地推,线上必须在演唱会开始之前见到相应的推广活动页面。当时我所负责的组员有3个,也就是能干活的包括我,就三个人。好吧,那时我其实还叫不全两名组员的名字就大伙分工,一人一个页面,用原始的方式切切切,把东西弄出来。那天,我们三个前端、两个php以及一个测试的妹子(可能是姐姐)搞到了凌晨3点多。
这是我第2天上班的节奏,现在还记忆犹新。其实,真的有点被吓到了。那时候(其实才是去年,但电商的节奏让我感觉已经很久很久以前的事情了),项目的后台系统很不完善,运营使用的东西几乎没有,专题快速部署的系统当然也不会有的,那么前端的工作就被限制在一些生效效率极度低下的专题页面的开发上,而且技术含量不高,就只能靠人力维持。
随着项目的发展和投入的逐步加大,活动页面需求越来越多,人力维持是不太现实的,我们需要一个专题快速生产的系统。经过项目和产品需求分析后,务必要控制在2个星期内完成程序猿简历模板,而实际给到开发的时间其实只有1周。。。但主要工作其实对编辑器二次开发,后台编辑器上传图片时,可对图片进行二次修改编辑,我们二次开发就是要增加图片生成商品锚点定位、倒计时,甚至后来还提出了直接将锚点商品加入购物者的功能。这其实主要是前端的要啃下来的活,php只是从属配合,把生成锚点代码和展示配置保存到数据库。如果有人问我前端有什么需求值得去每个前端都去尝试,那么我会将web编辑器列为其中一个。当然,如果开发周期预计得足够长,一切难点都不是问题,难就难在限时实现,和参加奥数比赛类似。由于时间有限,项目经理帮我们找了个有类似功能实现的kindeditor编辑器插件,但是人家是加密了的,我们只能把代码扒了出来进行反编译,接入到我们的后台编辑器里面(ckeditor),接下来就是两个人接力coding,住了好几天7天连锁。这个编辑器项目总算如期交付,虽然后期有很多兼容性bug,但还都在可控范围内,解决了专题发布效率低下的问题,而前端开发也由此从手工维护专题的漩涡中解脱出来。我也因此在不到1个月时间内被列入了核心开发的岗位,并提前转正加薪(税前应该大于20K了)。
六,第3个电商项目(下)
项目需求迭代的速度并没有因为我们程序开发经常通宵,也不会因为某个人可能存在放弃的念头而会慢下来。这才是‘正常的“互联网电商的节奏”,因为去年开始做海淘的项目开始喷发,有点当年千团大战的感觉,如果你把节奏慢下来,可能意味着落后,一步慢就会步步慢。Boss发话说,我们第一期发版后的UI界面和性能体验不好,而好多页面的首屏加载速度箱单缓慢,甚至有白屏情况,让要我们尽快出台优化方案。其实,上线只有1个多月,前期又没有太多时间做基础设施建设,整套系统都是在一个相对完整的商业系统上二次开发而来,能有多少好的性能体验呢?但是,在民营企业里面,Boss的话就是圣旨。就得立刻响应和执行。于是,我们整个技术团队就对前端性能优化做了一次相对完整的评估,雅虎**条军规,出台了一些优化方案。这个方案实施,我提出了要响应快速的迭代需求,前后端模式需要建立起松耦合的开发协作体系。
其实,这个时候阿里前后端开发体系的一系列文章才出来几个月,对于业界的影响还是有的,至少这个项目来自后端开发的传统程序员基本能接受这种开发思维,但是问题是如何建立?对于一个已经在线上跑的项目,彻底的打翻重构是不现实的。我又一次面临了一个有难度的前端模块化工程化、前后端分离开发体系建立的需求。但这次不同,这个项目代码规模更大,业务更复杂多变,而且一直是高速运行的。入职后的1个多月里被专题和编辑器羁绊住了(中间还请了一个星期的假),网站的其他业务其实我没有太多精力去顾及。
在电商这个领域,解决前后端耦合的问题,主要要做好服务端模板层的规划,控制权尽可能只压在前端或后端,多方维护的情况尽可能减少。以PC端为例,这里是要求SEO的,那么页面的渲染必须在服务端完成。当然,这里会涉及页面性能优化和前端资源调度的问题,服务端模板层最好是由前端团队来掌控。然而,不是每个前端开发人员都是懂后端语言的,这个其实是提高了前端人才的准入门槛,但这又是必须的。至少我前面几个电商项目都是这种情况,其他电商的做法就不清楚了。这里简单说我们的做法:
1,服务层按功能分层、分域,服务端view层独立开发域。比如,核心底层基类分出一个开发域,通用函数或组件也可以一个开发域,后台各种管理运营或配置系统划分为不同的域,而前台的,比如首页、列表页或专场、搜索、详情、购物车、登录注册找回密码、会员中心也可以分别各一个域。此外,即便是服务端模板层的开发语言,前端团队没能力决定,也至少单独一个开发管理的域。这是前后端松耦合的关键。当然了,不是各种开发域分得越细就越好,务必要根据按开发团队的人数以及实力来确定。如果分的太多太细了,代码合并管理的重复量会提升。每个人可能同时负责好几个域的开发,解决了代码耦合,但却降低了开发效率,而且增加系统间联调的风险,这是不合理的。
2,对服务端模板层进行公共页面、组件抽象。比如全站的很多头尾部是共用的,变化的部分相对较少的,进行公共文件剥离和抽象。垂直类电商一般是以页面为颗粒度的,页面展示大多以大块大块的图文列表出现,太精细的抽象是没必要的,至少我所负责的项目大抵如此。其他大众类电商因为要展示的商品种类多,页面可能会做的非常细腻,以更精细的页面组件来组织view层代码结构才会显得有必要。
3,开发前端静态资源调度机制。为什么要做这个事情?这个问题我就详细展开了,太多了。理论层面的,可参考大公司里怎样开发和部署前端代码? - 前端开发当然,因为业务不同,我们有自己实现机制。
4,我们遇到的问题——TTI延迟引起的前端构建框架重构前端模块机制是建立在requireJS基础上的,但之前我做的是异步的方式,在以前的项目中其实对于性能优化没有那么苛刻,但是这个项目不一样。是当前竞争最惨烈的一个垂直领域——海淘。
因此,任何一个可以改善用户体验的优化,对于项目的意义都是巨大的。从用户体验出发的几个核心时间指标包括:Start Render、DOM Ready、Page Load、TTI。不同的性能指标对用户体验的影响是不同的,而指标本身受哪些因素的影响也是不同的。一般的前端优化都会考虑前面三个的优化点,而最后的TTI优化往往被忽略。我们却碰到了必须解决这个问题的点,业务场景发生在需要加入购物的按钮上,比如详情页的下单按钮,比如这页面 :
如上图所示,两张页面是加载先后的两次截图对比。当用户打开页面时候,页面结构的渲染很快就完成了,但一些异步的请求较慢,SKU的计算也需要耗费一些时间,但问题用户可以看到加入购物车的按钮啊,大红色的很吸引人,让人点击的欲望是很强烈的。但是,有些时候网速稍微卡断一点,那么这个加入购物车的按钮就一直点击不了的。很多小白用户就可能会问,为啥不能点击加入购物车啊?
我敢肯定一定有这样的投诉,只是看网站开发者如何对待这个问题而已。这个就是典型的TTI问题。什么是TTI? 简单的说,Time To Interact指的是页面可交互的时间。这个应该越早越好,如果页面因为需要等待异步请求的结果才能计算,而异步的数据可能是回不来的,那么就不要让用户可以这么快地看到可交互的元素,因为它会吸引人去点击,但却没有响应,投诉就必然。当然,这个问题发生在我们的网站很多地方,比如详情页、购物车以及生成订单的页面,要知道这些页面的交互分分钟对转化率产生影响的。然而,采用requireJS异步请求模块的方式,这个TTi问题就会更加突出。因为页面首次渲染会发生在css加载完成之后,如果不做任何处理,加入购物车的按钮就会很早呈现在用户面前而触发用户去点击,但由于页面一方面要等待异步的js完成,还要等js发起的ajax请求返回的数据做进一步处理,即便是我们对按钮做loading状态处理,但require异步的js可能会发生很多意外,页面的购物车按钮区域一直在loading,而导致用户无法点击加入购物车。
也就是说,我们用requireJS框架代码的模块化管理,但却不能在生产环境中直接使用它的异步机制,因为它会对TTI延迟带来影响。到这里你可能对js模块化有些很反感,有这么多毛病干嘛还要模块化啊?这个问题很深刻,但问题不能单纯从一个角度看待,任何事物都是有两面性的。其实,如果用其他模块化方案,只要是异步加载js的,都会存在类似的问题,包括seajs。要知道模块化开发一定是团队配合的必然选择,既然已经选择了requireJS作为模块化机制,那么它带来的问题,我们就要着手研究解决方案。
5,前端模块化开发与TTI延迟问题的解决首先,我们的前端团队已经熟悉了requireJS,基本都能掌握AMD模块开发要点。首次重构的代码已经发布上线后,必须先将TTI问题严重的几个页面,做loading状态处理,让用户等待。但这只是过渡方案,更优化的解决方案是要对前端开发构建流程做优化调整,把异步的模块在发布生产时必须合并起来,作为同步加载的模块,放置在页面最底部,而且合并的文件应尽可能降低代码的冗余。但是页面js资源不仅仅只是优化一个页面,将一个页面combo成一个模块就完事了,应该想服务端模板一样,js也要分层,将最底层最核心的类库抽离出来单独combo程序猿简历模板,多个页面之间共用的模块也要单独combo(这种形式的combo结果可能有多个,因为如果共用模块过多,按一定的大小来合并,我们的原则是mini化之后不能不要超过200K一个文件,如果超过了,就要另起一个文件,当然,这个要灵活处理),前面两者是在页面之间可以相互继承的,而只有当期页面私有逻辑的js模块则应该是一个单独的模块。那么,网站js最终的形式可能是这样的:
这是我们希望得到的模块combo结果。我们采用的线下combo,然后将combo的结果发布到CDN,这样就需要解决以下的一些列问题:
1,如何区分核心js和页面共用js?
2,构建流程上如何解决它们的修改,然后编译的版本迭代问题?
3,对于开发的角度,在本地开发能够快速调试,包括源码调试以及combo状态调试?线上的问题代码,如何方便开发人员调试?
4,私有模块化如何调用共用模块的方法,或采用怎样的机制来对共用模块进行单独的实例化?
5,多个模块化之间,combo的先后顺序是什么?6,内嵌资源比如img图片引用,如果引用的图片发生了修改,如何解决它的缓存问题?
7,如果业务模块很多,比如好几百个(电商的业务很容易达到这样的量),那么可能因严重影响代码发版的速度,是不是考虑增加构建的缓存机制,或服务端combo的机制?……好吧,这些问题最终演变出来的,其实就是一整套环环相扣的前端工程化解决方案。这里面,单独就js而言,要涉及很多代码规范问题,比如js通用模块开发标准,私有模块开发标准,私有模块提升为公共模块的机制,第三方插件的改造规范,js模块的碎片化程度如何掌握?这是一个度的问题,等等。
因为加入CDN网络后的,强缓存解决方案是更换URL路径,而对于访问量大一点的电商来说,非覆盖式发布是最佳的选择。
前端架构的开发机制还会涉及服务端模板引擎的如何加载前端静态资源的问题,如果是纯静态的移动端网站优化,可能还需要你自己设计一套开发机制以及静态html开发的具备模块化能力的模板引擎,来解决动态变化的css或js引用问题以及开发调试的体验问题。好了,这其实是业务逻辑开发以外的,高阶前端开发者需要面临上述的前端痛点问题。这会涉及方方面的调整,比如前后端边界的处理,前后端交互的API规范,开发调试环境、测试以及发布流程的设计,版本迭代回滚,以及性能监控等等一些列衍生问题。
我可以负责任地告诉,不同的项目,前端架构设计是不太一样的,因为业务逻辑不同,前后端开发人员配比以及能力模型也不同,那么前端架构就可能得采用不同的设计方案。当你的业务发展要面临这些问题时,可能前端就没有大家想想中那样简单了?
“一叶障目不见泰山”
“前端说白了只是语法糖,一种编写页面的容器api和程序语言的封装,是计算机发展的大树长出的小枝桠。”
对于这句话,老铁们,你们怎么看呢?
未完待续......
今天看到有很多评论的同道中人(无论你是刚刚接触还是从业了,都可以算同道吧),到此刻今天的文章给就到这里,有时间的话我会坚持给大家更新文章,如果对你有所帮助,可以多多转发和关注,初学者有什么不懂的可以私信我,,欢迎留言评论和私信。【私信方法】文章上方处点击“作者头像”,进入作者首页,在作者主页上方点击“关注”旁边的“发私信”即可。