7月阅读周·前端架构:从入门到微前端 | 架构设计:多页面应用
背景
去年下半年,我在微信书架里加入了许多技术书籍,各种类别的都有,断断续续的读了一部分。
没有计划的阅读,收效甚微。
新年伊始,我准备尝试一下其他方式,比如阅读周。每月抽出1~2个非连续周,完整阅读一本书籍。
这个“玩法”虽然常见且板正,但是有效,已经坚持阅读六个月。
已读完书籍:《架构简洁之道》、《深入浅出的Node.js》、《你不知道的JavaScript(上卷)》、《你不知道的JavaScript(中卷)》、《你不知道的JavaScript(下卷)》、《数据结构与算法JavaScript描述》、《WebKit技术内幕》。
当前阅读周书籍:《前端架构:从入门到微前端》。
架构设计:多页面应用
单页面应用,是指只有单个Web页面的应用,它通过动态重写当前页面来与用户进行交互,而不是通过远程服务器来加载新的页面。对于那些从远程服务器加载新页面的应用来说,由于它存在多个页面,所以为了方便区分,我们将其称为多页面应用。
为什么不需要单页面应用
而如果单纯从技术的角度来考虑这个问题,原因是:
- 构建单页面应用的成本很高。
- 前端生态快速发展,学习成本高。
- 单页面应用对SEO(搜索引擎优化)不友好。
- 应用架构更加复杂。
构建成本
当使用单页面应用的时候,我们要考虑使用哪个框架,使用什么语言和技术栈,还需要考虑是否分离前后端。而不论是否分离前后端,我们的应用构建都会变得相当复杂。除了需要在本地处理构建流程,还需要在一台公用的服务器上运行构建(如持续集成服务器),以提供最后用于发布的软件包。一旦框架本身提供的构建流程不符合我们的需求时,我们就不得不花费大量的精力在重写构建脚本上。
学习成本
前端在过去的几年里经历了快速的发展、变化和更新。由于技术变革过快,所以今年使用某版本框架编写的应用,在明年可能就不再被支持。这个时候,回过头去看旧的应用,就变得非常陌生。我们不仅要学习新的框架,又要学习旧的框架。
当未来的某一天,又出现一个新的框架,它能解决旧的系统中的一些问题时——这些遗留问题持续地影响了我们的开发进度,如果能替换它们有助于效率的提升。我们写了一个又一个demo,又对一系列的指标进行测试,发现它能满足需求。于是计划使用这个框架,在切换框架的过程中遇到的第一个问题是框架的学习成本。特别是当我们使用“大而全”或“小而美”的框架时,学习成本很高。
后台渲染成本
如果是单页面应用,就要考虑使用额外的方式来支持:
- 预渲染,即面向搜索引擎提供一份可以被索引的HTML代码。
- 同构应用,由后端运行JavaScript代码生成对应的HTML代码。
- 混合式后台渲染,由后端解析前端模板,生成对应的HTML代码。
如果交互不复杂,那么反而不如多页面应用来得简单——直接进行后台渲染提供一份HTML。因此,如果交互少,那么使用多页面应用就显得更加合适。
应用架构的复杂性
单页面应用不仅带来了前端开发的变化,还带来了后端开发的变化。
架构方式变成了前后端分离架构。原先,业务逻辑的处理基本都交由后端来完成,而现在数据处理的逻辑则部分交给前端,尤其是数据的展示部分。为此,后端需要提供一个又一个RESTful API,将控制权交由前端进行交互,后端则将数据的展示部分解耦出来。这也意味着,后台的数据通过API直接暴露在所有攻击者面前。在设计的时候,我们不得不更加仔细地考量某些字段要怎么展示,是否采用二次请求的方式来完成等。
复杂的应用,则会进一步孵化出BFF(服务于前端的后端)层,在这一层针对不同的客户端提供不同的API。这样的中间层,可以明确职责,但也让架构变得复杂。
简单多页面应用的开发
多页面应用往往是一些轻量级的前端应用,多数时候会被划定为“前端页面”——往往只需要编写页面样式,即编写一些JavaScript就能完成工作了。
选择UI库及框架
在多页面的时代,由于前端应用的简单化,几乎大部分前端团队都拥有自己的前端框架和UI库。因为在这个时期,自己编写、维护一个前端框架和UI库是一件容易的事。
复杂的单页面应用几乎都采用了主流的前端框架——对于一些大型机构而言,仍然会存在自己的单页面框架,它们有足够的能力去维护这样一个框架。
于是,我们需要从外部选择一个合适的框架。
jQuery和Bootstrap仍然好用
如果你想快速地使用多页面技术来开发应用,那么使用jQuery的生态能感受到显著的开发优势,再将Bootstrap作为UI框架能提升开发体验。尽管这样做会成为一个“普通”的方案,即没有亮点,看上去和其他应用类似,但是在后期我们可以快速、方便地进行定制。
不使用框架:You Don't Need xxx
对于那些只是简单地显示、隐藏DOM等操作的应用来说,我们完全不需要任何框架。在新的HTML标准形成后,如果我们只是做简单的元素选择,可以使用原生的querySelectorAll,再配置一个pollyfill。在一些面向程序员的网站,如在GitHub上已经使用浏览器原生的DOM操作元素,来替换诸如jQuery这样的框架。
复杂多页面应用的开发
单页面应用与多页面应用存在一些交集。这些交集,往往会影响我们的技术决策。使用多页面应用过于简单,而使用单页面应用过于复杂。我们要想办法在中间状态做一个最好的选择,即自己选择和创建合适的框架来完成功能。
我们选择MVC框架,多数是因为我们需要其中的一些特性,比如:
- 模板引擎,动态生成、创建页面。
- 双向绑定,实时修改数据。
- 前端路由,路由变化映射到对应的逻辑上。
- ……
正是这些特性组成了一个前端框架,它也是处在单页面应用和多页面应用交集的一些技术。这时除了选用框架,我们还可以自制一些简单的框架来完成相应的开发工作。
模板与模板引擎原理
对于稍微复杂的多页面应用,我们常常会采用模板来动态生成一些HTML,比如弹窗(Popup)、对话框(Dialog),或者一些固定的业务模板。由于重复编写这些内容的HTML必然不是一个好的方式,所以简单的HTML可以通过字符串拼接或者模板字符串的方式来生成。
基于字符串的模板引擎设计
顾名思义,基于字符串的模板引擎,就是通过字符串替换的方式,来渲染出HTML,再将HTML插入DOM节点中,其代表性框架有Mustache和Handlebars.js。
从软件架构上来看,Mustache提供了多语言的版本,即官方提供了诸如Python、Java、Ruby等语言的模板引擎。因为前后台共用这些模板,它可以使得后台渲染变得相当容易。只需要读取对应的模板文件,就可以将Model填充到数据中。使用这种方式时,每次更新值都需要全节点替换DOM节点,这样会造成一定的性能问题。其基本原理是,全局正则匹配模板关键字,
如{% name %},再从传入的data中找到是否有对应的值,如data中存在name的对象,则使用该值进行替换,否则该值为空。
基于JavaScript的模板引擎设计
基于JavaScript的模板引擎的表现形式是,将模板转义为JavaScript,在执行的过程中,再动态更新所需要的DOM节点。相应的逻辑如下:
- 将模板编译为某种DSL(领域特别语言),比如HyperScript或者JavaScript对象(代码+数据)。
- 在使用时,调用JavaScript来渲染出DOM结点。
- (可选)当发生变更时,通过DOM Diff算法来替换对应的修改结点。
双向绑定原理及实践
双向绑定,即双向数据绑定,它是指视图(View)的变化能实时地让数据模型(Model)发生变化,而数据的变化也能实时更新到视图层。在进一步深入双向绑定之前,应当对单向数据绑定的定义有一定的了解。
从双向绑定的定义里,我们可以清晰地将单身绑定分为两类。
第一类,视图的变化能实时地让数据模型变化。常见的有用于用户输入数据的输入框(input标签),在输入模型中输入数据时,我们需要监听这些数据的变化,再将这些值传递到模型中进行处理。
第二类,当数据发生变化时,对应的视图上的值也发生了变化,此时需要更新视图的值。
前端路由原理及实践
传统的多页面应用,路由及相关的状态都是由后端控制的,发生变化时也由后端来做相应的处理。当应用的重心发生转换——一部分由后端转移至前端时,路由的控制权也相应地发生了一些变化。发展至单页面应用时,几乎都是由前端来控制路由的。路由是前端应用的一个核心功能,它用于连接分散在各处的控制逻辑。
谈及路由映射时,我们讨论的是监听路由的变化,以调用函数来处理对应的逻辑。即使在多页面应用中也是如此,当用户执行一些操作,并且可以和别人分享时,记录下这些操作。当其他用户打开带操作状态的链接时,多页面应用立即响应,并更新页面状态。
总结
在本篇文章中,我们对比了单页面应用和多页面应用,了解了这两种应用的适用场景。随后详细地深入了:为什么在某些场合下,使用多页面应用是一种更有效的选择?单页面应用的学习成本、构建成本、后台渲染成本,以及其带来的应用架构的复杂性,使我们在有些时候应该考虑多页面应用。
然后,我们简单地了解了如何使用现有的技术来开发简单的多页面应用。对于复杂的多页面应用来说,我们学习了MVC框架的一些核心要素:双向绑定、模板引擎、路由映射。它们都是一个MVC框架核心的、可以独立出来的元素。通过直接使用这些核心组件,我们既可以不绑定框架,又可以灵活地扩展应用的架构。同时,在未来还能更方便地进行架构演进。
作者介绍
非职业「传道授业解惑」的开发者叶一一。
《趣学前端》、《CSS畅想》等系列作者。华夏美食、国漫、古风重度爱好者,刑侦、无限流小说初级玩家。
如果看完文章有所收获,欢迎点赞👍 | 收藏⭐️ | 留言📝。
- 点赞
- 收藏
- 关注作者
评论(0)