Angular 5.0 来了! 有这些大变化
我们很高兴地宣布angular 5.0.0——五角形甜甜圈发布啦!这又是一个主版本,包含新功能并修复了很多bug。它再次体现了我们把angular做得更小、更快、更好用的一贯目标。
以下简单介绍v5的重大变化。要了解详情,请看changelog。
构建优化器
5.0.0开始,通过cli执行的产品构建默认使用构建优化器。
构建优化器是cli中的一个工具,它基于我们对你angular应用的理解,可以把构建后的包变得更小。
构建优化器有两个主要任务。首先,把你应用的某些部分标记为pure,以便原有工具利用它改进“tree shaking”的优化效果,同时删除应用中不必要的东西。
其次,构建优化器会从你的应用中删除angular装饰器代码。装饰器只有编译器会用,运行时不用,可以删掉。上述两项优化都可以减少生成js包的大小,同时加快应用启动速度。
angular universal状态转交api及对dom的支持
这样更便于在服务端和客户之间共享应用状态。
angular universal是一个帮助开发者执行服务端渲染(ssr)的项目。服务端渲染生成的html对不支持js的蜘蛛和爬虫友好,同时有助于提升用户感知性能。
在5.0.0中,开发团队添加了servertransferstatemodule及对应的browsertransferstatemodule。这个模块可以帮开发者在服务端渲染生成的内容中加入相关信息,然后传送给客户端,从而避免重复生成。这对于通过http获取数据的场景是很有用的。通过把状态从服务器传送到客户端,开发者就不用再发第二次http请求了。状态转交的相关文档几周后会发布。
angular universal团队还把平台服务器domino加到了平台服务器中。domino支持在服务器端环境下更多的开箱即用的dom操作,可以改进我们对非服务端第三方js及组件库的支持。
编译器改进
为支持递增编译,我们改进了angular编译器。结果让重新构建加快,特别是对产品构建和aot构建,效果更明显。我们还增强了装饰器,通过删除空白达到减少包大小的目的。
typescript转换
现在,angular编译器底层的工作机制是typescript转换,从而让递增式重新构建快了很多。typescript转换是typescript 2.3新增的一个特性,可以让我们深入到标准typescript编译管道。
在打开aot标签的情况下,运行ng serve就可以利用上述机制。
ng serve --aot
建议大家都试一下。将来这个配置会成为cli的默认值。很多项目都有性能问题,涉及上千组件,我们希望各种规模的项目都能从这些改进中受益。
在执行https://angular.io 的递增aot构建时,新编译器管道可节省95%的构建时间(在我们开发机上测试的结果是从40多秒减少为不到2秒)。
我们的目标是让aot编译快到能开发者用它开发的程度。现在,我们已经冲进了2秒以内,因此将来的cli中可能会默认开启aot。
作为向本次转换过渡的一步,我们不再需要gendir,而outdir也变了:现在,我们会把为包生成的文件都打到node_modules里。
保留空白
过去编译器会忠实地复现并在模板中包含制表符、换行符和空白。现在你可选择是否在组件和应用中包含空白了。
可以在每个组件的装饰器中指定这个配置,而当前的默认值为true。
@component({ templateurl: 'about.component.html', preservewhitespaces: false } export class aboutcomponent {}
或者也可以在tsconfig.json中进行全局配置,其中该项默认值也是true。
{ "extends": "../tsconfig.json", "compileroptions": { "outdir": "../out-tsc/app", "baseurl": "./", "module": "es2015", "types": [] }, "angularcompileroptions": { "preservewhitespaces": false }, "exclude": [ "test.ts", "**/*.spec.ts" ] }
一般规则是组件级配置要覆盖应用级配置。开发团队打算将来把默认值改成false,默认为开发者节省空间。不要担心你的<pre>标签,编译器会智能处理它们。
改进的装饰器支持
现在支持lambda和对象字面量usevalue、usefactory和data装饰器中的表达式降级(expression lowering)。这样可以使用只能在运行时计算的装饰器中被降级(lower)的值。
因此现在可以不使用命名函数,而改用lambda函数。换句话说,执行代码不会影响你的d.ts或你的外部api。
component({ provider: [{provide: some_token, usefactory: () => null}] }) export class myclass {}
我们还会将表达式降级,作为usevalue的一部分。
component({ provider: [{provide: some_token, usevalue: someenum.ok}] }) export class myclass {}
国际化的数值、日期和货币管道
我们写了新的数值、日期和货币管道,让跨浏览器国际化更方便,不需要再使用i18n的腻子脚本(polyfill)。
在以前版本的angular中,我们一直依赖浏览器及其i18n api提供数值、日期和货币格式。为此,很多开发者都在使用腻子脚本(polyfill),而结果也不好。很多人反馈说一些常见的格式(如货币)不能做到开箱即用。
而在5.0.0中,我们把这个管道更新成了自己的实现,依赖cldr提供广泛的地区支持,而且可配置。以下是我们对v4和v5所做的比较:a document comparing the pipe behavior between v4 and v5。
如果你还没条件使用新管理,可以导入deprecatedi18npipesmodule以降级到旧的行为。
staticinjector代替reflectiveinjector
为了消除对更多腻子脚本(polyfill)的依赖,我们用staticinjector代替了reflectiveinjector。前者不再需要reflect,为开发者减少了应用大小。
以前
reflectiveinjector.resolveandcreate(providers);
以后
injector.create(providers);
提升zone的速度
一方面提升了zone的速度,另一方面也可以在特别关注性能的应用中绕过它。
若要绕过它,启动应用时加上noop:
platformbrowserdynamic().bootstrapmodule(appmodule, {ngzone: 'noop'}).then( ref => {} );
这里有一个完整的例子:the example ng-component-state project。
exportas
组件和指令中增加了对多名称的支持。这有助于用户实现无痛迁移。通过把指令导出为多个名称,可以在不破坏原有代码的情况下在angular语法中使用新名称。angular material项目已经在其前缀迁移项目中用上了,对其他组件作者肯定也有用。
示例
@component({ moduleid: module.id, selector: 'a[mat-button], a[mat-raised-button], a[mat-icon-button], a[mat-fab], a[mat-mini-fab]', exportas: 'matbutton, matanchor', . . . }
httpclient
v4.3在@angular/common中推出过httpclient,用于在angular中发送请求,它小巧易用。httpclient受到了开发者的广泛赞誉,因此我们推荐在所有应用中使用它,放弃之前的@angular/http library。
要升级httpclient,需要在每个模块的@angular/common/http中把httpmodule替换为httpclientmodule,注入httpclient服务,删除所有map(res => res.json())。
cli v1.5
从angluar cli v1.5开始,已经开始支持angluar v5.0.0,默认生成v5项目。
在这次小版本升级中,我们默认打开了构建优化器,让开发者拿到更小的包。
我们还修改了使用.tsconfig文件的方式,以更严格地遵守typescript标准。此前,如果检测到延迟加载的路由,而且你在tsconfig.json中手工指定了一组files或include,那这些路由会自动化处理。而如今,根据typescript规范,我们不再这么干了。默认情况下,cli对typescript的配置中没有files或include,因此多数开发者不会受影响。
angular表单添加updateon blur/submit
这样可以根据blur或submit来运行验证和更新值的逻辑了,不必再单纯依赖input事件。
表单对应用很重要,如果有服务端验证,或者验证或更新值会触发较慢的操作,你当然希望它少跑几次。现在你可以在控件层面控制验证和更新值的时机了,也可以在表单层面设置。
此外,你现在可以直接在选项中指定asyncvalidators,而不是通过第三个参数指定。
模板驱动的表单
以前
<input name="firstname" ngmodel=""/>
以后
<input name="firstname" ngmodel [ngmodeloptions]="{updateon: 'blur'}">
或者
<form [ngformoptions]="{updateon:'submit'}">
反应式表单
以前
new formgroup(value); new formcontrol(value, [], [myvalidator])
以后
new formgroup(value, {updateon: 'blur'})); new formcontrol(value, {updateon: 'blur', asyncvalidators: [myvalidator]})
rxjs 5.5
我们已经把使用的rxjs更新到5.5.2或更高版本。这个新发布的rxjs可以让开发完全摆脱之前导入机制的副作用,因为我们以新的lettable operators的方式使用了rxjs。这些新操作符消除了副作用,以及之前导入操作符中“patch”方法存在代码切割和“tree shaking”等问题。
不再这样:
import { observable } from 'rxjs/observable'; import 'rxjs/add/operator/map'; import 'rxjs/add/operator/filter'; names = alluserdata .map(user => user.name) .filter(name => name);
现在这样:
import { observable } from 'rxjs/observable'; import { map, filter } from 'rxjs/operators'; names = alluserdata.pipe( map(user => user.name), filter(name => name), );
此外,rxjs现在发行了一个使用ecmascript modules的版本。新angular cli会默认拉取这个新版本,让包大小有明显减小。如果你没使用angular cli,那还是应该指向这个新版本。相关文档在此:build and treeshaking。
新的路由器生成周期事件
我们给路由器添加了新的生命周期事件,让开发者可以跟踪running guard启动到激活完成的各个阶段。这些事件可在有子组件更新时,在一个特定的路由器出口上展示加载动画,或者测量性能。
新的事件(按顺序)是guardscheckstart、childactivationstart、activationstart、guardscheckend、resolvestart、resolveend、activationend、childactivationend。以下是一个使用这些事件启动和停止加载动画的示例:
class mycomponent { constructor(public router: router, spinner: spinner) { router.events.subscribe(e => { if (e instanceof childactivationstart) { spinner.start(e.route); } else if (e instanceof childactivationend) { spinner.end(e.route); } }); } }
如何更新
这里有angular update guide,告诉你整个过程,以及更新前要做哪些事,还有更新应用的步骤,以及做好迎接angular未来版本的准备等信息。
我们删除很多以前废弃的api(如opaquetoken),也公布了一些新的废弃项。以上指南会详细介绍这些变更。
已知问题
当前已知与source map相关的问题。某些source map会报“未定义的源”错误。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。