“我们活得好好的,为什么要工程化?”
让我们从原始的前端开始。用记事本新建一个卡哇伊的a.html页面,给它点样式a.css,DUANG加特技a.js。无须编译,本地预览,OK,没问题,上传服务器,等用户访问。哇,前端好好玩,好简单有木有?!然后,我们访问页面,效果还行,再看下网络请求,200!完美!
等一下,还没完呢?小公司到这儿就OK了,数据上上去,没兼容问题,完美啊!大公司说:注意性能,我要访问量!不好玩了吧!看看a.css的请求,如果每次用户访问都要加载,是不是很影响性能,浪费宽带啊!如果网络请求状态是304就好了!304,本地缓存!
这回成了吗?不行,304是协商缓存,还是要和服务器通信一次。于是必须彻底灭掉这个请求,那么强制使用本地缓存,不要和服务器通信。那么问题来了:都不让浏览器发资源请求了,这缓存还咋更新呢?对,更新页面中引用的资源路径,让浏览器放弃缓存,加载新资源。问题解决,完美!
大兄弟,别慌呀!现在a.html上面只有一个a.css,带上版本参数来改变资源路径,OK。假如还有b.css、c.css,某次上线只改了a.css的版本,通用的路径生成器上将全部版本都改了,那岂不是又有浪费了。这样一来,要解决这种问题就必须让版本修改和文件内容关联,才能准确地对应资源版本。什么东西与文件内容相关呢?大佬们想到利用数据摘要算法对文件求摘要信息,这就有了一种可以准确到单文件粒度的缓存控制依据了。好了,将版本改为摘要信息。
这回完事儿了吧?Too young too simple!想喘气?没门儿!现代互联网企业为了进一步提高网站性能,会将静态资源和动态网页分集群部署,静态资源被部署到CDN节点上,网页中引用的资源也会变成对应的部署路径。好了,部署好了,当更新静态资源的时候,也要更新html中的引用。现在同时修改页面结构和样式,要发布代码,是先上静态,还是先上页面?先部署谁都有问题:先部署页面,有用户访问就会出现样式错乱,静态还没部署;先部署资源,页面执行同样错误。怎么办?蹭用户不注意的时候偷偷上线?大厂的网站用户访问可没准儿啊!
这个奇葩的问题起源于资源的覆盖式发布,解决它就采用非覆盖式发布。用文件的摘要信息对文件进行重命名,这样就变成一个新的文件发布到线上,不会覆盖已有的资源。上线的过程中,先全量部署静态资源,再灰度部署页面,整个问题完美解决。所以,大厂的静态资源优化方案,基本上要实现这个几个东西
- 配置超长时间的本地缓存——节省宽带,提高性能。
- 采用内容摘要作为缓存更新依据——精确的缓存控制。
- 静态资源CDN部署——优化网络请求。
- 更新资源发布路径实现非覆盖式发布——平滑升级。
“我们公司业务用不着工程化!”
前端工程化是技术发展的必然趋势,虽然它并不那么尽善尽美,但毕竟已是主打,在未来的发展上也会更加完善。这也有一个很实在的问题,在很多公司看来前端工程化在他们的业务上是没有必要的。比如,开发中小型企业网站的公司,他们设计、开发做完一单就不会再有迭代。再比如,游戏网站,官网更新迭代也不那么频繁。在他们看来,无论从技术层面还是从投入产出,这都是没有必要的!
我认为这并不是绝对的。中小型企业网站的设计开发总的来说是有规律可循的,这就代表可模块化。有时候懂得投入才会得到更好的回报,即便这些小公司不做,也会有人去做。社会在发展,时代在进步,程序员也在进步。用稍微偏激一点的思维来看:当大家都只写静态页面的时候,那么拥有更多实践经验的多一些报酬无可厚非;当大家都在用框架来做页面的时候,能多拿报酬为什么不去做?
之前待过一个公司就是这样,做的是电信的业务。也会涉及公众号的开发,很多公众号开发一部分就交出去了,不会迭代。自己维护一个公众号,还有一些活动支撑,前端把静态写好了,剩下就靠后端开发来完成。这样存在什么问题呢?前端按着自己的逻辑去做的,后端不知道前端什么逻辑,最后出来的效果和产品想要的不一样。前端说我做的没毛病呀,后端说我做的也没毛病呀,结果一看代码:前端要保留一个div,判断条件得写到div里面去。这样的情况太多了,前端本来就没什么逻辑,除了JS效果,太多人不大会去写注释。问题再严重一点就是互相丢锅,数据显不出来,大家都不想管,这是沟通成本!
还有一个问题,前端只管静态页面,相当于就是前端不懂后端代码,也就不能给他们开代码管理权限。BUG来了,有时候确实加上后端代码后会出现一些毛病,前端本地代码看没问题,只能到后端那儿去调试。赶巧,后端也很忙啊,没时间怎么办?明明是多线程的任务,活生生搞成了单线程阻塞任务。另外,前端将代码传给后端,后端上传服务器这也是时间成本。关于这一点,倒是可以通过分配代码上传权限解决,毕竟静态资源和后端渲染代码分离。线上的效果只有后端拉取静态后才看得到,这儿也存在沟通成本。
无非就是沟通嘛,大家合作一段时间,磨合磨合就好了嘛。真的只是磨合那么简单吗?前面说了,公司维护一个公众号,还有一些活动支撑。一个公众号只要不改版,基本没有太多的事,大多数时间就是在做活动支撑。突然有一天,产品说要改版,而且给的时间紧。要做活动支撑,还要进行迭代,怎么办?我想最好的办法就是将人力集中调度起来:小部分人支撑活动,能往后延的往后延;大部分人主要做迭代支撑,任务少的完成后接活动支撑。当然,不加班,任务完成了,大家都很开心。
有一天,产品说:样式不统一,要统一样式。样式怎么不统一了,全是蓝湖上复制的样式。其实也确实有可能不统一,因为设计师在做之前没有预先做UI库,同样的版块会存在间距,字体大小稍微有点差异。对于组件化的前端自然没有问题,可惜不是啊,这怎么弄?没法弄,几个人同时开工赶出来的,每个人的写法都不一样。只是统一几个相同组件还可能,要标题字体大小、段落间距之类都要做到,这肯定不行,还干不干别的了?就算前端做到了,后端怎么办?页面都写完了,挨着换样式,还只能在开发那边换,还干不干别的了?
其实,在很早之前就有人给老大提议改为前端工程模式,老大说:我们的业务用不着这种技术!原因很简单呐,核心全部掌握在后端开发手里,老大只懂后端,就不怕核心流失。用框架之后就不一样,如果前端技术流失,那么新来的人就得有一个学习的过程。如果核心前端流失,那么新来的人需要更久的时间去熟悉。再加上前端主要工作是静态支撑活动,最重要的是只会写静态没什么技术含量,便宜啊!他怎么会知道样式统一是个什么概念。即便是一开始就有足够的时间去统一样式,那么对于后来维护的人也是苦海无涯。前端流失之后,新招的人对之前的统一样式也会视若无睹。试想,都没技术含量了,还会有技术文档这种东西么?!
重点来了,老大以为业务用不着就不用,可是人往高处走啊!陆陆续续前端主力都走了,走就走呗,又不是招不到人,对吧?!嘿,还真招不到人!包括刚培训出来的新人,也不行!第一,现在的主流技术是框架,谁不想以后混好点,那么起码也得用框架吧!第二,只是做静态切片和一些效果能给多少,不可能比用框架给得多吧,技术含量在那儿呀!第三,按着老方法,UI不包切图,前端新人出来偏要UI给图,总有人不乐意,不同的活儿得给不同的话说!综合这三点,新招的前端都是学的新路子,还在走老路的技术恐怕用新手价很难招到咯!当然,这话不能太绝对,毕竟还是有人仅仅为了体验生活!
“前端工程化,启程!”
构建前端工程化目的就是将一些繁复的工作优化,比如图片拼成sprite图、图片压缩、样式压缩等等。像这类机械化的工作靠人工来处理,枯燥又浪费时间。所以,工程化并不是针对业务那么简单,它解决的是前端开发中的自动化、性能优化、模块化、开发规范、代码部署、开发流程等等问题。它让代码的维护和相互协作更容易更方便,同时解放生产力,提高开发效率。
一提到前端工程化,有人立马联想到Vue、React这类框架。我认为这得根据企业自身的业务需求来进行技术选型,是用Vue、React这类前端框架,还是只用Ant Design这类UI库,甚至只用jQuery。合理的技术选型可以节省许多工程量,比如管理系统用得特别多的Bootstrap,相对于纯手工要效率得多。尽管如此,作为技术始终要关注前沿的是什么,否则就会落后。
进行了技术选型就开始敲代码了?开发效率相对刀耕火种是进步了,要不要在性能上照顾一下?对代码进行压缩、校验、管理,对资源进行合并、压缩,这就需要选择一种或者多种构建工具来进行处理。既然我们在代码上有这么多工作要做,那么总得给前端一个代码管理方法吧。在不少公司都不把前端当程序员,就是一个切片的,他们连svn或者git账号也分配不到。每写完一套就全靠IM工具传给后端开发,这是多么悲催的事情!
技术选型也就决定了工程化的技术复杂度,如果就是基于jQuery来做一套东西,哪还管什么模块化。模块化的工程意义主要不是复用,而是不管将来是否复用这个模块它能很好得到维护。在大工程面前,前端的页面非常复杂,动辄几十上百人共同维护开发,模块的分治在维护上尤为重要。现今技术手段越来越丰富,JS模块化有AMD、CMD、UMD、CommonJS、ES6 Module等等方案,CSS模块化有less、sass、stylus等预处理器。尤其是Node的出现,不仅可以用JS写服务端,还将模块化、构建工具联系在一起形成了丰富的前端生态圈,从而达到重复的工作自动化。
对于大型项目来说,只是模块化还不够,还需要根据实际需求进行组件化,将UI进行拆分。这样做一是便于维护,二是便于组装复用。不同的技术选型决定了不同的组件封装和调用策略。这样一来,对于整个工程来说,项目初期进行规范化是十分重要的。
虽然前端工程化在工程问题较多,但相较刀耕火种时代思路更清晰不是吗?