JavaScript 生态之乱象

(原标题:作为一名 web 开发者,我已经被一个极度简单的 app 卡了 10 天)

我是一名全职开发者。我大部分工作的内容是网站的全栈开发。偶尔,我也用Python 或 Ruby 写写后端的服务器,有时写点儿 C# 。我还用 C++ 或 Node.js开发一些命令行工具,我发现 Clojure 很有意思,我接触 web 开发是在多年以前,那时用的是 Perl 和 PHP ,而在我首次进入职业开发道路的时候,我写了几年 Java 。

在我第一次接触 JavaScript 时,它主要用来往网页上写“现在是几点”这样的东西。我说的是上个世纪 90 年代,每个人都想让自己的页面变得更加有趣,_动态地_告诉偶尔到来的访客今天是周几(哇!),并以此为乐。这些年来,我们都发现 JavaScript 能做的远不止这些,我们都想要全效的 DHTML (Dynamic HTML)。是的,我们的 HTML 变得充满_动态效果_了!

在过去的几年中,我用过一些不同的框架开发过几个比较大型的单页应用,有时候忙起来,JavaScript 代码组织的极烂,把 jQuery 调用写得到处都是。

大概 10 天前,我想开发一个简单的 SPA 给自己用,把一个小工具改写成一个小项目。这一般也就是两三天的功夫。在过去的这半年,我一直在用 C# 写一个桌面应用。这是一个相当无聊的工作流管理程序,有一个网络服务后台和 winform 客户端。

当我起念要开发这个小型 web 应用的时候,我便预见这是一个尝试新技术的好机会,我曾在网上读到过一些,以此刷新我的 web 开发工具库并收获一点乐趣。想想都觉得激动,没什么太复杂的东西,也不用太费劲。

可事实证明,我根本无法着手编写这个简单的项目,因为我陷入了一种分析瘫痪循环

到目前为止,我已经有了四到五次“失败的开始”。问题的核心是在 选择 上,以及要如何从过度繁多的工具库中挑选出合适的工具。

谁想写这样的代码

MyNotReallyClass.prototype.getCarrots = function () {}

ES6 都快 落地了,它有了 近似 真正的类,并且 差不多 得到了完好的支持?市面上有那么多的打包工具,谁还想写十行

<script src="library-12.js"></script>

在页面的顶部?有那么多的框架帮我们组织应用,谁还要写这样的代码

$(‘.carrots’).innerHTML(myJson.some.property\[3\])

谁又想忽视如今编写浏览器端 Javascript 代码有了 Node.js 命令行工具辅助的事实?

所以我深入研究这些新事物,这些我曾经用过现在忘了或是发展了的事物。可天知道,除了一点 HTML 表单,我一直没能取得任何的进展。

请记住,这是一个简单的个人项目,我主要是想找点儿乐子,因此我的脑袋被设置为零容忍模式。一旦什么东西令我厌烦,我就抛开它去寻找其它的东西来抚平我的体验。

这是今天在 Javascript 领域尝试新技术我所期待的几个东西,例举如下

首先,我想试试 Typescript 。在过去几个月中我一直写的是 C# ,我知道有一门静态类型的语言是多么棒的一件事:它让你对自己的代码更加自信,重构起来更为便利,IDE 自动补全,不论你写的类有多么的混乱,你都只要写一半的代码。

我需要两个外部的库来实现核心功能。它们不在 DefinitelyTyped 中,因此我花了半天时间学习 .d.ts 文件以及为这几个库写包装类。谈不上富有成效,但我还是写出来了。

我一开始就想用 Mocha 添加一些测试。这里是噩梦的开端。我尝试为项目添加多个 .tsconfig.json 文件,但 JetBrains WebStorm 不支持,因此编译器不断地把测试代码和实际代码打包在一起。我开始阅读指导,查看 gist ,StackOverflow 的相关问题。使用这个 Gulp 配置文件。你必须先编译脚本,然后再对它们进行测试。但如果你测试也是用 Typescript 写,那你还得用这个 Gulp 插件不过它对 watchify 的支持不好。第一天过后,我有了一堆被合并、编译过的文件,src 和 dest 、test 文件夹触发了一些不必要的任务。我已经弄不懂底层究竟是怎么一回事。当编译代码时,依赖在哪里,我是应该 import 还是 require或是 reference 这个文件?我去他大爷的

之前,我曾在一个小项目中简单地用过一点 React ,体验还不错。我想再试试它。为此我添加了一些 Gulp 配置。这里的问题出在了 React 本身。我已经设计好了我的数据模型,但是 React.js 喜欢把数据模型、状态、属性混在一起,为此我不得不重新思考这个问题。我的应用很简单但是表单很密集。你猜怎么着,React 官方文档说:

如果你是初次使用这套框架,注意 ReactLink 在绝大多数的应用中是用不到的,而且你应该小心使用它。 
在 React 中,数据单向流动:从拥有者到子对象。这是因为在冯·诺依曼计算模型中数据只能单向流动。你可以把它当做“单向数据绑定”。

说得很有道理的样子,但是一个表单,尤其是一个重表单,本质上就是一个双向绑定的东西。因此,React 在没有插件和 mixin 的情况下,对大量输入的支持不好。你得装饰所有的 input 框来支持这个功能。很快,事情就变得让人厌烦起来。还有,说到 mixin ,我用的是 ES6 但 React 的类不支持。去他大爷的

所以,我需要大量的双向数据绑定,对吗?Knockout 在这方面做得很出色,我也有过一点使用它的经验。再一次,我尝试使用 ES6 的类,但是 this 的绑定又乱作一团。不用类的话,代码很快变得混乱起来。在尝试了 React 后,Javascript 和 HTML 混起来看丑的一逼。HTML 包含在 Javascript 中,不过这还算有点道理。至少你能够组织合理的逻辑单元,并使它们内聚。

(这是一条愤怒的旁注,似乎不论我选择什么构建工具,都需要有一些观察任务跑在后台,来进行编译,检查,打包,测试。我在编辑器里写了一些东西,然后 Cmd+S 保存,Cmd+Tab 切回浏览器,再 Cmd+R 刷新页面,可我并没有察觉到有什么变化。你猜怎么着,有时候我动作比编译器快,或者是“观察”任务没有检测到我的编辑动作,抑或是它抛出了一个异常。)

所以,甚至在我开始写一行代码之前,就不得不先选好我所要用到的工具(依赖管理,打包,测试,构建等等),而且每一种选择都有众多的替代品,它们要么相互竞争,要么相互补充,或多或少更接近标准,或多或少更为成熟,又或者两个合在一起用效果多多少少更好一点。

你想使用哪种风格的 Javascript ?你要用转译器吗?用什么语言?要用 Grunt 吗?Gulp?Bower?Yeoman?Browserify?Webpack?Babel?Common.js?Amd?Angular?Ember?Linting?我究竟在说什么?我是不是把东西给搞混了?我困惑了吗?去他大爷的?对,去他大爷的。

如果你还认同我所说的话,现如今,制作一个 web-app 就好像在玩一个非常困难的互动小说游戏(如魔城)。让我们穿回多年以前来开发一个程序

你置身于一个程序房间。你只能开发命令行程序。出现在你面前的是 C 语言和 Assembly 语言

> 用 C 语言

好的,你可以开始编写你的程序

现在,让我们回到 2016 年:

你置身于一个 web 应用的房间。

> 开发 web 应用

你是要开发游戏吗?不妨考虑使用 Unity 或者 GameMaker 或类似的可为 web 导出的软件

> 开发 web 应用

你有没有想过用 web 技术来开发桌面程序呢?比如,你可以使用 NW.js 或 Electron

> 开发 web 应用

几门语言出现在了你的面前。你看到 Javascript,Coffescript,Typescript,Clojurescript,Dart,asm.js。如果你想浏览总共127种可用语言,输入“更多”。

> 用 javascript

出现了两门语言:ES5 和 ES6

> 用 ES6

你来到一间转译器的屋子。你看到了 Babel,Traceur 或者你可以寄希望于浏览器已经支持了你将要用到的特性。输入“更多”查看更多转译器或者阅读“转译器工具(又名——死灵之书)”

> 使用 Babel

你来到任务走廊。你看到一只 Grunt 在一个角落,一只 Gulp 在另一角。一只 Babelify 攻击了你,众多 Webpack 正在聚集。在附近的房间里,你听到 Browserify 在叫喊,它正在与 Require.js 战斗。在你的背包中有“转译保存”。

> 离开这里

在近处的壁龛中有一只 Yeoman 在发光。你手握 npm 但你的 project.json 坏了。在地板上还躺着 Gruntfile,.jshitrc,.babelrc 和 tsconfig.json。你远远听见一只 Broccoli 和一只 Jasmine 在呼号。

> 操他大爷

你不能操他大爷,因为七个房间以前你选择了“npm install node-jsx”,而它目前还不兼容你的配置“操他大爷”

> 退出。

更新

这篇文章在 Hacker News 上受到了一些关注。我发现有些评论还真是够讽刺的:

> 我已经设计好了我的数据模型,但是 React.js 喜欢把数据模型、状态、属性混在一起,因此我又不得不重新思考这个问题。

用 Redux

> 这个 Gulp 配置文件…

用 Webpack

ClojureScript。好好学吧;ClojureScript 社区会积极跟上时代潮流,又或许偶尔你也可以为社区尽一份力。是的,你得做一些底层的调试工作,不过以你的技术背景应该是小菜一碟。

你该使用哪种组合工具?如果你不知道从何下手,可以试试 Ember ——这里没有其它工具有的那些问题,也可以在这里找到解决那些问题的工具。

由此,我猜测,跟社区讨论我因从过量工具库中选取和调研工具所导致的“分析瘫痪循环”的结果是被社区建议去尝试,花时间学习和再多研究四门我先开始没想到过的技术。Javascript,干得漂亮!