02 开发前端有哪些要点?React框架是如何应对的?
你好,我是宋一玮,欢迎回到React组件的学习。
在上节课,我们简单回顾了一下前端开发的历史,指出前端开发领域一直在积累特有的领域知识;提出了GUI图形用户界面也是一种接口,跟后端API开发类似,前端“接口”也有自己的设计准则。然后把本世纪初的Java Web技术当作参照物,列举了前端开发领域的变与不变。希望能帮助开发者坚定持续学习的信心。
再看现状,现代前端框架有很多,前端项目的技术选型令人头疼。这时前端开发者就希望能有一些方法帮助自己做出选择,不仅是为项目选择,也为了确定自己的学习目标而选择。
React框架在诸多前端技术排行榜上均位列第一,其生态也是最丰富最活跃的。你可能会好奇:
- React框架凭什么这么火?
- 是不是因为React火,所以我才要学它?
- 是不是因为React火,每个项目都无脑选它就对了?
在这节课,让我们回归到前端开发的本源,即模版、数据建模、交互、数据传输等等这些要点。我认为正是React在这些要点上具有优秀的设计、实践或生态,才造就了它今天的地位。
当你理解这些要点,再结合具体前端项目的需要,就可以更有信心地做出是否选型React的判断了。
“跳伞”+“跑圈”
你看到这个标题想到了什么?《PUBG》还是《和平精英》?啊?你从不打游戏啊,那打扰了。在玩生存类游戏时:
- 高手的流程为开局跳伞、落地跑圈、大吉大利;
- 菜鸟的流程为开局跳伞、落地成盒、重开一局。
当然,这节课肯定不是要教你打游戏,我只是想用游戏中的概念类比一下前端开发。游戏里选用的策略和装备,基本可以体现出你是不是高手;前端开发中选择怎样的架构和技术选型,很大程度上决定了你能不能“大吉大利”。
接下来就让我们看看React在全程都起到了什么作用。
“跳伞”:从前端架构到实现
“跳伞”是一个从高空接近地面的过程,地面的目标由远及近、由粗到细,跳伞玩家也可以控制自己目标落地区域。软件从架构设计到具体实现跟这个过程有很多相似,单是软件架构就可以有所谓三万英尺视图(30000-Foot View)、一千英尺视图(1000-Foot View)等不同粒度的设计。
顺便提一下,三万英尺视图本来是商业战略中的概念,后被《97 Things Every Software Architect Should Know》这本合著引入到软件架构设计领域。这门课程专注于前端,所以我们跳过系统架构、软件架构等不那么“前端”的概念。
前端应用分类
我们先试着从最高空鸟瞰前端应用,目前主流的包含GUI的分布式应用,基本可以分成:
-
B/S应用
-
浏览器端
- 移动H5应用
- 桌面Web应用
- 服务器端
- C/S应用
-
客户端
- 移动端App
- PC客户端
- 服务器端
近年来客户端也开始拥抱Web,衍生出基于Webview的Hybrid混合应用。
它们之间的关联关系如下图:
看到这样的地图,结合第一节的内容,你在“跳伞”的第一时间,基本就能确定自己要往哪里跳了。是的,你的目标区域是浏览器端,这也是React框架最擅长的领域。
我们这门课主要针对浏览器端,特别是桌面浏览器。之所以定位到桌面浏览器,是考虑到相关开发调试工具更加丰富,有利于在实践中学习。课程的绝大部分内容也适用于移动端H5应用。
前端逻辑架构
当你跳出机舱,下降了三分之一高度时,会看清浏览器端Web应用的一部分结构。这些结构仍在逻辑层面,相对抽象,强调各个模块的层次结构和相互关系,还不涉及到技术实现。这在软件架构设计中一般被称为逻辑架构。
前端的逻辑架构,设计的重点自然是前端应用。以用户体验较好的SPA单页应用(Single Page Application)为例,下图是一张用于参考的逻辑架构图,注意这张架构图并不是通用的、四海皆准的,我们只是用它作为例子:
在上图中,作为前端的SPA会包含若干业务功能模块,和服务器通信、前端路由、表单处理、错误处理等多种通用功能模块。通过服务器通信模块,前端会请求服务器端接口,获取或修改业务数据。服务器端即后端,一般包含入口的API网关(Gateway)、若干个后端服务,底层是数据库存储。
在架构图的两侧,展示了部分支持性质的模块。在设计阶段定义的设计系统(Design System)、响应式布局、可访问性等用户体验领域知识会支持整个前端应用的开发。在部署上线阶段,打包编译、CI/CD、自动化测试、运维工具等基础设施,会保证开发者辛辛苦苦开发的应用最终可以为用户所见、被用户使用。在运行时,用户认证(Authentication)、授权(Authorization)、前端监控、配置管理等通用模块可以支撑应用的正常运行。
你如果仔细观察会发现,这些模块在图上呈现的高度并不一致,与前端应用层也没有完全对齐。请你放心,我在画图上有些强迫症,这里是故意这么画的:
- 最右边的用户体验领域设计,是纯前端的支持模块,所以高度与前端一致,并在纵向上与前端对齐;
- 左右两侧的部署上线基础设施和运行时模块,基本同时涵盖了前端后端,所以它们的底边都延长到与后端平齐。
你如果追问为什么后端底边比其他模块更低?纯粹是为了美术上的构图平衡,让图更顺眼些。
其实在业界实践中,一个相对复杂的前端应用可能会同时包含多个SPA,最终以MPA多页应用(Multi-Page Application)的形式提供给用户。当然,这并不是必须的。
前端应用架构
别忘了,你还在“跳伞”过程中。经过刚才的观察,你已经搞清了前端应用从逻辑上都有哪些模块。我希望你一边继续下降,一边调整方向对准SPA单页应用区域。
已经下降了三分之二高度,这时你可以看清SPA内部的一些技术细节了。这些细节更加贴近技术,但还是相对抽象的,不限定技术实现方式。这在软件架构设计中属于应用架构。
下图是典型的MVC(Model-View-Controller)应用架构的变体:
一个“纯粹”的MVC架构,视图会触发控制器,控制器修改模型,模型再触发视图更新。常见的MVC变体,包括MVVM(Model-View-ViewModel)、MVP(Model-View-Presenter)、MVI(Model-View-Intent)。其中MVI架构最接近React社区里提倡的单向数据流。
既然是“跳伞”,那可别忘了开伞,现在是时候了。
“跑圈”:前端技术选型与React
好了,“跳伞”的你顺利落地了。现在开始“跑圈”。跑圈是指在有限的地面范围有目的地持续移动,造访多个目标地点、获取装备、采取各类行动;之后随着时间的推进,地面范围会逐渐缩小,你的行动也将更具挑战,之前实现的目标和积累的装备会成为你的助力,最终获胜。
软件开发中的技术选型和实现与这一过程异曲同工。软件架构要落地,其中一个重要环节就是技术选型。在前端领域,技术选型尤为重要。一般而言,前端开发交付的产品最终会运行在一个受限环境中,如浏览器、智能手机平台、Webview等,反过来就会要求前端框架也要迎合运行环境的特性,否则它有可能帮倒忙。
举个例子,浏览器里支持的脚本语言是JavaScript,但你在技术选型时第一时间选择了Go语言,那将很难开发浏览器端的交互逻辑(啊?你说Go代码编译成WebAssembly,那没事了)。
先根据“跳伞”时看到的各种模块,确定一下需要选型的前端技术点:
- 开发语言
- MVC或类MVC框架
- 服务器通信
- 表单处理
- 错误处理
- 前端路由
- 打包编译工具
- 自动化测试框架
暂时只列这么多。实践中根据具体应用需求不同,还会有很多其他技术点需要考虑。
下面请你跟随我,结合以上选型技术点,看React框架如何满足前端应用开发的需要。
开发语言
无论框架怎么选,先得选好开发语言。浏览器原生支持的语言包括:文档语言HTML、样式语言CSS和脚本语言JavaScript。2019年底WebAssembly正式进入W3C标准,成为浏览器的第四种原生支持语言,不过这门课程不会涉及WebAssembly。
除了这些原生支持的语言,开发者还可以使用其他语言开发,然后编译成原生语言在浏览器中执行。如JS的超集TypeScript,语法与JS相近,支持类型系统,通过编译器编译成浏览器可执行的JS,尤其适合开发大型Web应用。再如LESS、SaSS,扩展了CSS的语法,更方便模块化,通过编译器可以编译成浏览器可解析的CSS。
关于JS,还有一个值得提的点,在浏览器JS演进过程中,厂商和技术社区合作推出了标准化的ECMAScript(简称ES),从ES6即ES2015开始,每年ES会推出一个包含少量新语法或新接口的新版本。
其中ES2015包含的新特性是最多的,随后ES2017的 Async
/Await
、ES2018的对象展开语法(...
)、ES2020的可选链操作符(?.
)都是改变JS开发者编程习惯的重要特性。然而并不是所有浏览器的所有版本都支持最新的ECMAScript。
为了兼容用户的老浏览器,但又能充分利用新语法带来的好处,可以用Babel这样的编译器将高版本的ES代码转译成更多浏览器支持的低版本,如为了(不得不)支持已经退出历史舞台的IE11,将ES2020的代码转译成ES5。
这门课程中的样例代码将以ES2020编写。
React对应技术点
React框架是Meta公司前身Facebook(下称FB)于2013年开源的,声明式、组件化的前端开发框架。
首先从开发语言看,React支持ES2015以上的版本。虽然也支持ES5,但并不推荐,如果必须要支持老浏览器,那就利用Babel转译吧。同时,React对TypeScript也有很好的支持,提供了完整的类型定义。所以打算用React时,你不用担心语言支持的问题。
然后,我们不妨把React直接拉进我们的技术选型里,看看React涵盖了哪些技术点。
第一,MVC或类MVC框架。
React为视图层带来了声明式的JSX语法,这种语法是模版的同时又是JS语言本身,易学性、灵活性和性能远超其他模版引擎。
在视图之外,React设计了一套单向数据流机制进行应用状态管理。从视图事件触发状态变更,状态变更的结果汇总在一起,通过不可变数据传递给关心这些数据的视图,视图根据传入的数据决定是否重新渲染。
开发者将视图和相关逻辑声明成一个个React组件,React底层实现了一套虚拟DOM模型,它比浏览器DOM更为轻量,React靠比对新旧两个虚拟DOM来实现低成本的渲染。
这里提到的JSX语法、React组件、虚拟DOM、单向数据流,在后续课程中会一一讲解。
说句题外话,虚拟DOM作为一种抽象,并不与浏览器直接绑定,理论上可以用于其他平台。于是2015年FB开源了React Native框架,开发者们可以用JS语言,加上与React基本相同的API开发iOS和Android的原生应用。
与Hybrid应用不同,React Native的JSX会被渲染成目标平台的原生组件,进而提高性能、提升体验,这在当时也给React挣足了面子。但不像React,React Native在后来发展中经历过一些波折,被Google推出的跨端框架Flutter迎头赶上。
第二,表单处理。
React框架本身并没有提供高度抽象的表单处理组件或者接口。但在React开发者可以将HTML表单元素声明为受控组件(Controlled Components),并基于受控组件的状态数据进行表单处理。
第三,错误处理。
React没有内建处理全局错误的机制,但提供了错误边界(Error Boundaries)API,可以在组件树中实现类似try...catch
的功能。
受控组件、错误边界在后续的课程中会涉及到。
React生态
你可能会吐槽,React的功能怎么这么少?隔壁Angular可是内置了服务器通信模块和路由模块啊!
我个人认为所谓的“功能少”反而是React流行的重要原因之一。一个大而全的框架难免会落入一个窘境:学起来更累,用起来更重,定制起来也更受限。
React做好了属于自己卖点的部分:声明式、组件化、单向数据流,以及后来的Hooks,其他领域则留给第三方。用React的人越多,为React开发的第三方开源库越多;React生态越丰富,用React的人越多。这就形成了React的马太效应。
列举一些React生态:
- 类MVC框架:早期的React侧重于视图,并没有内置
dispatch
和reducer
相关的接口,但开源社区为React设计的应用状态管理框架如雨后春笋,百家争鸣,如FB的Flux、开源的Redux、MobX等等; - 服务器通信:浏览器标准的
fetch
API,以及更强的React Query框架; - 表单处理:Formik框架、React Hook Form框架;
- 前端路由:事实标准的
react-router
框架; - 组件样式:诸多CSS-in-JS框架,如
emotion
; - 打包编译工具:Webpack、Babel,以及包含了前者的Create-React-App脚手架;
- 自动化测试框架:Jest、React Testing Library。
此外还有大批高质量的可复用组件库,如AntD、Material-UI等。这些第三方框架和工具,为React补足了开发现代Web应用缺少的功能。有些组合固定出现,以至于被开发者戏称为“React全家桶”。
小结
这节课我们借用“跳伞”+“跑圈”的比喻,将这门课程的范围设定在桌面Web应用,从架构层面分析了前端开发的组成部分,包括逻辑架构的SPA、业务功能模块、通用功能模块和应用架构的类MVC模式。
然后聊了技术选型阶段面对的技术点,将ES2020指定为这门课程的开发语言,也简要介绍了React框架本身和React生态的分工。
下节课我们会快速进入实践环节,请你跟着我写一个简单的React应用。
思考与互动
“跳伞”过程中你看到了前端逻辑架构和应用架构,里面定义的不少模块在各类前端框架中都很常见。可否请你选择一个你熟悉或者完全不熟悉的、React以外的前端框架,对照着这个框架的文档,看看框架都涵盖了哪些模块?
欢迎把你的思考和想法分享在留言区,也欢迎把课程分享给你的朋友或同事,我们下节课见!
- . 👍(3) 💬(1)
几乎没有这些框架设计的理念, 平时看代码都是逐行逐句看的。
2022-08-27 - Geek_9373fc 👍(2) 💬(3)
老师你好,请问为什么jsx是声明式?声明式和命令式的区别是什么?
2022-08-25 - Geek_fujinshuai 👍(1) 💬(1)
借用网络经典书籍名, 自顶向下学习方法!
2022-08-23 - 我听着呢 👍(0) 💬(1)
老师课程之后会讲工程化方面的内容吗
2022-08-23 - chen 👍(5) 💬(0)
一直不太明白react的单向数据流和vue的双向绑定有啥区别
2022-11-03 - Angry阳。 👍(1) 💬(0)
学习了
2022-09-11 - Hello,Tomrrow 👍(1) 💬(0)
第二天,打卡
2022-08-29 - Black Jack 👍(0) 💬(0)
老实说,虽然专业名词多,看不太懂,但一定是高屋建甄,等学完了再回来看。
2024-01-15 - Sarai李 👍(0) 💬(0)
感谢大佬的呈现,这样“由高到低”的视野让小白也有了感谢认识!打算直接跟着这个课程快速入门!
2022-12-27