The long way to Angular and TypeScript | Part.2

引言

在一年多之前,我写了一篇文章《The way to Angular 2 | Part.1》介绍 Angular,最初打算持续完成一个系列,然后在我写完文章之后,Angular 和 TypeScript 都发生了相当大的变化,整个系列也搁浅了。 如今,我打算换一个角度,继续这个系列。

为什么要使用 Angular

angular.io_features

为什么要使用 TypeScript

www.typescriptlang.org_index.htm

你愿意使用 Angular 吗?

1. 关于 Angular 这个名字

首先你需要理解并接受,Angular 特指 Angular 2及以后的版本,而以前所说的 Angular 1现在就是 angularjs。

2. 来看一下初始化一个 Angular App 的代码

// src/app/app.modules.ts
import { NgModule }      from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
@NgModule({
  imports:      [ BrowserModule ],
  providers:    [ Logger ],
  declarations: [ AppComponent ],
  exports:      [ AppComponent ],
  bootstrap:    [ AppComponent ]
})
export class AppModule { }

// src/main.ts
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';
    
platformBrowserDynamic().bootstrapModule(AppModule);

3. Dependency injection

早在 angularjs 的时候,它的依赖设计就颇具争议,现在到了 Angular 也一样。依赖注入深入到了 Angular 的方方面面,是它实现模块化、作用域管理的核心之一。 那么又回到了上面的问题,你必须记住,要在合理的 Module 层和 Component 层注册 providers,也对你的整个应用规划提出了很高的要求,也许为了方便,你会选择在 Root AppModule 直接注册所有服务,来方便在所有子模块(甚至没有子模块,只有子组件)里注入服务。 大多数时候,你可能很难感受到它给你带来的好处,毕竟你在使用没有依赖注入设计的前端框架进行开发得时候,也很得心应手。 当你需要将很多原本一个函数,一个 JavaScript 模块就可以完成的工作,提升到服务的层面的时候,你也许就不会喜欢这种设计了。

4. 关于各种核心架构

rxjs,zone.js,SystemJS 你能接受它们吗? 在 Angualr 的 HTTP 请求库重写成 HttpClient 之后,rxjs 的 Observe 模式已经是主流,那么你有没有理解 Observe 模式的意义在哪里? Do Observables make sense for http? 看完上面这篇讨论,你可能会有一些收获。然而你依旧需要改变你原先的习惯和想法,去主动尝试这些新的模式。

你愿意使用 TypeScript 吗?

在最初的时候,我一直认为,就像官方宣传的那样:

Starts and ends with JavaScript

从 JavaScript 到 TypeScript 应该不是一件很困难的事情,并且最初我也是这么感觉的,但随着 TypeScript 的版本不断更新(本文撰写时,最新稳定版本是2.4),我编写的应用、代码也越来越复杂,我才突然发现,并不是这么一回事。

你会选择「真正」地使用 TypeScript 吗?

给「真正」加上引号,实际上,在我过去三年使用 TypeScript 的经历中,不管是我自己编写的代码,还是我接触的其他使用 TypeScript 开发的项目,有很多都并没有真正地使用 TypeScript,其中相当一部分,只是利用了 TypeScript 的编译器,将它作为 Babel 之类的 JavaScript 代码转换器的替代品。例如:

阻碍我「真正」使用 TypeScript 的原因是什么?

我当然理解使用 TypeScript 的好处是什么,也知道它的各种特性和语法,那为什么我还是没能写出「真正」的 TypeScript 代码呢?

使用 TypeScript 成为一个包袱

如同我在上面提到的,很多情况下,TypeScript(的编译器)被用来替代 Babel 等工具,甚至仅仅是用来处理 ES2015+ 的代码,在这种情况下,其实你有更好的选择。 比如你面对的浏览器或者 Node 环境,其实很大程度上已经支持了 ES2015+,大量特性都可以不用转换直接使用,而一些没有被支持的特性,你可以选择性地安装对应的 Babel 插件来支持,这样,不管是从维护性,还是从最终代码性能的层面,都会更有优势,而不需要用 TypeScript 一股脑的转换到 ES5。

TypeScript 让我觉得无形增加了工作量

你可能立刻就要反驳我了,没关系,我认为每个人都会有自己的观点,而我也可以说说自己的处境。 大多数时候,我维护的是一些编写了一次之后,只剩下维护,并且没准下一次就会直接推到重来的代码。我可以给某一个数据模型定义对应的 interface,并且在所有它被使用的地方加好类型声明,但是很可能它参与的代码总量,还没有声明它的 interface 的代码来得多。很可能它因为各种各样的历史原因,会是两种,三种甚至完全不确定的类型,这时候,我想我会选择给它一个 any。 我也并没有维护一个很大规模的应用(代码库),也没有超过两位同时维护同一份代码的同事,我的绝大多数代码都属于就地调用,声明的地方和调用的地方可能不超过一个屏幕。

TypeScript 引以为傲的工具支持并没有太大优势

这是我想要特别提到的一个点,不少人觉得,TypeScript 的工具支持(编辑器等),自动完成提示,类型解析,定义追溯等也是它非常大的一个优势,但是实际上,除去在 VS 家族(studio 和 code),像是在 WebStorm 等平台上,这些特性并不一定需要通过 TypeScript 来实现。利用 JSDoc 之类的语法,在 JavaScript 中,我们也可以实现相同的效果,可以定义属性类型,定义方法参数、返回值,由此,在编辑器中,我们一样可以实现上述效果。

为什么我还在坚持 Angular 和 TypeScript

这可能是你最关心的问题,既然这两个技术有上面那些让我觉得困惑、难受的地方,为何我还在主动使用它们?

优秀的技术终将有它的价值

  1. Angular 的架构设计,让我感受到了一个前端框架的魅力。
当你在使用 Angular 开发一个应用时候,你会主动去思考 Module、Services、Component 的规划,合理安排它们相互之间的依赖关系,主动去用更优美的架构实现你的应用,此处再次贴出这张官方架构图: ![](https://i.loli.net/2017/08/31/59a7b38faf46e.png) 而不是把你的所有逻辑都糅杂到一个组件里面,然后在另一个组件里面复制一遍。
  1. TypeScript 的价值
TypeScript 的编译器的价值很容易被人忽视,一个优秀设计的编译器,能给你非常大的帮助,不管是当你在编辑器中编写代码,还是使用 TSC 编译代码的时候,类型检查都可以避免非常多的问题。 我当然不希望我辛辛苦苦编写的代码,仅仅因为一个参数类型的错误而导致额外的麻烦,毕竟 JavaScript 中的隐式类型转换有便利,也有不利。 相比起写更少、更优雅的代码(这是 ES2015+ 给我们提供的)来说,编写更加安全可靠的代码显然价值更大。

Keeping Up with the Emerging Technology

我直接引用了 John Papa 的这句话,新兴的技术推动了 Web 开发的前进,我想现在大家都没有兴趣回到那个用 ES3、ES5 和 jQuery 去和跨浏览器兼容搏斗的年代了。 主动追求更加先进、优雅和完备的技术,应该是一件值得骄傲的事情。正如当初以 ember 为代表的一众框架,将 MVC/MVVM 架构引入了 Web 开发,从而改变了整个行业一样。同样还有 HTML5、CSS3、ES2015+ 的大量贡献者,真正推动了现代 Web 开发的发展。

These tools are the current answer to how we move forward without leaving behind our customers.

后续

相比起这些值得吐槽的缺点来说,Angular 和 TypeScript 还有更多值得我们去使用的优点。

参考文献

  1. Angular.io
  2. TypeScript
  3. Understanding Angular modules (NgModule) and their scopes
  4. Do Observables make sense for http?
  5. Understanding ES5, ES2015 and TypeScript
  6. Wikipedia: Anders Hejlsberg