查看原文
其他

Angular 9.0 发布!Ivy 正式抵达!

汪志成 前端早读课 2020-10-12

前言

ts3.8正式版20号发布了。Angular 9就默默的发布了,你有在关注么?本文由@汪志成授权分享。

正文从这开始~~

Angular 的 9.0.0 版本发布了!这是一个跨平台的主版本,包括框架、Angular Material 和 CLI。这个版本默认会把应用程序切换到 Ivy 编译器和运行时,并改进了组件测试方法。

这是 Angular 在过去 3 年中所做的最重大更新之一,我们很高兴能通过各种方式帮助开发人员构建出更好的应用并为 Angular 生态系统做出贡献。

如何更新到版本 9

访问 update.angular.io,获取详细信息和升级指导。为了获得最佳的更新体验,我们建议你先升级到 Angular 8 的最终版。

首先,更新到 8 的最新版本

  1. ng update @angular/cli@8 @angular/core@8

然后,升级到 9

  1. ng update @angular/cli @angular/core

要查看使用此更新内容的关键修改(包括已弃用了哪些 API),请参阅 Angular 文档中的“更新到 Angular 9 ”。

Ivy(常春藤)

默认情况下,版本 9 会把所有的应用程序迁移成使用 Ivy 编译器和运行时的。除了数以百计的 bug 修复之外,Ivy 编译器和运行时还提供了许多优点:

  • 打包尺寸更小

  • 测试速度更快

  • 更好的调试

  • 改进了 CSS 类和样式绑定

  • 改进了类型检查

  • 改进了构建错误

  • 缩短了构建时间,默认启用了 AOT

  • 改进了国际化支持

下面是一些比较值得注意的改进项。

打包尺寸更小

Ivy 编译器的设计目的是删除那些无法通过摇树优化使用的 Angular 部件,并为每个 Angular 组件生成更少的代码。

通过这些改进,小型应用和大型应用可以节省大量成本。

  • 那些没用多少 Angular 特性的小应用从摇树优化中受益最多。

  • 包含很多组件的大型应用从减小的工厂函数体积中受益最多。

  • 中等大小应用的包体积可能只会小一点点,因为它们从摇树优化中受益较少,并且没有足够的组件从减小的工厂函数体积中受益。


测试速度更快

我们还改进了 Ivy 中 TestBed 的实现,以提高效率。

以前,TestBed 会在运行每个测试之间重新编译所有组件,而不管组件是否有任何变化(例如,通过覆写)。

在 Ivy 中,除非已经手动覆盖了一个组件,否则 TestBed 不会在这些测试之间重新编译组件,这样就可以避免大多数测试间的重新编译。

有了这项更改,框架的核心验收测试速度提高了大约 40%。我们期待用户自己的应用测试速度也能提高 40-50%左右。

更好的调试

Ivy 为你提供了更多调试应用的工具。当我使用 Ivy 运行时在开发模式下运行应用时,我们现在提供了新的全局对象 ng 来进行调试。

  • 你可以要求 Angular 访问你的组件、指令等实例

  • 你可以手动调用各个方法并更新状态

  • 如果要查看变更检测的结果,可以使用 applyChanges 来触发变更检测



Ivy 还改进了用于调试问题的调用栈跟踪,比如 ExpressionChangedAfterItHasBeenCheckedError 。以前堆栈跟踪可能没多少帮助:

在 Ivy 中,你可以看到一个更实用的调用栈跟踪,它允许你直接从一个已更改的表达式跳转到模板指令。

例如,如果在上面的堆栈跟踪中单击 AppComponent_Template,就可以在生成的代码中看到抛出该错误的具体代码行:

如果愿意,你还可以进入任何一个框架指令,来了解框架是如何创建或更新你的组件的。

改进了 CSS 类和样式绑定

Ivy 编译器和运行时改进了处理样式的方式。以前,如果一个应用程序包含了对某种样式的竞争性定义,那些样式就会破坏性地相互覆盖。在 Ivy 中,样式将以可预测的方式合并在一起。

考虑下面的模板和组件片段:

  1. <my-componentstyle="color:red;" [style.color]="myColor" [style]="{color: myOtherColor}"myDirective></div>

  1. @Component({

  2. host: {

  3. style: "color:blue"

  4. },...

  5. })

  6. ...


  7. @Directive({

  8. host: {

  9. style: "color:black",

  10. "[style.color]": "property"

  11. },...

  12. })

  13. ...

以前,被最后计算出的那种绑定会胜出,而这可能取决于对这些表达式的修改时机。而如果 myColor 和 myOtherColor 都是未定义的,静态的'red'样式就会被忽略。

在版本 9 中,你可以通过一个清晰、一致的优先顺序来管理你的样式,而这些顺序与时间无关。最具体的样式始终具有最高的优先级。例如,对 [style.color] 的绑定会覆盖 [style] 中的同名绑定。

但是,出于向后兼容性的考虑,我们仍然把 [ngStyle] 和 [ngClass] 的绑定行为保持原样。也就是说,它们的绑定值发生变化时,新值会覆盖任何竞争性绑定。

你可以在文档中的模板语法一章阅读更多关于样式优先级规则的内容。

作为样式重构的一个额外收获,你现在也可以绑定 CSS 自定义属性(也叫 CSS 变量)了。

  1. <div [style. -- main-border-color]=" '#CCC' ">

  2. <pstyle="border: 1px solid var(--main-border-color)">hi</p>

  3. </div>

改进了类型检查

Angular 编译器可以检查应用中的更多类型,还可以应用更严格的规则。这些特性可以帮助你和你的团队在开发过程的早期阶段发现 bug。

除默认值外,我们还支持两个主要的标志来进行额外的类型检查:

  • fullTemplateTypeCheck - 激活这个标志会告诉编译器要检查你模板中的所有内容( ngIf , ngFor , ng-template 等)

  • strictTemplates - 激活这个标志会在类型检查中使用最严格的类型系统规则。

要了解有关模板类型检查选项的更多信息,请参阅文档中的模板类型检查指南 。

改进了构建错误

新的 Ivy 编译器不仅运行速度更快、有更强大的类型安全性,而且还能让所有的错误信息更容易阅读。

在版本 8 或 View Engine 中,典型的编译器错误如下所示:

在使用 Ivy 的 9 版本中,同样的错误如下:

缩短了构建时间,默认启用了预先编译器(AOT)

感谢 Ivy 的新架构,我们对编译器的性能做了很大的改进。

我们会根据应用中普通的 TypeScript 编译开销来衡量编译器的性能。对于我们的文档应用(angular.io)来说,使用 Ivy 时,这个开销从 0.8 倍减少到了 0.5 倍,提升了近 40%。

这些改进意味着 AOT 构建的速度可以显著加快。感谢这次加速,我们第一次在开发模式下使用 AOT。这意味着 ng serve 现在可以从与构建时相同的编译期检查中获益,从而大大提高了 Angular 的开发体验。

由于编译器和运行时都发生了变化,我们也不再需要 entryComponents 。这些组件全都会根据用途被自动发现和编译。

改进了国际化支持(i18n)

国际化已经成为 Angular 的核心特性,你可以在每个语言环境中构建一次应用,并收获高度优化的本地化应用。在 9.0 中,我们通过把 i18n 的工作移到构建过程的后期实现了这一目标。这种变化让我们能把它提速 10 倍。

阅读更多 以了解关于新 i18n 中 @angular/localize 和新的 angular.json 配置的信息。

版本 9 还有其它一些改进

该团队还努力工作,不断提升使用 Angular 的全部体验。

更可靠的 ng update

我们对 ng update 工作方式进行了一些修改,以提高它的可靠性和信息量。

  • 始终使用最新的 CLI。从 CLI 的 8.3.19 版本开始,我们现在在升级过程中使用了 TARGET 版本的 CLI。这意味着,在未来,更新将始终由最新的 CLI 自动处理。

  • 进度更新更清晰。ng update 现在做了更多的工作来告诉你幕后的情况。对于每次迁移,你都会看到迁移中的更多信息。

  • 更容易对更新进行调试。默认情况下,ng update 运行所有迁移,并在磁盘上留下最终结果更改供你检查。版本 9 的更新还引入了新的 --create-commits 标志。当你运行 ng update --create-commits 时,该工具会在每个迁移动作后提交代码库的状态,这样你就可以逐步理解或调试我们对代码所做的更改。

providedIn 的新选项

当你在 Angular 中创建一个 @Injectable 服务时,你必须选择它应该添加到注入器的什么位置。除了以前的 root 和模块这两种选项之外,还有两个新选项。

  • platform - 指定 providedIn: 'platform' 可以在一个特殊的单例平台注入器中使用该服务,该注入器由该页面上的所有应用共享。

  • any - 在每个注入该令牌的模块(包括惰性加载模块)中提供一个唯一的实例。

请到我们的 API 文档中了解详情 。

组件的测试挽具

历史上,测试组件一直靠 CSS 选择器这样的实现细节来查找组件和触发事件。这意味着只要组件库改变了它的实现,就需要更新依赖这些组件的所有测试。

在版本 9 中,我们引入了组件的测试挽具,它提供了另一种测试组件的方法。通过抽象出实现细节,你可以确保你的单元测试被正确的局部化,而且不那么脆弱。

现在,Angular Material 的大多数组件都可以通过这些挽具进行测试,而且我们还会把这些挽具作为组件开发套件 (CDK)的一部分提供给任何一位组件作者。

这是一个在使用组件挽具之前的一个测试范例:

  1. it("should switch to bug report template", async() => {

  2. expect(fixture.debugElement.query("bug-report-form")).toBeNull();

  3. const selectTrigger = fixture.debugElement.query(

  4. By.css(".mat-select-trigger")

  5. );

  6. selectTrigger.triggerEventHandler("click", {});

  7. fixture.detectChanges();

  8. await fixture.whenStable();

  9. const options = document.querySelectorAll(".mat-select-panel mat-option");

  10. options[1].click(); // Click the second option, "Bug".

  11. fixture.detectChanges();

  12. await fixture.whenStable();

  13. expect(fixture.debugElement.query("bug-report-form")).not.toBeNull();

  14. });

而用组件挽具做同样的测试如下:

  1. it("should switch to bug report template", async() => {

  2. expect(fixture.debugElement.query("bug-report-form")).toBeNull();

  3. constselect= await loader.getHarness(MatSelect);

  4. awaitselect.clickOptions({ text: "Bug"});

  5. expect(fixture.debugElement.query("bug-report-form")).not.toBeNull();

  6. });

了解更多关于 Material 的组件测试挽具或用 CDK 构建你自己的挽具。

新的组件

你现在可以在应用中添加来自 YouTube 和谷歌地图的功能了。

  • 你可以使用全新的 youtube-player ,在你的应用中内嵌 YouTube 播放器。当你加载了 YouTube 的 IFrame 播放器 API 之后,这个组件就会利用它。

  • 我们还推出了 google-maps 组件。利用这些组件,你可以轻松地渲染谷歌地图,显示地标,并像普通的 Angular 组件一样与其交互,让你无需学习完整的 Google Maps API 即可使用。

IDE 和语言服务改进

转到定义(Go to definition)和改进的语言服务演示 Visual Studio Marketplace 上的 Angular 语言服务扩展已做了重大改进。随着对性能和稳定性问题的重大架构变革,许多长期存在的漏洞也得到了修复。还包括一些新特性:

  • Angular 模板语法的 TextMate 语法定义,现在可以在内联和外部模板中启用语法高亮显示了

  • 针对 templateUrl 和 styleUrls 的“转到定义”功能

  • 悬浮工具提示中的 NgModule 和类型信息

TypeScript 3.7 支持

Angular 已经更新,可以用 TypeScript 3.6 和 3.7 了,也包括 TypeScript 3.7 中非常受欢迎的可选串联(optional chaining)特性。为了与生态系统保持同步,我们还更新了其他生态系统依赖的版本,比如 Zone.JS 和 RxJS。

谢谢社区

这个版本是两年多来工作的结晶。我们对这项工作的未来及其无限可能感到非常兴奋。如果没有社区数百人的努力,这是不可能实现的。

关于本文 译者:@汪志成 译文:https://zhuanlan.zhihu.com/p/105522992

为你推荐


【第1789期】使用 Angular 打造微前端架构的 ToB 企业级应用


【第1805期】一种前端灰度发布方案

    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存