写点什么

下一代前端语言之争,JavaScript 要被新语言反超?

  • 2023-01-03
    北京
  • 本文字数:4265 字

    阅读完需:约 14 分钟

下一代前端语言之争,JavaScript 要被新语言反超?

假如大家正在编写前端代码,那么会选择哪种编程语言?目前来看,最有希望的选手主要有三个:首先是最常规的 JavaScript,然后是能编译为 WebAssembly(Wasm)的语言,最后则是能编译成 JavaScript 的语言。


常规 JavaScript 需要的配套工具最少,但代价是调试起来相当麻烦,代码可读性也差。虽然选择 JS 确实门槛较低,不过除了一味痴迷“极简主义”的铁粉以外,我个人觉得这个选项只能说一般。


能编译为 Wasm 的语言虽然越来越多,但总体上还是新生事物。这些语言往往带有大量的二进制文件,因为其中大多需要配合额外的运行时。Interop 距离发展成熟还差得远。另外,即使两种语言都能编译成 Wasm,也不代表它们之间就能良好实现互操作。再有,这个阵营的生态储备还远远比不上积累了几十年的 JavaScript DOM 库。在 Wasm 这边,React 和 Svelte 应该是最好的选项了。大家千万别误会,我可不是在唱衰 Wasm。它已经拥有专属于自己的表现舞台,如果大家想要在浏览器中运行高计算量原生代码,但 Wasm 就是最完美的选项。可如果不是这种情况,我个人不太推荐用它进行日常前端开发。


最后剩下的就是能编译成 JavaScript 的语言了。但这个阵营形成了一家独大的局面,其中的老大我们稍后会具体讨论。相比之下,ClojureScript、Elm、ReScript、Dart 等语言都形成了颇具体量的社区,但未来市场份额还能不能进一步扩大尚未可知。这就很尴尬了,毕竟能编译成 JavaScript 的语言代表的基本就是浏览器上的最佳编程体验。在它们的支持下,我们既能享受 JS 所不具备的良好功能,比如静态类型、强类型、不变性、宏等,同时也能通过 bindings 支持 JS 及其广泛的生态系统。而且,它们还不需要笨拙的大型运行时。


由于 Wasm 的存在,我怀疑 JS 编译阵营会有所保留,毕竟很多人觉得前者才是浏览器上的最佳编译目标。我其实并不同意这种观点,能编译成 JavaScript 的语言还是越多越好。总之,我想借这篇文章跟大家聊聊现有及未来可能出现的前端语言,应该朝着哪个方向发展。

TypeScript 还行吗?


这就是我前文提到的 JS 编译阵营中的“老大”——TypeScript。TypeScript 是种很棒的语言,显著改善了开发者体验。它还新增了安全层,促进工具质量提升,并大大降低了使用门槛。考虑到生态系统的繁荣现状以及对 JS 类型检查难题的妥善解决,TypeScript 确实取得了非凡的成就。


当然,也有不少针对 TypeScript 的非议值得关注。首先就是这门语言的性能和健全性问题。需要注意的是,TypeScript 团队其实很清楚这两大顽疾,而其根源是开发团队在项目之初做出的明确权衡。在我看来,这些权衡是当时为了提高执行效率而做出的正确选择。


话虽如此,但性能确实是 TypeScript 最受诟病的问题。TypeScript 是自实现的,而且这种实现非常复杂。它的类型系统本身可以算是种迷你编程语言,这导致类型检查的速度极其缓慢。


第二个问题就是健全性。这事的讨论热度没那么高,但在编程爱好者群体内部还挺受关注。概括来讲,TypeScript 一身都是“缺陷”——allwJs 配置选项、any 类型和 intersection 类型,其类型系统根本无法保证代码的类型安全。换言之,我们编写的 TypeScript 很可能会触发运行时 bug。另外,除了极其简单的场景之外,TypeScript 还缺乏可靠的类型推断,所以开发者在很多地方都得明确标出类型注释。


但同样的,这两点也是项目权衡的结果。


引导编译器的存在对于 TypeScript 的内部测试至关重要,这能帮助项目开发者理解 TypeScript 这种语言用起来的真实感受。具体来讲,项目团队要体验如何编写大型 JS 代码库,再逐步采用代码库中的类型。在健全性方面放松一点,开发者才能在现有 JS 代码库中逐步引入 TypeScript,也能轻松使用 any 类型来直接摆脱类型系统的束缚。


光是这部分就够单独写篇文章了。在我看来,TypeScript 可能是第一种更多关注开发者体验、而非自身语义的编程语言。它并没有添加任何运行时结构、不插手性能,而是添加了一套类型系统,并让整个语言社区接纳了这种不用类型也行、没高质量工具也行,还不强调正确性的生态氛围。这简直是个不可思议的壮举。

下一代前端语言是什么样?


所有这一切都表明,TypeScript 早在十年前就做出了一众对自身产生巨大影响的权衡。而随着时间推移,我觉得是时候通过新语言再做一轮权衡了。确切来讲,我们需要一种具备健全性、类型推断和更快编译速度的语言。


要求明确了,但我们该拿什么来换?

健全性


先从健全性说起。下一代语言不再努力对各种 JS 模式进行类型检查,而是以独立语言的形态通过更简单的类型系统将代码编译成 JS。它会将现有 JS 代码视频外部互操作对象,对 JS 代码执行显式运行时类型检查,而且依靠不同的原生语言来实现。


为什么要这样?首先,我个人特别喜欢具备既健全、又相对简单的类型系统的语言。我希望这种语言能够在浏览器中运行良好,而且能顺畅适配现有 Web 生态系统。那些能编译成 Wasm 的语言经常忽略 Web 生态系统中的其余部分,总想在浏览器中建立起基于像素的原生 UI。我觉得这个想法不错,只是跟我的观念相悖。我只想用下一代语言开发常规网站;我不想要纯函数式语言,而更倾向于跟 C 的老派风格相似的语言(对不起了,Elm!);我希望这种语言能体现出我在工具设计上的想法。


那为什么下一代前端语言应该诞生在现在这个时间点?俗话说得好,种一棵树最好的时机是十年前,其次是现在。这十年来,JS 社区已经发生了很大变化。人们开始学习 TypeScript,也习惯于关注编译器并通过类型进行数据建模。现在,很多开发者开始使用 Rust、Swift 和 Kotlin 等语言,也意识到高质量工具的重要性。我不是说十年前的人们会抵抗强调类型安全的语言,但那时候的普及难度确实更高。


明确表达了需求,有些朋友可能觉得这说的不就是 ReScript/ReasonML 吗?没错,确实有几分相像。但在理想情况下,我期待的下一代语言应该能对 JS 代码和特性进行显式运行时类型检查。运行时类型检查是达成良好互操作性的前提,这样我们就能更轻松地随意使用 JS 库。


同样地,我觉得 traits 对用户来说也很重要,它们可以跟其他语言特性映射起来,比如 Java 接口和 C++ 概念。这可太方便了,比如轻松通过 Display trait 输出任意类型。这类需求听起来简单,但确实能大大提升语言的可用性,消除“我该怎么输出这个?”或者“为什么 + 代表整数加法,而 +. 代表浮点加法?”之类特别劝退的问题。再有,我还想去掉一些没用的东西,比如对象、链表、多态变体等。这些都是 ReScript/ReasonML 做不到的,而且我上次试用的时候,ReScript 的开发体验和错误消息也没给我留下深刻印象。


也就是说,我不排除 ReScript 代表着正确方向的可能性。毕竟上次尝试已经是几年之前了,也许是我记错了、也许它已经变得更好了。而且随着同 OCaml 的剥离,ReScript 确实成了很好的前端语言选项,我有必要再确认一下。

类型安全


对于下一代前端语言,我希望能用一种更系统的方法实现类型安全。具体来说,我觉得用 Rust 处理非安全代码块的方式实现 JS 互操作性的好办法。基本上,在调用 JS 的过程中,我们需要将代码打包在一个非安全代码块中。这会是个明确的标志,提醒开发者要认真阅读这段代码。接下来的目标,就是在这些指向 JS 库的非安全代码块上实现 bindings。起初这个过程需要手动完成,但后续应该会有类似 bindgen 和 cxx 的工具出现。


在 JS 中使用非安全代码块好像有点反直觉,毕竟 JS 的安全性又不像 C 那么糟糕。但很多人似乎没意识到,安全的意义并不仅限于安全本身。所谓安全,是指可以任意使用一个值、而不必担心其是否为 null 的保障能力。所谓安全,是在不致引入 Bug 或混乱的前提下保证可变性的能力。Rust 的非安全块概念允许用户既维护自己的安全区,又能与大量非安全代码交互。下一代浏览器语言也该做到这一点。


至于运行时检查,我觉得它仍然物有所值。我们已经在 JS 当中进行过大量模式验证,只是以往只能通过 zod 这类临时性机制完成。在下一代前端语言中,这类功能也许是在运行时出错时对语言类型执行自动转换,也许能对 JS 值进行模式匹配。


对于 WebAssembly,我还是很看好它的发展前景的。但要说它一定能成为浏览器的通用运行时,我个人还是持怀疑态度。也许未来我的态度会有转变,但目前我更多是将 Wasm 看作一种硬件加速器。


当用户的高强度计算任务要求调用固定宽度整数和静态函数时,大家就会使用 Wasm;这就像在需要执行并行计算时,大家会选择 GPU 一样。在这样的模型中,我看到了支持异构编译的潜力——其中部分代码可以被编译成 JS,另一部分代码则可编译为 Wasm。这项工作可以由用户显式完成,由分析自动完成,甚至可以即时完成。通过对 JS 和 Wasm 代码的同时控制,编译器就能最大限度减少跨越语言边界的次数,从而提高性能水平。我觉得未来甚至可以有某种机制将部分代码发送给 WebGPU。


在这样的模型之上,也许我们可以更轻松地编写计算密集型程序,比如机器学习模型、电子游戏和渲染软件。


这种对 Wasm 和 JS 进行分别编译的概念,可以在下一代前端语言中体现出来。我希望其中能有显式整数和浮点类型,最好还能有 Rust 中 usize 那样的显式索引类型。这样如果需要把代码编译成 Wasm,新语言就能利用 Wasm 的固定宽度整数。


还有另一种可能性,就是为语言创建一个子集,在这里整合闭包、垃圾收集等动态特性以提升 Wasm 编译质量。要跟这个子集交互,开发者需要使用 unsafe 代码块,比如 strict 块,或者让该子集通过 dynamic 块跟外部代码交互。这些都是假设,但我觉得其中确有探究的价值。

具体实现


这种新语言可能会用 Rust 来实现。毕竟我个人是 Rust 的粉丝,而且相信代数数据类型、相对更高的代码性能、受限但可用的可变性,以及比较丰富的库组合足以支撑起一套优秀的编译器。


如果 Wasm 后续发展得够好、性能几乎逼近原生水平,那我也会考虑使用由编译为高速 Wasm 代码的语言子集来引导编译器。但这应该不着急,毕竟一个 Rust 编译器应该就够用好多年了。

总结


大家可能已经注意到,类型安全和 Wasm 部分其实就是在从系统语言(例如非安全概念和硬件加速)中汲取灵感,再把它们应用到基于浏览器的语言当中。这是设计使然,毕竟不少最有趣的编程语言都是从系统层面衍生出来的。我只希望这些好点子也能在浏览器上有所体现。


这里我要澄清一下,我所指的下一代前端语言绝不是单一语言,我希望能有多种语言齐头并进、朝着前面提到的方向共同探索。我想激励更多朋友在浏览器语言领域不断创新。当然,我个人也会参与其中,目前正在研究的是名叫 vicuna 的实现方案,但还处于非常早期的阶段。


原文链接:

https://uptointerpretation.com/posts/the-next-browser-language/


2023-01-03 09:4611350

评论

发布
暂无评论
发现更多内容

看完这篇SpringBoot让我在阿里成功涨薪40%,感谢

钟奕礼

Java java程序员 java面试 java编程

SREWorks 数智服务尝鲜,你的数据准备好了吗?

阿里云大数据AI技术

大数据 运维 数据 十一月月更

avm 开发 APP 怎么设置字体

YonBuilder低代码开发平台

使用keytool生成Tomcat证书

源字节1号

HarmonyOS 3重磅版本更新,Mate Xs 2等更多设备支持超级中转站!

极客天地

Java对象拷贝原理剖析及最佳实践

京东科技开发者

Java Apache 编程 对象拷贝 srping

一个漏测Bug能让你想到多少?

得物技术

测试 测试框架 bug修复 漏洞检测 测试技术

创云融达基于 Curve 块存储的智慧税务场景实践

网易数帆

开源 分布式存储 Ceph curve

MatrixOne从入门到实践03——部署MatrixOne

MatrixOrigin

MatrixOrigin MatrixOne

先聊聊「堆栈」,再聊聊「逃逸分析」。Let’s Go!

王中阳Go

Go golang 逃逸分析 内存分配 11月月更

工程团队如何合理地管理数据库访问

Bytebase

DevOps 运维 dba 数据库管理工具 删库保护

《算法》世界二

初学者

算法 网络 11月月更

MASA Framework 事件总线 - 进程内事件总线

MASA技术团队

Framework MASA Framewrok MASA

react源码分析:深度理解React.Context

flyzz177

React

MatrixOne从入门到实践01——初识MatrixOne

MatrixOrigin

MatrixOrigin MatrixOne

「风控算法服务平台」高性能在线推理服务设计与实现

京东科技开发者

Python 数据 高性能 风控 风险控制

深入浅出DDD编程

百度Geek说

架构 后端 领域驱动设计

前后端结合解决Excel海量公式计算的性能问题

葡萄城技术团队

前端 性能 Excel

react源码分析:组件的创建和更新

flyzz177

React

《算法》世界一

初学者

算法 网络 11月月更

如何给 Fiori Elements 应用添加自定义按钮

汪子熙

前端开发 web开发 Fiori SAP UI5 11月月更

AR手势识别交互,让应用更加“得心应手”

HarmonyOS SDK

HMS Core

直播预约|Flink + StarRocks 实时数据分析新范式

StarRocks

数据库

阿里技术风险与效能部负责人张瓅玶:阿里集团深度用云实践

云布道师

云计算

上海 Meetup | 一键获取 11 大云原生热门开源项目技术分享入场券

阿里巴巴云原生

阿里云 开源 容器 微服务 云原生

如何用科学的方法“撞大运”? | 学点运气

赵新龙

CTO 创新 与运气竞争

算法基础:单链表图解及模板总结

timerring

算法 11月月更 单链表

OpenHarmony 3.2 Beta多媒体系列——音视频播放gstreamer

OpenHarmony开发者

OpenHarmony

MatrixOne从入门到实践02——源码编译

MatrixOrigin

MatrixOrigin MatrixOne

下一代前端语言之争,JavaScript 要被新语言反超?_语言 & 开发_Nicholas Yang_InfoQ精选文章