JavaScript 的诞生与死亡
JavaScript 在浏览器中运行,权限极低。尽管如此,它却运行着服务器、构建工具,甚至是数据库。这并非预先设计的蓝图,而是在 1995 年的一个决定之上,通过一系列补丁构建而成的。
2014 年,Gary Bernhardt 发表了一场名为“The Birth and Death of JavaScript”的演讲。许多人将其视为一个失败的预言,而我则将其视为一种诊断架构摩擦(architectural friction)的工具。
Bernhardt 描述了一条充满讽刺意味的路径。JavaScript 最初只是一种玩具语言。它之所以能生存下来,是因为它是浏览器中唯一的语言。这种垄断地位使其成为了地球上执行频率最高的语言,即便它并非技术上的最佳选择。
核心矛盾很简单:浏览器既需要安全地运行代码,又需要快速地运行代码。这两个目标往往是冲突的。
2014 年时,人们预测 WebAssembly 将取代 JavaScript。但事实并非如此。WebAssembly 很稳定,对于 Figma 或 Google Earth 之类的应用非常有用。然而,它并没有取代 JavaScript 作为一种应用语言的地位。
相反,JavaScript 发生了变异。TypeScript、打包工具(bundlers)以及像 Deno 或 Bun 这样的新运行时,都是为了解决 Bernhardt 所指出的那些摩擦而进行的尝试。
不要利用这场演讲来逃避学习 JavaScript。也不要在遇到真正的性能问题之前,利用它来为转向 WebAssembly 寻找借口。
应该利用它来审视你的技术栈,并提出以下问题:
• 我使用这个工具是因为它是解决该问题的最佳方案吗? • 我使用它是因为它是当前环境下唯一可行的方法吗? • 我工具的复杂性是解决了实际问题,还是仅仅将问题转移到了其他地方? • 如果我今天从零开始,我还会选择它吗?
如果你在服务器端使用 TypeScript,你获得了类型安全,但也增加了编译开销。如果你使用 Next.js,你获得了更多功能,但也增加了缓存的复杂性。这些都是真实的权衡(trade-offs)。
最常见的错误是在问题实际上源于使用不当时,却去责怪语言。如果你编写了阻塞事件循环(event loop)的沉重同步代码,问题在于你,而不是 JavaScript。
停止寻找所谓的“魔法替代品”。开始测量你真正的瓶颈所在。