前端网页就是这么简单,除去图片、视频等资源外只有三部分,即标记网页元素的HTML、设置元素样式的CSS和负责交互处理的JavaScript。
在软件开发上,普遍认为架构设计能把复杂的工程代码分解成相互耦合度较低的模块,规划整个工程。简单地说,在大多数人的认知里,架构设计是为了分离代码而存在的。更直接地说,架构设计就是为开发人员分工而存在的。而前端网页是天然按照单个网页解耦的(即网页与网页之间是独立的),在大多数的前端工程中,一个网页的复杂度刚好适合一个人的工作量。基于这样的认知,前端网页确实是不需要架构设计的,因为绝大多数的前端工程不存在分工的问题,每个前端工程师分几个页面就完事了。
而事实上,前端网页的复杂度已经逐渐超出控制。在一些稍具规模的网站上,需要由几十甚至上百个页面组成;在一些复杂的网页中(如在线画图,在线剪辑视频),也需要由几十甚至上百个小模块组成。在大型网站的前端工程里,如果没有架构设计,任由开发人员自由发挥的话,一定会出现代码高度混乱和高度冗余的情况。这种情况是危险的,很大程度上会造成项目进度失控或运维成本过高等状况。
再者,软件架构并不是仅仅为了分工而存在的。架构是软件整体结构的抽象描述,是一个软件的基本思想,而分工只是结构抽象带来的附加好处。
而基于这样的认知,所有软件(包括前端)都需要架构设计。但是如果网站只有几个页面,并且没有任何扩展需求,此时还要大费周章地去做架构设计,就相当于牛刀宰鸡了。
因此,在具有一定规模的前端工程中,是需要架构设计的。而前端架构,一般需要解决4个问题来提高前端网页的质量和性能,即规整化、适配性和兼容性、模块化、单页应用。
由于前端页面的易学性,导致很多前端开发工作都是由其他软件工程师兼职的。即使一些专职的前端工程师,有相当一部分也没有系统地学习过前端开发,所以前端代码中会出现各种各样的编写习惯,很多代码细节也过于粗糙,导致源源不断地出现各种小问题。
由于前端的代码在网上很容易找到,因此一些前端工程师会东找个例子,西找个例子,然后简单地把代码放到一起,顶多再模仿着写几行代码或者在例子中修改几个变量,这样就算完成一个页面了。像这样在很多代码细节还不清楚的情况下,直接把代码堆到一起,看起来是很快就完成了一个页面,但是一旦出现问题,便需要花很长的时间去“尝试”出问题的位置,大部分情况下这种行为是得不偿失的。
由于网上有很多网页模板,看起来还很不错,因此一些工程师便使用这些模板稍稍改动就算完成页面了,导致整个网站是“色彩斑斓”“五彩缤纷”。
但是到网站发布前UI风格整顿的时候,网页修改的工作量和重新做一次没什么两样。
由于JavaScript语法的开放性,夸张地说,100个人用JavaScript就会有100种编程语言。越大的前端工程,越多的前端工程师,前端工程也会越混乱。
以上,浮躁地忽略学习过程、随意地抄袭代码、偷懒地使用网页模板、一人一个样的语法使用习惯和低估了前端工程的复杂性,这些都造成了前端结构极度混乱和代码高度冗余的局面。虽然看上去功能是完成了,但是一旦发生Bug修正、需求变更、UI改版、交互方式变更等情况,都会出现工数和风险完全不可控的局面。
很多人可能会认为,前端是天然按照单个网页解耦的,混乱是可以控制在一定范围内的。但是,前端工程除了网页标签以外,往往还有CSS样式文件和JavaScript脚本文件,这些文件是可以无限制地被多个网页引用的。混乱的前端结构如图3.16所示。
由此可知,在混乱的前端工程内部,其实并不是天然按照单个网页解耦的。所以混乱其实不能天然被控制在一定范围内。
图3.16 混乱的前端工程结构
更可怕的是,这种不好的前端编程行为会遵循破窗效应,会感染到其他的前端工程师,甚至整个开发团队。因此,前端架构第一个需要做的便是规整化,制定一些规则,以达到约束整个前端开发过程的目的。
首先是适配性。现在的显示设备多种多样,前端网页的显示也不仅仅局限在PC浏览器当中。更多地,手机浏览器、某些嵌入网页的App、平板电脑、电视,甚至是巨屏,都可能需要显示前端网页。这些林林总总的显示设备,分辨率、长宽比各式各样,交互方式也不尽相同,而前端页面对这些设备的适应性,就是适配性。当然,网页不需要适配所有的显示设备,很多情况下,PC的网页和手机的网页都会分开实现。但是即使是只需要在PC浏览器显示的网页,也需要有一定的适配性,因为PC显示器的分辨率不尽相同,浏览器的窗口也可以随意缩放。
因此,前端架构应该考虑网页的适配性。适配性做不好的网页,很容易产生一些页面错位等用户体验不好的状况,这种山寨的感觉会影响用户对网站的第一印象。网页需要适配的多种设备如图3.17所示,但是在一般情况下,网页不需要适配所有的设备,只需要适配选定的设备种类即可(如PC版网页、移动端版网页)。而对大型网站而言,大屏展示端不是必需的,但是PC端和移动端的适配需要充分对应。
图3.17 网页需要适配的多种设备
其次是兼容性。除了多种多样的显示设备以外,浏览器也是各式各样的,这些浏览器即使都支持HTML 5,但有些CSS样式配置和一部分浏览器API也是不一样的,而前端页面对这些浏览器的适应性,就是兼容性。目前比较流行的浏览器有Chrome、Firefox和Safari,当然还有很多其他浏览器,它们的内核大多数和Chrome是一样的,所以兼容了Chrome、Firefox和Safari就相当于兼容了所有现代浏览器。而兼容性最大的挑战莫过于IE了,IE 9以下版本不支持HTML 5,IE 9、IE 10、IE 11虽然支持HTML 5,但是都不太友好。当然了,也不是要让网页兼容所有浏览器,毕竟兼容浏览器带来的工作量和测试量也是不小的。
因此,前端架构也应该考虑浏览器的兼容性。网页需要适配的多种浏览器如图3.18所示,这里忽略了一些用户量不大或者没有独立浏览器内核的浏览器,如360浏览器、搜狗浏览器、百度浏览器、小米浏览器、华为浏览器等。
市场上浏览器很多,每个浏览器的不同版本之间也有区别,但一般情况下,网页不需要兼容所有的浏览器,现在很多网站都放弃IE 6~IE 10了。对于大型网站而言,由于用户使用的浏览器不集中,所以还是要尽量兼容足够多的浏览器。
图3.18 网页需要适配的多种浏览器
在前端的开发过程中,很多时候我们是在做重复的事情。例如,A页面需要一个播放器,B页面也需要一个播放器;C页面有一个视频列表,D页面也有一个视频列表,如图3.19所示。诸如此类,页面与页面之间,会有很多类似的,甚至相同的部分。
图3.19 网页与网页间相似的部分
面对这些类似的部分,比较原始的方法是直接复制代码。这种方法很直接,但是复制的代码需要重新调整和重新调试。如果复制的是其他人编写的代码,调整时间会更长。如果需要调整所有这些复制代码的话,这个过程将会是相当无趣的。
现在,前端部分流行组件化,出现了如Bootstrap等前端组件工具箱,可以很简单地画出列表和导航栏,以及一系列通用的页面组件。这些组件工具箱确实能帮助我们在UI描画时省点力气,但是,组件工具箱一般只是对HTML默认标签进行了美化或者扩充,其无法提供现成的业务模块(例如图3.19中的视频资源列表)。
其实,我们希望的是把这些通用的业务模块做成独立的部分,各个网页通过简单地调用即可把这些业务模块拼接进来,就像搭建积木一样,如图3.20所示。这个就是模块化,相同部分只有一份代码。
图3.20 网页与网页间相似的部分
传统的网站会不断地跳转页面,例如单击搜索后会跳转页面,单击翻页后也会跳转页面。一旦出现跳转页面,用户就需要等待重新加载页面后才能继续操作,如果在网络不好的情况下,这种等待的体验是糟糕的。为了改进这种糟糕的体验,单页应用(Single Page Web Application,SPA)的概念开始流行。单页应用是指在浏览器中运行的应用,其在使用期间不会重新加载页面。
简单地说,单页应用是把多个页面合并成一个页面。传统网站与单页应用的对比如图3.21所示。
更简单地说,单页应用是只有一个前端页面的网站,浏览器一开始会加载必要的HTML、CSS和JavaScript文件,之后所有的操作都会在这个页面上完成。以翻页操作为例,JavaScript脚本会向服务器请求翻页所需要的数据,数据返回后,JavaScript脚本会进行DOM操作,修改页面显示的内容,如图3.22所示。因此单页应用只是刷新列表而不是重新跳转页面。
图3.21 传统网站与单页应用的对比
图3.22 单页应用的翻页操作
单页应用能避免页面跳转的发生,提高用户体验,但是单页应用也有不好的地方。由于单页应用是把多个网页合并成单个网页,所以这个网页的内容是相对庞大的,JavaScript脚本的内容也是复杂的,导致了单页应用加载网页资源的时间会比较长。如果把整个具有一定规模的网站做成一个单页应用(想达到App或者桌面软件的效果)的话,那将会是一个很不理智的行为,因为每次打开页面都可能要花上五六分钟,配置差一点的机器甚至会造成浏览器崩溃。
因此,前端架构不要极端地把一个网站做成单页应用,而是需要适当地使用单页应用,权衡哪些网页需要合并成一个单页应用,哪些网页则必须要分离,如图3.23所示。
图3.23 单页应用和多页跳转结合