关于未来泛前端框架的一些设想

    关于前端开发框架的讨论已经有一段不短的历史了, React VUE Angular 以及为数众多的实验性框架已经给出了不错的答案,但这仍然是一个能给予我们丰富想象力的话题。如今:

    • 各种基础设施的革新赋予了更多的可能性;
    • 小程序给了我们一个全新的框架视角;
    • 前端领域的泛化使得我们需要重新考虑更加广泛的编程问题。

    是时候来重新考虑这个问题:我们距离理想的前端开发框架还差什么?

    一、 WebAssembly

    WebAssembly 可以取代 JavaScript 以获得更好的执行性能,或者将其他语言的代码编译到 web 环境下。 WebAssembly 已经经历了漫长的发展过程。现在,相关的各种基础设施也愈加成熟。 Emscripten 工具链、 Binaryen 工具集已经广泛应用。它作为通用的字节码标准,也有很多解释器和 JIT 使它能应用于非 web 环境下。

    近年来 rust 团队和社区也为 WebAssembly 做了很多积极的工作。毫无疑问, rust 作为底层编程语言,和 WebAssembly 非常契合。 rust 非常小的运行时代码、极佳的性能、优秀的包管理机制,以及 wasm-packtwiggy 等配套工具,使得它非常适合作为 WebAssembly 的编程语言。实际上,已经有一个不错的 rust 前端框架 Yew ,不过我们还需要留给它更多时间。

    这些使得 WebAssembly 可以成为框架实现的更佳选择。使用 WebAssembly 构建框架,可以提供更多性能优化的空间:代码执行性能更好,通过手动内存管理、缓慢的 Virtual-DOM 也有巧妙的优化方式。然而不只是性能—— rust 这样的编程语言更加适合编写和维护底层框架逻辑。强大的 enum 可以清晰描述复杂的数据构成, procedure macro 可以让 html 巧妙嵌入到 rust 代码中,显式错误处理让框架本身不会轻易陷入异常状态,不可变引用可以零开销地避免高层逻辑带来的意外数据变更……显然,这样会使框架比在 JavaScript 中实现要可靠得多。

    对于 WebAssembly 构建的框架而言,高层逻辑可以是 WebAssembly 或 JavaScript 的。前者可以获得更好的编译期优化;后者会损失一些性能,但对大多数开发者而言,他们可以使用更熟悉的编程语言。比较理想的想法是:不同的高层组件可以根据自身需要选择 WebAssembly 或 JavaScript ,当然这也要求框架的接口设计更仔细。

    二、多后端

    不少前端框架都在事实上有“渲染后端”的概念:在 web 浏览器中,框架维护一棵 DOM 树;在服务器端渲染时,则生成一段 HTML ;一些框架还可以将小程序作为渲染目标。框架自身终究承担的是某种“代码组织”的工作,最基础的界面组织则由相应的后端完成。因而,框架逻辑应当能与后端合理解耦,例如,框架给出一种“通用协议”,不同的后端实现这套协议来最终渲染出界面。

    这样可以让框架充满更多的想象力:编译到 WebAssembly 的框架,也可以编译成平台原生代码,这样,再制作一个基于 WPF 的后端,框架不就能直接用于 Windows 原生界面开发了吗?事实上这种设计在现有的 GUI 框架中比较常见(例如 imgui ),然而,要与 web 相容显然会有更大的阻碍, CSS 如何处理, JavaScript 如何嵌入都会成为复杂的问题。但无论如何,通用的后端协议都将提供更广泛的空间,同时也更利于分布式开发协作。

    三、定义式与模板

    现今,流行的框架接口风格其实已经比较固定,大家都喜欢“定义式”的界面组织方式。定义式的本质是让界面开发者描述界面的当前状态、而非如何从旧状态变成新的状态。这可以显著降低界面开发的工作量并减少意外的 bug 。

    我们没有理由质疑定义式开发在实践上的价值。可是,定义式接口带来的框架开销较难抑制,尤其在性能敏感的场合(如拖拽动画)问题会变得比较显著。多数框架尝试在接口灵活性与框架开销之间找寻微妙的平衡,现在已经做得足够好了吗?恐怕答案并不是肯定的。

    如果从接口风格上考量,定义式框架又可以大体分为两类:将模板融合到逻辑代码之中,如 react 的 jsx ;模板单独是一个代码块,如 vue 。前者接口更为灵活,后者进行模板优化更为容易。两者应当如何取舍?或者,更贪心地,有没有可能将两者更好融合呢?又或者,还有没有一种更突破性的设计呢?

    也许 elm 给了我们一个可能的答案,也许我们还需要加深探索。

    结语

    这是一个问题与尝试要远比答案更多的时期。

    如果从更宽广的视角看,我们或许正站在 GUI 编程的十字路口。 nuklear 带着 immediate mode GUI 的概念席卷而来, WebRender 给出了新的绘制理念, PathFinder 正试图改变矢量绘制。众多的研究者们正尝试给出与前人迥异的思考。也许, GUI 框架即将迎来一个新的时代。

    对于泛前端框架而言,未来又会如何呢?