如今,市面上的 JavaScript 框架越来越多,过于丰富的选项往往令人不知所措。我也是迷失在其中的一员,所以我尝试构建了一款工具,想帮助开发人员选择适合自己的框架方案。但效果嘛……不怎么样。
在本文中,我想跟大家分享自己在 JavaScript 领域的探索之旅。从最初轻狂粗暴的情绪化“表情包”到后来糟糕的网站,再到回归开放包容本心,我会深入反省自己一路上学到的教训,特别是如何在选择技术堆栈和框架之前先就项目提出正确的问题。
年轻人不要太气盛
欢迎来到这场颇具争议的讨论。去年 6 月,我曾发表过一篇博文,说自己对于 JavaScript 生态系统的混乱现状而感到不知所措。选项太多了,完全可以做个专门的表情包……。每分钟都有新的 JavaScript 框架问世,这也太夸张了!
我还专门为此创建了个愚蠢的网站:should-i-write-a-new-javascript-framework.lol(有必要开发新的 JS 框架吗?),而我自己当时的观点是没必要。虽然当时的我年轻气盛、自信满满,但访客们的反馈和建议帮我开启了一段探索之旅。随着网站内容的持续发布,我开始意识到新的 JS 框架有其价值。没错,我的结论已经变了——我们确实需要更多 JavaScript 框架。
相信很多朋友都在网上看到过类似的问题:我打算开发一个新项目,到底该选哪个 JavaScript 框架?我的那个网站就是为此而生,旨在帮助大家选择适合自己的框架。
答案当然要视具体情况而定,我的网站就是想引导开发人员深入探究自己的依赖需求,再据此找到最合适的框架选项。没有炒作、没有偏见,我把整个选择过程整理成了两个问题。确实有点蠢,实际情况也远比这复杂,但我还是想把自己当时的思路分享出来。
问题一:你打算构建哪种类型的网站?也许你要开发的是一个静态站点,也就是那种被打包起来、用来承载内容分发网络所提供的 HTML 文件和资产的网站。这类站点上的内容不会经常变更,所以构建难度较低。另一种可能,就是构建的是需要在服务器端进行渲染的站点,其中各个 HTML 页面都是由服务器在收到请求时全新构建出来的。这指的就是那些需要通过各个页面为用户带来自定义体验的动态站点。当然,我们也可以将二者结合起来,一部分是静态页面、一部分是动态页面,我将其称为混合模式。
问题二是,你需要跨多个页面进行状态维护吗?但这方面需求是有多种实现方式的,所以我承认这个问题提得有点毛病。因此,我提供了更多技术透明度选项,比如是否需要用 JavaScript 构建单页应用程序。所谓单页应用程序,简称 SPA,是指能够在浏览器本地为不同页面构建 HTML 的 JavaScript 应用程序,需要借助客户端 JavaScript 才能运行。或者,大家也可以选择多页面应用程序(简称 MPA),其中每个路由都对应自己的 HTML 文件。文件从服务器发出,所以初始内容的加载并不依赖于客户端 JavaScript。
接下来,我们提供一份框架列表。假设我们选择要创建动态站点,之后选择单页应用程序,那照理说就可以根据框架的可用功能进行推荐了吧?但事情没那么简单,What the Framework 上只包含 23 种 JavaScript 框架,原因是我对上榜框架设定了筛选要求——第一,框架必须得到良好维护;第二,框架已经发布了稳定版本。
但是,假定我们的项目需要同时提供静态内容加服务器端渲染的页面,也就是混合模式,而且又属于多页面应用程序,那可选的框架有哪些?答案有五个:Eleventy、RedwoodJS、Next.js、Nuxt 以及 Gatsby。听起来不少,但在具体观察框架功能后,我们会发现它们并不能满足所有需求。
Next.js 和 Gatsby 使用的是默认为 SPA 的 React,所以并不完全适合我的用例。当然,我们可以想办法用 Next.js 或 Gatsby 生成静态站点,再将站点转换成多页应用程序。但这些都属于变通手段,而且这些框架的静态构建其实无法使用服务器端渲染功能(至少截至撰稿时还不行),所以并不符合我的要求。
Eleventy 是个不错的选项,但边缘功能的服务器端渲染还处于试验阶段;而且它只适用于 Netlify,我又特别讨厌供应商锁定。
那剩下的就只有两个选项了:Nuxt 和 RedwoodJS。目前,Nuxt 3 专门提供静态和服务器端渲染页面的混合组合,能够很好地服务于多页应用程序。但我还没用过 Vue,所以不知道有没有必要在新项目中额外学习一套新框架。
RedwoodJS 是一个全栈框架,理论上应该会是理想的选项。但它会带来大量的开销和集成负担,让我感觉好像很没必要。也就是说,虽然今年已经是 2023 年了,但 Web 开发方面的称手工具并没有我们想象中那么丰富。而且这里我提出的场景并不复杂,混合模式的 MPA……实际开发中很可能会出现更多细微差别。
Eleventy 的缔造者 Zack Leatherman 表示,其实有很多方法可以定义服务器端渲染。那如果我不清楚自己需要哪种类型的服务器端渲染,或者根本就不需要服务器端渲染,又该如何选择框架方案?另外,随着 Web 的不断发展,性能优化层面的选择因素也在快速增加。
Astro 的核心维护者 Ben Holmes 对缓存和服务器端渲染进行了一系列实验,并发现服务器端渲染在速度上已经能跟静态站点并驾齐驱。也就是说,即使我们减少静态页面预构建、将更多内容交由服务器端渲染,网站的整体速度仍然可以保持在不错的水平。
就是说服务器可以提供更好的性能,但各种不同的服务器端渲染类型还是让人难以取舍。我不知道自己需要哪种,甚至不知道要不要继续用静态站点。总之,肯定有某些现实问题还缺少理想的现成框架;我们身为开发人员,怎么能对有益的新方案说不呢?
SolidJS 的缔造者 Ryan Carniato 表示,“我们仍然需要新的框架,我们仍然需要更多创新。”Ryan 一直希望将框架作者汇聚起来,共同建立起更好的 Web 生态系统、避免框架之间的对抗。而在当初发布博文时,我曾带着这些问题跟他进行了深入交流。
最近,我还专门研究了 Twitter 的技术发展史,并发现这是一段有趣的故事。
简单来讲,2010 年时的 Twitter 几乎完全使用 JavaScript 来实现新架构。其主要目标之一,是交付运行方式类似于传统网站的富 Web 应用程序,借此简化并加快页面导航体验。在我看来,这似乎就是个单页应用程序。而那时距离 React 首度亮相还有三年时间。到 2012 年,Twitter 宣布为了重新优化前端性能,他们决定将大部分渲染从客户端转移回服务器。2013 年,在 React 发布的短短九天之后,Twitter 公布了一套 JavaScript 框架——Flight,并直接投入自家生产环境。这是个有趣的 React 替代方案,不仅不再强制要求使用模板语言,而且允许在客户端和服务器上渲染 HTML。请注意,那可是 2013 年,也就是十年之前。
2017 年,Twitter 又发布了 Twitter Light,希望最大限度减少数据用量、加快低质量网络连接上的加载速度,并将设备空间占用控制在 1 MB 以内。这一切,明显是为了改善移动版 Twitter 的使用体验,现在大家仍然可以下载到这个版本。这是一款渐进式 Web 应用,强调重现单页应用程序的原生使用体验。
如今,这段故事还在继续。Twitter 旗下一系列技术、项目和产品都在沿着这个方向探索和前行。
这就形成了有趣的历史循环。Web 1.0 时代,我们把一切渲染都交给服务器;后来,我们开始在浏览器中利用 JavaScript 完成所有操作,全面走向单页应用程序时代;再往后,我们又把所有内容转移回服务器,因为这样速度更快。这当然不是坏事,毕竟变革的背后是越来越强大的网络和算力发展。但我们可以从中总结出两个结论:第一,技术发展是有周期性的。Web 1.0 时采用的是服务器端渲染,之后人们开始把前端嵌入到 JavaScript 框架当中,可最终服务器端渲染又重新成为主流、并贯穿到如今的各类 Web 场景之下。第二,Twitter 会根据用户的使用方式对技术做出调整和发展。特别是从 2017 年开始,移动端开始成为优先级最高的绝对中心。
也就是说,我们做出的技术选择(包括使用哪种 JavaScript)不仅仅取决于产品的功能需求,更会受到用户使用方式的巨大影响。因此,大家在选择技术时一定要先提出有意义的问题。比如产品的受众是谁、他们的网络连接质量如何、他们使用什么设备、他们会跨设备使用吗、他们习惯于以怎样的方式使用产品,等等。
考虑到这么多影响因素,我鼓捣出来的 What the Framework 根本帮不上什么忙。这也反过来给了我们信心:如果我们正在构建某些产品,并发现其中的问题无法通过现有技术直接解决,那就果断构建出新的 JavaScript 框架。当下不存在完美的解决方案,往往意味着永远都不会存在。只有亲自动手才能改变现状,推动技术进步。
我们永远不可能彻底解决每款产品的每种用例上的每个问题,所以我们永远需要更多、更丰富的 JavaScript 框架。这就是我现在的结论,我愿意为此负责。
原文链接:
https://whitep4nth3r.com/talks/we-need-more-javascript-frameworks/