微信号:frontshow

介绍:InfoQ大前端技术社群:囊括前端、移动、Node全栈一线技术,紧跟业界发展步伐。

为什么说ReasonReact是编写React的最佳方式?

2018-10-07 19:36 前端之巅
作者|David Kopal
译者|无明

使用 React 开发用户界面是一件很酷的事情,但我们能让它变得更酷、更好吗?要让它变得更好,我们首先需要找出它存在的问题。那么,React 作为 JavaScript 库还存在哪些问题?

React 最初并不是为 JavaScript 而开发

如果你仔细看一下 React,你会发现,它的一些主要原则与 JavaScript 有点格格不入。让我们来谈谈不变性、函数式编程原则,特别是类型系统。

不可变性是 React 的核心原则之一。你不想改变 prop 或 state,因为如果这样做了,可能会遇到不可预测的后果。但 JavaScript 并没有提供开箱即用的不可变性。我们通过约定的方式来保持数据结构的不可变性,或者我们使用 immutableJS 之类的库来实现不可变性。

React 采用了函数式编程的原则,因为 React 应用程序实际上是函数的组合。尽管 JavaScript 提供了一些这方面的特性(如一等函数),但它仍然不是一门函数式编程语言。当我们想编写声明性代码时,需要使用外部库,如 Lodash/fp 或 Ramda。

那么,类型系统有什么问题呢?在 React 中,我们有 PropTypes。我们用它们来模仿 JavaScript 的类型,因为它本身不是静态类型语言。为了利用高级静态类型,我们需要使用外部依赖库,例如 Flow 和 TypeScript。

React 和 JavaScript 的比较

如你所见,JavaScript 与 React 的核心原则不兼容。

有没有另一门编程语言与 React 具有更好的兼容性?

或许 ReasonML 就是这样的一门语言。

Reason 提供了开箱即用的不可变性。因为它是基于函数式编程语言 OCaml,所以也具备了 OCaml 内置的一些特性。Reason 还提供了一个强大的类型系统。

React、JavaScript 和 Reason 比较

Reason 与 React 的核心原则兼容。

Reason

Reason 并不是一门新语言,它是 OCaml 的另一种 JavaScript 风格的语法和工具链,而 OCaml 是一门已经存在了 20 多年的函数式编程语言。Reason 是由 Facebook 的开发人员创建的,他们已经在一些项目中使用了 OCaml(如 Flow、Infer)。

Reason 具有 C 语言风格的语法,这让来自 JavaScript 或 Java 等主流语言的人很容易上手。相比 OCaml,Reason 提供了更好的文档和不断增长的社区。此外,它还可以与现有的 JavaScript 代码库集成。

OCaml 是 Reason 背后的语言。Reason 与 OCaml 具有相同的语义——只是语法不同。这意味着你可以使用 Reason 的 JavaScript 风格的语法来编写 OCaml 代码。因此,你可以利用 OCaml 的强大特性,例如强大的类型系统和模式匹配。

我们来看一下 Reason 的语法示例。

let fizzbuzz = (i) =>
  switch (i mod 3, i mod 5) {
  | (0, 0) => "FizzBuzz"
  | (0, _) => "Fizz"
  | (_, 0) => "Buzz"
  | _ => string_of_int(i)
  };
for (i in 1 to 100) {
  Js.log(fizzbuzz(i))
};

我们在这个例子中使用了模式匹配,但它仍然与 JavaScript 非常像,对吧?

不过,浏览器目前唯一可用的语言仍然是 JavaScript,所以我们需要将它编译成 JavaScript。

BuckleScript

BuckleScript 编译器是 Reason 的一个强大特性,它可以将 Reason 代码编译成可读且高性能的 JavaScript,并移除死代码。如果你所在团队中不是每个人都熟悉 Reason,就让他们阅读编译好的 JavaScript 代码。

Reason 与 JavaScript 非常相似,以至于编译器都不需要对某些 Reason 代码做任何修改。因此,你可以享受静态类型语言带来的好处,而无需修改任何代码。

let add = (a, b) => a + b;
add(6, 9);

这段代码在 Reason 和 JavaScript 中都是有效的。

BuckleScript 附带了四个库:标准库 Belt(OCaml 的标准库不够强大),以及与 JavaScript、Node.js 和 DOM API 的绑定。

由于 BuckleScript 是基于 OCaml 编译器,所以编译速度比 Babel 要快得多,也比 TypeScript 快上几倍。

现在让我们编译我们在 Reason 中编写的 FizzBuzz 算法代码。

通过 BuckleScript 将 Reason 代码编译成 JavaScript 代码

如你所见,生成的 JavaScript 代码可读性很高,看起来就像是由 JavaScript 开发人员编写的。

Reason 不仅可以被编译为 JavaScript,还可以被编译为本地代码和字节码。因此,你可以使用 Reason 开发一个应用程序,然后在 macOS、Android 和 iOS 手机上的浏览器上运行。Jared Forsyth 开发了一款叫做 Gravitron(https://github.com/jaredly/gravitron)的游戏,它就是用Reason 开发的,它可以在我刚刚提到的所有平台上运行。

与 JavaScript 的互操作性

BuckleScript 还为我们提供了与 JavaScript 的互操作性。你不仅可以将 JavaScript 代码粘贴到 Reason 代码库中,还可以让 Reason 代码与 JavaScript 代码打交道。这意味着你可以轻松地将 Reason 代码集成到现有的 JavaScript 代码库中。此外,你可以在 Reason 代码中使用 NPM 生态系统中的所有 JavaScript 包。例如,你可以在一个项目中组合使用 Flow、TypeScript 和 Reason。

当然,事情并没有看上去的那么简单。要在 Reason 中使用 JavaScript 库或代码,首先需要通过 Reason 绑定将它们移植到 Reason。换句话说,需要对无类型的 JavaScript 代码赋予类型,然后才能能够利用 Reason 的强类型系统。

如果要在 Reason 中使用 JavaScript 库,可以通过浏览 Reason Package Index(Redex)数据库看看这个库是否已被移植到 Reason。Redex 是一个网站,它聚合了使用 Reason 和 JavaScript 库编写的库和工具。如果在那里找到了你需要的库,就可以将其作为依赖项安装,并在 Reason 应用程序中使用它。

如果没有找到你需要的库,就需要自己编写 Reason 绑定。如果你是个 Reason 新手,那么要注意,编写 Reason 绑定是一件很有挑战性的事情。

如果你只需要 JavaScript 库中的某些功能,就不需要为整个库编写 Reason 绑定,而是对需要使用的功能或组件编写绑定即可。

ReasonReact

这篇文章是关于如何使用 Reason 开发 React 代码,这要归功于 ReasonReact 库。

或许你还在想:“我仍然不知道为什么要使用 Reason 来开发 React”。

正如之前提到的那样,主要原因是 Reason 与 React 的兼容性比 JavaScript 更好。因为 React 是为 Reason 而生的,或者更准确地说是为 OCaml 而生的。

ReasonReact 之路

React 的第一个原型是由 Facebook 使用 Standard Meta Language(StandardML,OCaml 的表兄弟)开发的,然后被迁移到 OCaml,React 也随之被转录为 JavaScript。

这是因为整个 Web 都在使用 JavaScript,说出“我们将在 OCaml 中构建 UI”这样的话是不明智的。它确实奏效了——使用了 JavaScript 的 React 已被广泛采用。

然后,我们习惯了认为 React 就是 JavaScript 库。React 与其他库和语言一起(Elm、Redux、Recompose、Ramda 和 PureScript),让函数式编程在 JavaScript 中流行起来。随着 Flow 和 TypeScript 的兴起,静态类型也变得流行起来。因此,具有静态类型的函数式编程范式成为前端世界的主流。

2016 年,Bloomberg 开发并开源了 BuckleScript,这是一种将 OCaml 转换为 JavaScript 的编译器。他们因此能够使用 OCaml 的强类型系统来开发安全的前端代码。

函数式编程的普及以及 BuckleScript 的发布为 Facebook 提供了理想的环境,让他们萌生了回到最初使用 ML 语言开发 React 的想法。

他们采用 OCaml 的语义和 JavaScript 的语法创建了 Reason。他们还创建了 React 的 Reason 包装器——ReasonReact,提供了额外的特性,例如在有状态组件中封装 Redux 原则。这样一来,他们让 React 回归到了初心。

React 和 Reason 的威力

当 React 进入 JavaScript 世界时,因为 React 存在的不足,我们需要引入各种库和工具来。这也意味着项目对其他库的依赖性很高。有些依赖库还处在开发阶段,而且还会定期引入重大变更。因此,我们不得不在项目中谨慎维护这些依赖项。

这为 JavaScript 开发增加了另一层复杂性。

典型的 React 应用程序至少具有以下依赖项:

  • 静态类型——Flow/TypeScript

  • 不可变性——immutableJS

  • 路由——ReactRouter

  • 格式——Prettier

  • lint——ESLint

  • 辅助功能——Ramda/Lodash

现在让我们切换到 ReasonReact。

我们还需要这些依赖吗?

  • 静态类型——内置

  • 不可变性——内置

  • 路由——内置

  • 格式——内置

  • ling——内置

  • 辅助函数——内置

在 ReasonReact 应用程序中,你不需要这些依赖项,因为语言本身提供了很多关键特性。维护软件包将变得更加容易,并且不会随着时间的推移而增加复杂性。

这一切要归功于已有 20 多年历史的 OCaml。它是一门成熟的语言,所有核心原则都很稳定。

总 结 

起初,Reason 的创建者面临两种选择。采用 JavaScript 在一定程度上会让它变得更好,但同时也会背上一些历史负担。

最终,他们走的是一条不一样的路。他们采用了 OCaml,一门成熟的语言,具有出色的性能,并对其进行了修改,让它看起来很像 JavaScript。

React 也遵循了 OCaml 的原则,这就是为什么在 Reason 中使用 React 会获得更好的开发者体验。React 和 Reason 是构建 React 组件的一种更安全的方式,因为有强类型系统的支持,你不需要处理大多数在 JavaScript 中存在的问题。

下一步

如果你是来自 JavaScript 世界,就可以轻松地上手 Reason,因为它的语法与 JavaScript 很像。如果你一直在使用 React,那么接下来会更轻松,之前所有的 React 知识都可以继续派上用场,因为 ReasonReact 具有与 React 相同的模型和非常相似的工作流程。这意味着你无需从头开始,在开发过程中边用边学 Reason。

在项目中开始使用 Reason 最好的做法是循序渐进地进行。你可以将 Reason 代码用在 JavaScript 中,反之亦然。对于 ReasonReact 也是一样的。你可以将 ReasonReact 组件用在 React JavaScript 应用程序中,反之亦然。这种增量方法已被 Facebook 开发人员所采用,他们在开发 Facebook Messenger 时就大量使用了 Reason。

 相关链接

ReasonML:https://reasonml.github.io/

ReasonReact:https://reasonml.github.io/reason-react/

OCaml:https://ocaml.org/

BuckleScript:https://bucklescript.github.io/

Belt:https://bucklescript.github.io/bucklescript/api/Belt.html

英文原文:

https://medium.freecodecamp.org/psst-heres-why-reasonreact-is-the-best-way-to-write-react-5088d434d035

 活动推荐

前端发展至今,社区中出现了很多高质量的框架与解决方案,在有限的研发资源下,团队需要尽可能多地使用社区的方案解决问题。12 月 7-8 日在北京国际会议中心举办的 ArchSummit 全球架构师技术峰会邀请了超过百位的国内外专业讲师,并设置了前端技术专题,分享他们的最新黑科技和研发经验。

目前大会 8 折优惠购票火热进行中,扫描以下图片二维码或点击“阅读原文”了解更多详情!

如有疑问欢迎咨询票务经理灰灰:17326843116(微信同号)

 
前端之巅 更多文章 重磅!尤雨溪发布Vue 3.0开发路线 Create React App 2.0正式版发布,不再支持 Node 6 过来留言,有书相送! Next.js 7.0正式发布:重新编译速度提高42%,支持WebAssembly CodeSandbox推出容器,进化为WebIDE
猜您喜欢 [译] NPM 与前端包管理 Intel也有黑科技:VROC(NVMe RAID)安装试用 小米广告交易平台(MAX)的架构实践 如何高效开启你的顾问人生模式 ✪​原创|大数据从何而来?你不得不知道的7个数据源供应平台