者|Tobias Merkle
译者|无明
判断一个公司是否开始走下坡路,最可靠的一个方法是看看随着时间推移,它的产品所提供的效用的变化情况。苹果公司在发布 iPhone 时,它的平均产品效用大幅上升,这种趋势持续了一段时间,但当他们开始取消 3.5mm 耳机插孔等重要功能时,这种趋势进入了一种稳定状态。一般来说,大多数公司都会经历这种效用的 S 曲线或抛物线曲线:前者通常会找到自己的利基市场,并且在没有创新的情况下获得丰厚的利润,而后者设法将事情搞砸,让自己的产品陷入混乱。
Angular——慢慢念出这个单词,你会感觉喉咙都会因为这个单词的可怕的形状而发生扭曲,这种形状代表了丑陋、尖锐和虚伪。
将这三个单词与它们的形状相对应时,你会看到 Angular 是多么扭曲
在这篇文章里,我将告诉大家,这个恶魔是如何给我的心灵带来各种不同的创伤的。这个恶魔就是谷歌的心血结晶:Angular。
文 档
你是否也有过类似的经历:你有一个很好的想法,想要把它作为周末项目,你从周六下午开始,然后意识到这个项目至少需要六个月才能完全实现?在谷歌对 Angular 内部工作进行文档化时就经历了这样的时刻。他们把这个工作交给了一个实习生,这个实习生在喝了几个礼拜的浓缩咖啡后,终于搞出了一个 Hello World 代码,并把它作为完整的项目文档。
但这个文档并没有列出任何在使用 Angular 构建 Web 项目时可能会遇到的错误。实际上,你需要的设计模式或核心概念很少出现在这个文档中。如果你想要学会如何使用 Angular 构建一个工具,不得不去购买在线课程,而这些课程会告诉你所有的真相。如果你天真地以为,你可以像 React 或 Vue 开发人员那样,马上就可以开始编写简单的 JavaScript,那就大错特错了!
Angular 的文档看起来更像是一个函数,我可以使用下面的伪代码来表示。
有没有发现,在修复错误时,你必须将搜索关键字中的“angularjs”排除掉,你不能指望使用“Angular”就可以排除掉这个框架的第一个版本的内容。
接下来,在你阅读了足够多的 Stack Overflow“解决方案”之后,你开始意识到,在你的代码和运行在浏览器上的代码之间,不仅存在被编译器破坏的 CSS,当中还有一个黑盒,要求你以某种方式格式化你的应用程序,否则整个项目就会失败,或者更糟糕的是,出现不正确的错误信息。当 Angular 告诉你你做错了什么,你却不敢相信了,因为它甚至都不知道它自己的系统是如何工作的。
Angular 的开发体验就是这样的。你先是全速向前冲,在撞了几次墙之后,你学会以蜗牛的速度爬行,慢慢摸索这个框架可能抛出的任何问题。在这个世界上,没有什么比试图操作这个世界上据称最聪明的公司排泄出的这个可怕和喜怒无常的装置更令人沮丧的了。
请想象一下一辆不能打开引擎盖且只有一个仪表盘的汽车。要是汽车坏了都没办法修理,只能换新。汽车在没有启动的情况下也会往外喷气。厂家也不提供服务手册。如果你想知道它的工作原理,这里有一本 5,280 页的装配指南,拿去吧,祝好运!
架 构
Angular 开发效率很低,开发一个应用程序需要很长时间,而一旦你的应用程序变得比“Hello World”更复杂时,开发速度就会变得更慢。如果 Angular 能够为用户或程序员带来更多好处,例如在发生运行时错误时正常退出,或者更快的编译速度,或者提高应用程序安全性的,这些都是可接受的。但 Angular 并没有这么做。事实上,只要一提到“Uncaught TypeError”,开发者们就会崩溃成堆。
基本上,想要知道 Angular 在做什么,唯一方法是阅读 Angular 开发人员在 GitHub 上提供的数百万行源代码。因为没有人会去这么做,所以 Angular 勉强提供了一两种设计模式用来构建完整的应用程序。你唯一的另一个选择就是让自己沉浸在学习 Angular“工作原理”的狂热之中。
我可以告诉你它的工作原理。组件与服务通信,通过应用程序导入的模块将数据中继到其他注入组件中。还有什么不清楚的?如果你需要进一步的解释,请参考 Material Design 指南。它为你提供了所有必要的组件,而且请务必保证你的设计是像素完美的。这应该很容易吧,因为 Material 和 Angular 都是由谷歌设计的,它们应该可以很好地协同工作。当列表项的填充占据了网页的三分之一,并且打开下拉菜单需要十六秒,这种感觉很棒吧?
Angular 的设计没有哪一部分是为了让你的代码运行得更快。它只带来了三个东西:膨胀的复杂性、完成一个简单功能需要更长的时间,以及为你和团队提供更好的工作保障(如果你们能够日复一日地写出意大利面代码而不会发疯)。
Angular 的 Web 开发体验
打开你的 IDE,输入 IntelliJ IDEA 许可密钥,选择用于“Lint”你的 TypeScript 代码的“Linter”类型。Angular 使用的是 TypeScript,也就是带有类型的 JavaScript。看到了吗,你必须使用与 TypeScript 兼容的 IDE。TypeScript 会出新版本,会破坏你现有的代码和依赖项中的代码,这是预料之中的,而这就是生活!
如果你的依赖库对你从未使用的类的某个属性做了修改,造成了重大变更,请不要惊慌。你只需要为每个构建过程添加手动文件编辑步骤即可,或者,你也可以停留在某个兼容版本,并放弃所有未来可能出现的改进。感谢你选择 TypeScript 和 Angular。
Angular 可以帮你将假的 HTML 元素混合到真实的 HTML 元素中,他们用冒名顶替的东西污染了真正的规范。在创建 HTML 文件域时,请记得使用 Angular 的标记语言,其中包含的指令会让你的代码在调试时变得更加违和。你甚至可以编写自己的指令。所有这些高级的 Angular 风格的 HTML 都让跟踪源错误变得比任何其他库、框架或编码环境都要难。它们会向你提供不正确的错误消息。在花了数天时间查找是否遗漏了某个标签的结束标记之后,你才意识到错误实际上隐藏在条件和神秘的导入指令深处的某个地方。
此外,你还有足够的时间考虑是否继续使用这个漂亮的框架,因为每次你修改了任何一小部分 HTML 都需要重新编译整个应用程序。热加载只是个婴儿玩具,对于应用程序中稍微复杂一点的东西,你都需要等上 60 到 300 秒,哪怕是在一个弹出窗口中为某个元素添加一个 HTML 类。你的很多时间消失在虚空之中。你的很多时间花在查看控制台的消息:“92% chunk asset optimization”上。
被谷歌的悲观编程思维奴役一年之后
Angular 让我成为一个更好的程序员,因为它教会了我如何在站在火山口的同时还能开发出可运行的应用程序。我所做的任何事情都需要走一大段弯路,它们比将数据对象 A 粘附到显示元素 B 的最简单的解决方案要复杂得多。你的 Angular 应用程序中的任何一个错误都将导致其余部分出现意外的行为。我们最终实现了一个系统,应用程序会在每次发现未捕获的错误时重新加载页面,因为这样最简单不过了,不需要去判断这个错误是 Angular 本身的错误还是因为其他错误导致的。
Angular 知识将在我的余生与我如影随形,我根本没有办法摆脱它,它就像强力胶一样粘在我的身上,就像天然乳胶一样彻底堵塞了我的脑洞。如果我要养活家人,我别无选择,只能继续作为一个 Angular 开发者。但仍然还有其他希望,有一天,我可能会加入其他使用其他框架的项目(如 React 或 Redux 或 Vue)。但是,现在我必须继续战斗,紧紧抓住记忆里尚未被谷歌入侵的领地,抵抗谷歌的进一步入侵。我们活着,为的是迎接新的一天。
我现在在 Whiteboard Dynamics 工作,不需要经常花很多时间在拷贝 Angular 代码上,也不需要经常花时间开发每三个月就要重写一次的代码。但如果客户提出要求,我们还是会用 Angular 开发一些东西——正如我所说的,我无法打破这个诅咒——但请相信我:你最好还是选择人们会喜欢使用的开发库。因为这些库只会花费你更少的时间和金钱,而且可以保持你的灵魂永生。
英文原文
https://hackernoon.com/why-angular-made-me-quit-web-dev-f63b83a157af
本文简单介绍了Angular的核心概念与演进过程,从七大核心概念看其背后的设计亮点,通过分析Angular 从框架到平台演进的过程来观察其发展趋势。方便读者对Angular有个直观的全局认识。
Angular 框架有七大核心概念,它们是Angular 的重要组成部分。
Angular 的七大核心概念
1. 模块
在Web 开发中,通过依赖全局状态或变量和保证JavaScript 文件引入顺序来正确加载相应的类库。比如:$ 代表jQuery,在引入$.superAwesomeDatePicker 类库来实现日期选择控件前,需要确保jQuery 已经正常载入。随着项目中的程序越来越大、文件切分越来越细,就会需要一个成熟的模块系统来帮助管理项目文件的依赖关系。在新的语言标准ES 6 中,提供了import 来导入在其他文件中定义的模块,且用export 将诸如jQuery 或moment 这样的依赖导出到业务代码模块中。
2 . 指令与组件
在Angular 中,指令是一个极其重要的概念。指令可以为特定DOM 元素添加新的行为特征,从而扩展元素的功能。指令与HTML 元素属性的使用方式非常相似,但指令的可自定义特性在一定程度上弥补了HTML 元素属性功能的不足,这也为多样的Web前端开发创造了更多的可能性。
实际上,组件是指令的一种类型。以组件为基础的架构模式是现在Web 前端开发的主流方式。不仅仅在Angular 中,在类似的React、Ember 或Polymer 等框架中也是很常见的。这种开发方式就是构建一个个小的组织代码单元,每个代码单元的职责定义清晰,并且可以在多个应用中复用。例如:想使用Google 地图组件,就在页面引入<google-map pointer="46.471089,11.332816"></google-map> 这样语义化的标签。
Angular 全面支持这样的开发方式,在Angular 中组件是“一等公民”。伴随组件而来的是组件树的概念。一般来说,每个Angular 应用都有一棵组件树,由应用组件或者叫顶层的根组件和许多子组件及兄弟组件组成。组件树是很重要的概念,后续章节还会继续讲解。它有很多作用,比如形象地勾勒出UI 界面的组成,这种树形结构也体现了从一个组件到另一个组件的数据流动,Angular 也依赖组件树做出合适的变化监测策略。
一个博客模块的组件树例子如下。
一个博客模块的组件树例子
变化监测是Angular 在应用的数据变化后,用于决定哪个组件需要随之刷新的机制。
3 . 模板和数据绑定
当使用组件标签时,可以通过template 或templateUrl 属性引入HTML 来描述让Angular 渲染显示的界面内容。另外,需要数据绑定机制来实现把数据映射到模板上,或者从模板(如input 控件)中取回数据。
4 . 服务和依赖注入
在Angular 中,如果说组件是用于处理界面和交互相关的,那么服务就是开发者用于书写和放置可重用的公共功能(如日志处理、权限管理等)和复杂的业务逻辑的地方。服务可以被共享,从而被多个组件复用。在Angular 中,一个服务就是一个简单的类。通常在组件中引用服务来处理数据和实现逻辑。
依赖注入可以帮助应用解耦,一般通过对实现服务的类加上@Injectable 装饰器,同时把它注册到Provider(可以在模块、其他服务、根组件或需要注入服务的上层组件中实施),从而将服务提供给调用者使用。
Angular 的项目经理Brad 说过,Angular 现在更像是一个平台,而不是简单的类库或者单一的框架。Angular 在技术架构上倾向于平台化设计,其跨平台开发特性使得周边生态圈变得更加繁荣兴旺。
Angular 平台一览
Angular 框架核心包含了以下内容:
其中,Zones 可以独立于Angular 使用在其他地方,并且已经提交给TC39,TC39 也考虑将其纳入ECMA 标准中。而渲染引擎也是平台独立的,从而可以方便地实施在桌面软件和原生的移动客户端中。
在此之上,还有不少其他的外部工具库,类似于:
除了这些,Angular 周边也有完善的工具体系:
当然,为了开发强大的应用,Angular 在功能开发上也提供了不少辅助模块,例如:
以上内容先后介绍了Angular 核心概念和Angular 平台提供的各种各样的功能,那么Angular 相对于其他前端技术有什么特点呢?
它拥有超快的性能:
其中,Angular 服务端渲染(Server-Side-Render)会在后续章节中进行详细讲解和实践介绍。
它支持完善流畅的开发体验。除上面提到的CLI 工程化的命令行工具、Augury 审查工具和TypeScript 语言服务外,也包括:
Angular CLI 工程化流程
它的社区和周边也强大多样。除了上面提到的Material Design UI、Mobile Toolkit,还包括:
不得不说,基于最新Angular 的ionic 变得越发强大,是用JavaScript 技术开发移动应用的不错选择。同时,利用最新的PWA (Progressive Web App)Web 技术,能够帮助我们很好地打造移动版网站。因此,在本书后面会用专门的章节来讲解这两个热门话题。这就是你应该立即使用Angular 的原因!
在实际项目中,我们可以使用Angular 提供的模块、组件、模板数据绑定、服务、依赖注入和注解等特性来实施应用开发,Angular 社区也提供了各种辅助周边、功能模块和开发工具等。这最终形成了性能强劲、开发体验完善和社区周边强大的Angular。
本文选自《揭秘Angular(第2版)》,获取详情点击“了解更多”
√ 本书为谷歌开发者社区官方指定用书,由谷歌Angular技术开发团队作序力荐。
√ 目前市面上*无仅有的基于Angular 4系统全面介绍这一技术方方面面的书籍。
√ 本书作者团队从Angular早期版本问世以来即投入生产实践,积累丰富实战经验。
√ 首版问世后饱受好评,国内一线前端团队及技术社区资深专家集体亮相盛赞。
*请认真填写需求信息,我们会在24小时内与您取得联系。