[Web翻译]从2020开始使用Flow

246 阅读10分钟

原文地址:medium.com/swlh/starti…

现在是2020年,你搜索一下 "2020年Flow的状况"。你会发现一些来自Flow的博客,也许是一些比较Flow和TypeScript的博客,一些与关键词 "flow "无关的东西,也许是这个博客。真的没有那么多。

但2020年是我开始使用Flow的一年,在这一点上,我永远不会考虑回到vanilla JavaScript。我将在这篇文章中分享我的Flow之旅,但如果你想找一份入门指南,你可能要去别的地方看看。


我使用React开发JavaScript已经5年了。我过去也用过Java,但我真的很喜欢JS的动态特性,而且从来没有真正错过类型。另外,你可以做一些很酷的事情,比如const [value, setValue] = useState(),其中第一个索引可以是一个字符串,第二个是一个函数。

因此,在2020年前后,我很高兴地在编写JS,并在一个公司内部组件库上工作。在这一点上有相当广泛的用途,我在想,我怎样才能使代码更稳定、更可靠,并且不会有随机引入的错误。我已经在用Enzyme/React-testing-library和storybook分别进行单元测试和可用性交互测试。

我开始寻找,结果发现我所寻找的正是Flow的目标,健全性。

"处于良好状态的状态;健壮性"。

作为参考,与TypeScript相比,他们的主要目标是完备性。这里有一个非常棒的视频,深入介绍了两者的区别,youtu.be/uJHD2xyv7xo


我对我目前的工具相当满意,用Babel转译,Airbnb eslint配置,等等。因此,当我知道Flow可以作为一个辅助工具,你可以简单地把它安装到你现有的工具链上,这让我更加高兴。它还允许我逐步将Flow添加到我的库中,这很重要,因为我可以在项目内部使用它,直到我准备好将它暴露给我的消费者。 我写了一个小的bash脚本,记录了所有Flow类型的文件,当我最终迁移了所有的源代码后,我把它添加到我的lint-staged配置中。

#!/bin/bash
targetFolder="src"
files=$(find ${targetFolder} -type f)
echo "The following files are not flow typed, consider adding \"// @flow\" to the top of the file"
echo "---"
notype=()
for f in ${files}; do
  value=`cat ${f}`
  if [ "${value:0:8}" != '// @flow' ]; then
    notype+=($f)
    echo ${f}
  fi
done
echo "---"
# Pass or fail check
if [ ${#notype[@]} -eq 0 ]; then
  echo "✨ All src files flowtyped, congrats! 🎉"
else
  echo "💥 Please flowtype the files above and try again"
  exit 1
fi

你也可以使用flow-coverage-report,不过因为它解析和运行报告,所以会慢一点,而且可能不会像git钩子那样好用。


好的、坏的、丑的

在我学习的过程中,我发现了很多负面的反馈,以及我自己的缺点。

显然,这些都没有让我放弃,对你来说可能是这样,但我认为正确设定新用户的期望是很重要的,这样他们就不会因为期望不同而感到失望了。

首先,我发现学习曲线非常陡峭,而且文档并不公正。有时它非常全面,而其他时候文档中的部分内容则直接缺失,或者不清楚在哪里可以找到。

更具挑战性的是,我必须弄清楚如何做那些专门用于运送库的事情。有时我会花好几天时间来解决一个问题,有20多个标签深入到兔子洞里。尽管找到答案是很有意义的。

一旦我掌握了它,我发现这个工具非常流畅,我自然而然地发现自己因为编码方式不同而错误地遇到了更少的健全性错误。

我说健全性错误而不是类型错误,是因为我认为Flow首先是一个健全性工具,其次才是一个类型检查器。例如,你可能很熟悉你用react写的第一行代码为

import React from 'react';
import ReactDOM from 'react-dom';
ReactDOM.render(
  <div>Hello World</div>,
  document.getElementByTestId('root'),
);

但在Flow中,它在你的代码周围执行防护措施,以防止尽可能多的运行时错误。因此,你必须这样做,而不是。

// @flow
import React from 'react';
import ReactDOM from 'react-dom';
const element = document.getElementByTestId('root');
if (element) {
  ReactDOM.render(
    <div>Hello World</div>,
    element,
  );
}

这可能看起来超级微不足道,而且相当无意义,但这是我喜欢的东西。它为我的代码设置了合理的护栏,这样我就会自然而然地被引导到更好的标准。

在我展示Flow的第一个代码片段时,需要注意的是,与TypeScript不同,Flow并不阻止任何形式的编译。同样,这也是我的一个粉丝。尽管Flow会告诉你你的代码中有错误,但它并不强迫你的代码是正确的,因为归根结底,它是一个基于人类编写的类型定义的静态类型检查器,并不运行真正的代码。在非常复杂的情况下,它很有可能是错误的。

// $FlowFixMe
const isIcon = children?.type?.displayName === 'Icon';

考虑到上面的react代码片段,我已经测试了它在不同的用例和浏览器中都能工作,但Flow告诉我这是错误的,我还没有想出正确的方法来打这个字,但有了Flow,我就能测试了,因为编译不会被阻止,而且我可以添加抑制注释,这样我以后就能回来了。

总的来说,我发现我遇到的问题从来不是工具的限制,而是我的理解。

第二,Flow最大的障碍之一是它的社区和支持是有限的。

如果你想寻求帮助,你会去的三个主要地方是。

  • Flow的Github问题
  • Stackoverflow上的[flowtype]标签
  • Flow的discord discord.gg/8ezwRUK

问题是,这些地方大部分都很荒芜,每个问题可能只有0-3个活跃的人愿意支持你,而且无论在哪个平台提问,从Flow的维护者那里得到的答案都很不稳定。我个人也曾试图提供力所能及的帮助,但由于我缺乏经验,只能做到这一步。这真的很遗憾,仍然有很多人第一次使用Flow,但他们没有得到所需的支持,无法看到它的好处。

另一个问题是,Flow没有提供官方支持来帮助开发者以一致的方式在他们的库中提供类型定义。

就像TypeScript的DefinitelyTyped repo一样,Flow也有自己的flow-typed repo,社区可以聚集在一起,为可能用vanilla JS或TypeScript编写的库添加类型定义。这里支持相当多的定义,如果你使用社区的标准库,如jest enzyme moment redux,你可能不会遇到任何问题,当你开始使用不知名的包时,你才会遇到问题。当然,你在开发过程中不会受到阻碍,Flow-typed会帮助你存根任何没有类型定义的包,但当这种情况发生时,你会发现Flow的帮助会少很多。

Flow-typed建议你填写你的存根,并提交一个拉动请求,以帮助社区的其他成员。我已经这样做了几次,那里的维护者也很积极,所以这实际上是一个非常好的、简单的回馈Flow社区的方式。

其他人强调的Flow的主要问题是,Flow的需求来自Facebook内部。他们没有同样的要求来运送第三方库或在论坛上提问,因为我认为他们都使用同样的集中式工具,如果需要帮助,他们可以直接问旁边的人。

但这并不全是坏事,这确实意味着Flow得到了Facebook的100%支持,而且每隔几周总会有源源不断的变化发布。比如最近发布的类型优先架构,这应该能极大地提高性能,因为Flow不断吹嘘的一件事是,与其他所有人的代码库相比,Facebook的代码库非常庞大。

除了Facebook,我很高兴看到其他一些流行的库和公司也在使用Flow。

  • Facebook和他们的开源工具(React、GraphQL、Recoil等)
  • VueJS
  • Uber和他们的BaseWeb组件库
  • Styled-components
  • Emotion
  • 可汗学院和他们的库 Aphrodite 和 Wonder Blocks
  • Parcel捆绑器
  • Redux-form和react-final-form(尽管维护者表示他想转到TypeScript)。

所以你可以看到,尽管Flow并不流行,但它绝对没有死。如果你几年前使用过它,那么值得一试,或者重新拾起它,因为我想开发者的体验已经大大改善。我个人没有遇到过任何麻烦。

据我所知,我个人的想法是,我认为Flow刚发布的时候,人们尝试过,有很多问题,比如新版本的不断中断变化和糟糕的开发体验。这使得该库失去了很多吸引力。如果你不知道,Flow在0.X.0下发布新版本,意味着它基本上处于测试阶段。这让很多人感到失望,因为他们质疑产品的稳定性,但我认为这是Flow的人做出的一个非常合理的决定,因为虽然这是一个成熟的产品,但他们仍在进行实验,看看有什么合适的地方,并对架构进行修改,他们不想提供一个虚假的承诺,即每次发布时你都可以盲目地升级你的软件包,而你却没有任何工作。

但我认为在这一点上它是相当稳定的,我从0.121.0开始使用它(在写这篇文章的时候已经在0.130.0上了),我在新版本发布后的几天内升级没有问题。有时升级后会出现新的Flow错误,但这更多是因为Flow能够更好地推断类型错误,而不是随机的假阳性。

而对于那些没有发货的库来说,就更容易了,因为你不需要考虑下游的影响,如果你没有得到任何错误,你就可以走了。

总的来说,我喜欢Flow。我认为它是一个很好的工具,可以做它需要做的事情,它的边缘很粗糙,但我看到了今年的改进和承诺,这让我对未来感到兴奋。

最后,我将留下我希望在未来看到的愿望清单,它们可能不是直接来自Flow团队,也许你可以帮助。

  • 更多来自Flow维护者或一些社区经理的活动,帮助回答问题或将用户引向正确的来源
  • 一个更活跃的社区,对Flow-typed的贡献,使其对新用户更有吸引力,完善支持工具,回答问题
  • 改进文档和更好的快速入门指南,鼓励最终将默认启用的配置设置。
  • 对带有库的运输类型的官方支持和指导

正如你可能注意到的,我对这个工具本身没有任何问题,我相信它只是按照它应该的方式工作(主要是,我知道有一些错误)。它只是有一个巨大的陡峭的学习曲线,没有明确的方向说明如何到达顶端。

如果你对这个工具有实际问题,请发表评论,我很想听听你的限制。


www.deepl.com 翻译