我已经使用TypeScript两年多时间,是时候写一两篇文章来总结一下了。
谷歌在很早之前就张开双臂拥抱Web应用程序,Gmail已经发布14年了。当时,JavaScript的世界是疯狂的。Gmail工程师不得不为IE糟糕的垃圾回收算法捏一把汗,他们需要手动将字符串文字从for循环中提取出来,以避免GC停顿。最近,我找到了那个时代一个设计文档,是关于如何“minify” JavaScript文件的,只不过一些工具仅用于Windows平台。这些事情在今天看来是难以想象的。
多年来,谷歌构建了大量的基础设施,用于开发大型的JavaScript应用程序。例如,他们开发了一个模块系统,可以让源文件自描述它们之间的相互依赖关系,还有一个捆绑器,可以将源文件合并在一起,并缩小为可与浏览器兼容的工件。另外还有一个工具,它通过动态加载入口点来分析应用程序的依赖关系图,并抽取服务的公共子模块。还有非常常见的服务器端渲染。所有这些概念对于今天的Web开发人员来说都是很熟悉的,但谷歌的技术栈总是很超前,它们并行演进,虽然在概念上很相似,但实际上却完全不同——不同的流程、工具,甚至名字都不一样。
另一个有关并行演进的例子:谷歌、Facebook和微软各自构建了相似但不兼容的编译器,这些编译器向JavaScript中加入了静态检查。谷歌的编译器通俗地称为Closure(不要与Clojure这门编程语言混淆,另外请注意,ClojureScript使用的是Closure编译器)。
谷歌的JavaScript技术栈非常棒,其中一些部分已经超越了当今最好的技术。例如,Closure编译器可能仍然是最复杂的JavaScript优化器,可以使用类型信息来优化代码、跨热加载块边界进行函数内联,以及将无用的代码剥离成单个符号。
当然,谷歌的JavaScript技术栈也存在一些问题。Closure是JavaScript的一种带有静态类型的变体,通过注释来引入语言新特性。Closure具有不可预测的语义,它运行速度慢,容易出现bug,除非你很小心,否则它很容易就让你的代码变得一团糟。它是开源的,但除了一些能够招到谷歌前员工的公司之外,行业中很少有公司会使用它。在谷歌内部,我认为JavaScript的声望并不高,部分原因在于我们的工具,它将静态语言的冗长性与动态语言的不可预测性结合在了一起。
而在谷歌之外,JavaScript在不断演进,变得越来越流行。为了解决IE垃圾回收器的问题,我们开发了Chrome,然后v8出现了,继而nodejs诞生,所以今天的大多数Web工具都是用JavaScript编写的。模块系统(UMD、AMD、CommonJS)大肆膨胀,ES6也发明了自己的模块系统,但由于某种原因,与其他模块系统不兼容,非常可惜。npm统一了工具和库的共享方式。Webpack可以在你开发代码的同时将模块动态加载到正在运行的应用程序中。
但谷歌没有使用这些东西。我们有一个类似SASS的CSS预处理语言,只是它不叫SASS,而且没有人喜欢用它。花哨的块分割器并不支持第三方JavaScript库,部分原因是这些工具的出现早于JavaScript的库生态系统。
这些都已经成为历史。你可以说我们不应该忘了我们是如何到达这里的,但不管怎样都无法改变我们已经达到这里的事实。或许我们更应该关心接下来要去哪里。我们有几个选择。
第一个选择是放弃这个已经破败不堪的星球,去到一个没有JavaScript的新星球。如果我们在GWT(一个将Java编译为JavaScript的谷歌项目)或Dart(一个将其他语言编译为JavaScript的谷歌项目)或WASM或(Clojure?Haxe?Elm?)上做更多的投入,根本就不需要担心JavaScript!
作为编程语言爱好者,我觉得这个主意不错。不过长话短说,这里有一些问题:首先,采用不同的语言对于我们现有的数百万行代码来说并没有任何意义——“使用新语言重写”在某些情况下可能是正确的选择,但很难做到充分利用Gmail工程师的时间。其次,采用不同的语言对于我们想要聘请的前端程序员来说一点帮助都没有,等于说他们之前的经验都用不上了。
改变一切的对立面是不做出任何改变。JavaScript世界充斥着业余代码和leftpad灾难。一个优秀的工程师总能适应特殊的前端开发方式,我们总能改进或构建更多属于自己的工具。我们构建的应用类型——谷歌搜索主页每天的点击量超过数十亿次——与其他人构建的网络应用程序不同,我们的工具不仅优秀,而且都是必需的。我认同这种观点。我认为存在某种权衡,一方面,构建我们自己的工具是有意义的,另一方面,我们已经远离了主流,以致于我们的工具变成了一种负担。关键在于,我们现在处于这个权衡的哪个位置上,我相信我们离后者更近。我们从对LLVM/Clang的贡献中获益,因为我们依赖于C++,但是我们不会从构建自己的LLVM中获得更多额外的价值。
我的团队一直在追求中间那条路:在必要的时候逐步采用一些外部工具。这项任务并不那么有趣——我们不可能只是简单地把遗留的那套东西直接丢掉——但我喜欢谦虚一些,向外看,而不是向内看。
在谷歌JavaScript孤岛和大陆之间架起桥梁的首先是一个静态检查器:
(1)它不是我们内部开发的
(2)已经很流行,与我们现有的代码相似
(3)旨在为JavaScript做桥接
(4)支持大规模开发
这个工具就是TypeScript。Closure编译器的优势在于它的优化输出,而TypeScript具有出色的用户接口,但不提供优化。这两个工具是互补的,并且在处理某些任务时可以进行分层式协作。
使用TypeScript给我们带来了很多好处——从IDE风格的代码完成到从StackOverflow上获取相关问题的答案。我们所要做的工作主要是集成:将我们的应用程序逐步迁移到TypeScript,而不是从头开始重写。在与谷歌范围内的构建系统集成时,我们非常谨慎,我们进行增量编译,这对大型应用程序来说至关重要。一个模块发生变更,只要不影响公开的API,就不应该导致下游模块进行重新编译。与Closure类型/模块系统的集成意味着ES6 TypeScript模块可以导入谷歌模块系统模块,反之亦然,而且可以保留大部分类型信息。
在谷歌,现在到处都可以看到TypeScript的身影。如果你在使用谷歌的产品,很可能是在与TypeScript代码打交道。TypeScript本身就是一系列有趣的方案的折衷,它在静态类型的编程语言与自由转换的JavaScript生态系统之间做出了权衡。这就是我们的工程师要做的事情:做出有趣的权衡,尝试在各种问题之间找到平衡点。我希望后面能够写更多文章分享这些年发现的一些有趣的事情,我认为TypeScript在这个领域内达到了很好的平衡。
英文原文: http://neugierig.org/software/blog/2018/09/typescript-at-google.html
感谢覃云对本文的审校。
来自:http://www.infoq.com/cn/articles/typescript-at-google
- 本文固定链接: https://zxbcw.cn/post/6086/
- 转载请注明:必须在正文中标注并保留原文链接
- QQ群: PHP高手阵营官方总群(344148542)
- QQ群: Yii2.0开发(304864863)