Angular8新特性

    |     2020年4月11日   |   web前端技术   |     0 条评论   |    1082

Angular 团队发布了 8.0.0 稳定版。NgConf 2019 上已经提到从工具到差分加载的许多内容。下面按新功能做一份速览,方便对照升级。

这一版里更值得先记住的是:差分加载(减小包体积)、loadChildren 改成动态 import、ViewChild / ContentChild 必须带 static 标志,以及 Ivy、Bazel 仍处于可选预览。

特性 状态 / 作用
差分加载 按 browserslist 拆包,旧浏览器走带 nomodule 的 polyfill
Ivy 可选预览;新应用当时仍建议视图引擎
Bazel 可选预览,预计进 CLI v9
懒加载 废弃字符串 loadChildren,改动态 import
ViewChild 必须提供 static: true/false

一、差分加载与 SVG 模板

根据 browserslist,构建时 Angular 会为不同浏览器创建单独的 polyfill 包,从而减小捆绑包。做法是给旧环境脚本加上 nomodule,阻止它在支持 module 的现代浏览器里执行:

<body> 
  <pp-root> </ pp-root>

<script type =“text / javascript”src =“runtime.js”> </ script> 
  <script type =“text / javascript”src =“es2015- polyfills.js ” nomodule > </ script> 
  <script type =“ text / javascript“src =”polyfills.js“> </ script> 
  <script type =”text / javascript“src =”styles.js“> </ script> 
  <script type =”text / javascript“src =”vendor .js“> </ script> 
  <script type =”text / javascript“src =”main.js“> </ script> 

</ body>

nomodule 是布尔属性:现代用户代理跑模块脚本,旧用户代理跑经典脚本。

SVG 作为模板

现在可以把 SVG 文件当作模板,不再只能用内联 HTML 或外部 HTML。

@Component({
  selector: "app-icon",
  templateUrl: "./icon.component.svg",
  styleUrls: ["./icon.component.css"]
})
export class AppComponent {...}

二、Ivy 渲染引擎(实验)

Ivy 在 Angular 6 就提出,8 仍是试验。可通过 enable-ivy 标志试用。Igor Minar 在 ngConf 2019 建议:新应用仍推荐视图引擎。

To enable Ivy in an existing project set enableIvyoption in the angularCompilerOptions in your project’s tsconfig.app.json

现有项目在 tsconfig.app.json 的 angularCompilerOptions 里设 enableIvy:

“angularCompilerOptions”: {“enableIvy”:true}

也可以用新引擎创建应用:

ng new my-app --enable-ivy

Ivy 的好处(前三项预计在 Angular 9):编译更快、模板类型检查更好、包更小(I/O 19 上 Vikram Subramanian 展示过 4.3 KB 的应用)、向后兼容、以及可以调试模板。

三、Bazel 与 Builders API

Bazel 是 Google 开源构建工具,内部用了很久,当时对所有人仍是「选择预览」,预计包含进 @angular/cli 第 9 版。好处:首次构建较慢但并发更快(Angular CI 从 60 分钟降到 7.5 分钟);增量构建只编改过的部分;Bazel 文件默认隐藏,可弹出查看。

添加支持:

ng add @ angular / bazel

或用 Bazel 建新应用:

npm install -g @ angular / bazel 
ng new my-app --colection = @ angular / bazel

Builders API(Architect API)

Angular 用 builder 做 serve、build、test、lint、e2e,可在 angular.json 里看到:

...
"projects": {
  "app-name": {
    ...
    "architect": {
      "build": {
        "builder": "@angular-devkit/build-angular:browser",
        ...
      },
      "serve": {
        "builder": "@angular-devkit/build-angular:dev-server",
        ...
      },
      "test": {
        "builder": "@angular-devkit/build-angular:karma",
        ...
      },
      "lint": {
        "builder": "@angular-devkit/build-angular:tslint",
        ...
      },
      "e2e": {
        "builder": "@angular-devkit/build-angular:protractor",
        ...
      }
    }
  }
}

从 8 开始可以写自定义 builder,类似于 gulp/grunt 时代的命令。builder 就是一组命令的函数,交给 @angular-devkit/architect 的 createBuilder():

import { createBuilder } from '@angular-devkit/architect';
function customBuild(options, context) { 
  return new Promise((resolve, reject) => {
    // set of commands
  })
}
createBuilder(customBuild);

四、懒加载、$location、Worker

不再推荐 loadChildren:string。8.0.0 之前:

loadChildren: './lazy/lazy.module#LazyModule';

现在:

loadChildren: () => import('./lazy/lazy.module').then(m => m.LazyModule)

懒加载模块很多、想靠包来改时,可查当时的迁移说明。

AngularJS $location

为方便从 AngularJS 升级,增加了对 $location 的支持,新包是 angular/common/upgrade:可从位置服务取状态、跟踪所有位置变化、读取 hostname / protocol / port / search,并提供 MockPlatformLocation 测位置服务。

Web Worker 与 Service Worker

可以把耗时进程委派给 Web Worker。用 CLI 生成:

ng g webWorker <name>

PWA 背景下 Service Worker 也有改进:SwRegistrationOptions 增加选项;一个域支持多个应用。细节见 Angular 文档。

五、表单、TypeScript 与性能

新增 markAllAsTouched,一次性把 FormGroup 里所有控件标成 touched,方便触发整组校验。以前要手写:

validateFormAndDisplayErrors(form: FormGroup) {
  Object.keys(form.controls).map((controlName) => {
    form.get(controlName).markAsTouched({onlySelf: true});
  });
}

从 FormArray 清掉所有元素,以前要循环 removeAt(0) 直到空:

while(formArray.length){ 
  formArray.removeAt(0); 
}

现在直接 clear:

formArray.clear()

TypeScript 支持到 3.4.x 一线(文中写 Angular 8 用 TS 3.3,v7 用 3.2.x),没有太多破坏性变化。

性能:ServerRendererFactory2 以前为每个请求新建 DomElementSchemaRegistry,很贵;现在共享全局实例。

六、弃用 API 与 ViewChild 时机

  • 从 @angular/platform-browser 删除已弃用的 DOCUMENT,改从 @angular/common 导入
  • @angular/http 在 Angular 5 就不推荐,因 platform-server 依赖而一直留着,8 起从包列表删除

使用 ViewChild / ContentChild 时必须提供 static,声明何时解析实例:

// Ensure Change Detection runs before accessing the instance
@ContentChild('foo', { static: false }) foo!: ElementRef;
// If you need to access it in ngOnInt hook
@ViewChild(TemplateRef, { static: true }) foo!: TemplateRef;

这不适用于 ViewChildren / ContentChildren,它们在变更检测后解析。static: true 时拿不到 *ngIf 这类动态模板的结果。Ivy 会用这套语法,可运行 ng update @angular/core 迁移。

Angular Material 工程改名为 Angular Components,包名不变。总体改动不大,仍是每年一个稳定版。

一句话总结:Angular 8 的关键升级点是差分加载、动态 import 懒加载,以及 ViewChild 必须声明 static;Ivy 和 Bazel 当时仍是预览。

转载请注明来源:Angular8新特性
本文链接地址:https://ai.zhousir.top/?p=2604
回复 取消