浏览器是如何将布局数据计算为像素数据的,你能实现出原理类似的渲染器吗? 浏览器在各个平台上的文字排版渲染结果是否一致,你能解释原因吗? 你所负责的前端应用,其渲染性能还有多大的提升空间,你能量化地证明吗? 你能设计实现出类似 RN 和小程序那样的 Hybrid 方案吗? 你能自己控制 GPU 渲染管线,实现渲染的硬件加速吗?
从 1979 年乔布斯造访施乐 PARC 算起,前端开发的历史,不是从 jQuery 甚至 JavaScript 的诞生开始的,而是从 Macintosh 时代的上古平台开始的。当你用这种方式来回顾几十年来的 GUI 软件开发框架时,相信你会对软件工程架构的进步有全新的认识。
在我目前的理解里,GUI 应用的架构实现,依次走过了这些重要的阶段:
过程化绘制时代 - 直接调用 drawLine / drawRect 风格的 API 来绘制像素。在我的树莓派里,只要 include X11 的头文件,就能用 C 语言体验这种硬派的 GUI 开发了。HTML5 中的 Canvas,其实也属于这种风格。 面向对象抽象时代 - 纯粹过程化的代码,并不利于维护事件驱动的业务逻辑。比如,你需要自行计算来判断出某次点击应该选中哪个 UI 元素。在 MFC 和 GTK 的时代,人们实现了面向对象风格的 UI 框架。按钮、输入框等 UI 控件具备了实例方法,能更好地组织代码。 界面与样式分离时代 - 用 C++ 系语言的代码来描述 UI,很容易写出面条式的丑陋代码。因此人们又引入了 XML 风格的语言,专门来表达嵌套式的界面。DirectUI 和 HTML / CSS / JS 基础上的经典 Web,都是这个时代的产物。 MVC 与 MVVM 时代 - 如何维护日益复杂的 UI 交互逻辑?许多框架引入了软件工程中的 MVC 和 MVVM 等设计模式。这个时代的代表产物有苹果的 Cocoa 和微软的 WPF,以及 Web 上的 Angular 1 框架。 声明式组件化时代 - 为什么我们必须编写连接 UI 布局语言和业务逻辑的面条代码呢?Facebook 的 React 提出了新的 UI 开发思路。通过 JSX,很容易用 JS 来编写嵌套的、声明式的、更易维护的 UI 组件,并借助 JavaScript 的动态性来实时调试 UI。当前风口上的 Vue,Flutter 和 SwiftUI,都明显地借鉴了这种思想。 理解了 GUI 技术架构的演进后,就不难明白一些口水问题的答案了。例如在我一个关于拖控件式编程的知乎回答里,有些人反对我的论据是「拖控件比写代码更高效」。没错,拖控件属于界面与样式分离时代的产物,这确实比面向对象抽象时代编写面条代码更好。但到了声明式组件化时代,编写代码反而比拖控件更高效而方便了。
看起来一切都在进步,一切都欣欣向荣。长期被原生开发者们鄙视的 Web,甚至引领了最新的 UI 开发技术浪潮。但这有什么问题呢?
问题就是,Graphics 被封装得太好了,以至于都不需要被关心了。
在最早的 GUI 时代,计算机甚至是没有 GPU 的。你绘制的文字和图像,都是内存里的 Bitmap。这时的 UI 框架作者们,必须认真考虑如何优化窗口化的 2D 渲染,并实现文字渲染、布局算法、点击测试等基础功能。而到了装机必备独立显卡的时代,如何用 GPU 来实现硬件加速的渲染,也变成了一个新的重要课题。最后,现代 GUI 应用基本都需要一个异步非阻塞的 Main Loop 配合子线程来保证渲染不卡顿,这也需要对操作系统的多线程技术有充分的理解。
可以看到,要成为原生 GUI 库的作者,多半需要扎实的操作系统和计算机图形学基础。但在今天流行的 Web 和 App 平台,这些计算机基础知识,已经被藏在厂商提供的 API 后面了。而流行的 React 和 Vue 等 UI 框架,其输入和输出都已经是相当结构化的数据,更不涉及困难的 Graphics 部分。虽然大多数场景下这些 API 是够用的,但当你需要更多的自由、更多的掌控时,你会发现自己被限制住了:你能用 JavaScript,直接读写某个 DOM 元素在某个像素下的颜色吗?
这种能力上的限制,不仅影响了前端工程师的长期技术成长,还使得社区的风气都变得有些古怪。React 的声明式 UI 确实有用,但在其影响下函数式编程被社区奉为圭臬,某些布道者甚至连 for 循环都要抵制,这就有些舍本逐末了——要想掌握原生的图形渲染管线,几乎必须掌握非常命令式的编程。在渲染能力的限制下,整个社区的发展都倾向于关心代码自动格式化、强类型提示、编写更优雅的状态管理代码等层面的东西。这些技术方向固然有用,但多半只能增量地提高开发效率,并不能创造出全新的用户体验。
怎样突破标准化 API 的限制,创造出全新的用户体验呢?我很喜欢举 Photopea 的例子,这是个浏览器内的 PS 替代品(其国内版是我们部署的 ps.gaoding.com)。当我在捷克与作者 Ivan 交流时,他告诉我一般的 Web App 可能有 90% 的代码是第三方框架实现的,但他的 Photopea 则有 90% 的代码都需要自己写。他将 PS 中各种重要的算法实现到了 Web 上,最终获得了 WOW 级别的图像编辑体验。他明确地告诉我,他并不认为自己是一个 Front End Developer,而是一个 Programmer,能根据需要去学习并解决具体的技术问题。他对技术的态度,对我个人有很大的影响。
很多抱怨 35 岁焦虑的同行根本没有认识到,前端框架快速变迁的真正原因,在于 GUI 背后的整个产业链,还具备巨大的发展和改进空间,仍然处于朝气蓬勃而充满机遇的时期。需要对整个 GUI 系统及其背后的计算机科学有着更深刻的了解,才能把握住这样的机会。