立即更新至Angular版本8!
本文最初发布于https://juristr.com/blog/2019/06/angular-v8。访问juristr.com/blog查看更多内容。
让我们深入了解一下刚刚发布的最新版 Angular 8。我们将快速探索一下它的新功能、为什么要更新、更新过程以及需要注意的事项。
在开始之前,Angular 团队还发布了一篇关于此次发布的官方帖子:
请查看我关于“ Angular组件懒加载”的相关文章。
升级过程中,您将收到一条通知,其中包含一个链接,可查看更多详细信息。
您可以访问https://angular.io/guide/static-query-migration查看所有详细信息。
如果 Angular CLI 无法自动推断是使用静态解析还是动态解析,它会在控制台中添加相应的注释和警告。
总而言之,这一切究竟是关于什么的?
假设您拥有以下资源:
<div foo></div>
在你的代码中,你会使用@ViewChild类似这样的函数:
@ViewChild(Foo) foo: Foo;
(此处Foo为 Angular 指令)
通常情况下,可以安全地假设 `<object> foo` 会在 `<object>` 之后ngAfterViewInit(或ngAfterContentInit对于带有 `<object>` 的内容查询@ContentChild)被填充。然而,其中一些也可以直接在 `<object>` 中访问onInit。原因是编译器在后台将它们归类到 `<object>` 中。
- 静态查询立即可用
- 动态查询仅在运行时可用。
上面的代码示例就是一个静态查询的例子,因为<div foo>它可以立即使用。我们可以安全地在代码中访问它ngOnInit。另一方面,假设我们像这样更改代码:
<div foo *ngIf="isVisible"></div>
在这种情况下,只有当结果为真时,该查询才会可用isVisible,而这可能在应用程序执行期间的任何时间发生。这类查询是动态查询。
主要问题在于这一点没有明确说明。因此,升级到 v8 时,代码迁移会自动将您的代码转换为
// query results available in ngOnInit
@ViewChild('foo', {static: true}) foo: ElementRef;
// query results available in ngAfterViewInit
@ViewChild('foo', {static: false}) foo: ElementRef;
TypeScript 升级
升级到 Angular 8 的同时,您也将升级到 TypeScript 3.4。如果您想了解新功能,请参阅相关文档。
因此,升级后(即使升级成功完成),您可能会遇到错误。这些错误很可能是由于类型推断的改进导致新的潜在类型问题被发现所致。
其他弃用项
请查看官网上的最新弃用指南。还有疑问?如果问题与升级相关,请在Angular CLI 代码库中提交 issue;如果问题与框架相关,请在Angular 代码库中提交 issue。或者直接在 Twitter 上联系我😃
常见问题解答 - 潜在的升级问题
重新运行迁移
如果你进行了 Angular 升级,但由于某种原因,某些代码转换没有成功完成,那么你的 node_modules 文件夹中最终会包含 Angular 8(或你正在升级的任何版本)package.json。
一般来说,我的建议是使用 Git。创建一个迁移分支,这样在升级过程中可以轻松地来回切换。每完成一步就提交一次,这样就相当于有一个备份。
除此之外,Angular CLI 还允许您再次运行迁移,即使您的项目中已经安装了最新版本package.json。只需执行以下命令即可。
// re-run CLI schematics
$ ng update @angular/cli --from 7 --to 8 --migrate-only
// re-run Angular core schematics
$ ng update @angular/core --from 7 --to 8 --migrate-only
材质升级:致命错误:堆内存接近极限时,标记压缩无效,分配失败 - JavaScript 堆内存不足
当我在相当大的 monorepo 上升级 Angular material 时ng update @angular/material,我遇到了以下异常。
<--- Last few GCs --->
[85884:0x103802200] 712051 ms: Scavenge 2004.6 (2047.9) -> 2004.5 (2047.9) MB, 4.1 / 0.0 ms (average mu = 0.199, current mu = 0.181) allocation failure
[85884:0x103802200] 712072 ms: Scavenge 2006.3 (2048.9) -> 2004.6 (2048.4) MB, 3.8 / 0.0 ms (average mu = 0.199, current mu = 0.181) allocation failure
[85884:0x103802200] 712077 ms: Scavenge 2005.6 (2049.4) -> 2005.6 (2049.9) MB, 4.3 / 0.0 ms (average mu = 0.199, current mu = 0.181) allocation failure
<--- JS stacktrace --->
==== JS stack trace =========================================
0: ExitFrame [pc: 0x100e146e6]
Security context: 0x08b76239a2f1 <JSObject>
1: stringSlice(aka stringSlice) [0x8b725f97839] [buffer.js:~568] [pc=0x1d077761a16a](this=0x08b76f0804d1 <undefined>,0x08b765580f19 <Uint8Array map = 0x8b742025759>,0x08b786894e49 <String[#4]: utf8>,0,1073870)
2: toString [0x8b7623f02f9] [buffer.js:~622] [pc=0x1d0777ee3789](this=0x08b765580f19 <Uint8Array map = 0x8b742025759>,0x08b786894e49 <String[#4]:...
FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory
1: 0x100075bd5 node::Abort() [/Users/jstrumpflohner/.nvm/versions/node/v12.4.0/bin/node]
2: 0x100076316 node::errors::TryCatchScope::~TryCatchScope() [/Users/jstrumpflohner/.nvm/versions/node/v12.4.0/bin/node]
3: 0x1001697d7 v8::Utils::ReportOOMFailure(v8::internal::Isolate*, char const*, bool) [/Users/jstrumpflohner/.nvm/versions/node/v12.4.0/bin/node]
4: 0x10016976c v8::internal::V8::FatalProcessOutOfMemory(v8::internal::Isolate*, char const*, bool) [/Users/jstrumpflohner/.nvm/versions/node/v12.4.0/bin/node]
5: 0x1005480d5 v8::internal::Heap::FatalProcessOutOfMemory(char const*) [/Users/jstrumpflohner/.nvm/versions/node/v12.4.0/bin/node]
6: 0x1005491c3 v8::internal::Heap::CheckIneffectiveMarkCompact(unsigned long, double) [/Users/jstrumpflohner/.nvm/versions/node/v12.4.0/bin/node]
7: 0x100546bc3 v8::internal::Heap::PerformGarbageCollection(v8::internal::GarbageCollector, v8::GCCallbackFlags) [/Users/jstrumpflohner/.nvm/versions/node/v12.4.0/bin/node]
8: 0x10054487f v8::internal::Heap::CollectGarbage(v8::internal::AllocationSpace, v8::internal::GarbageCollectionReason, v8::GCCallbackFlags) [/Users/jstrumpflohner/.nvm/versions/node/v12.4.0/bin/node]
...
[1] 85884 abort ng update @angular/material @angular/cdk @angular/cdk-experimental
当 Node 进程需要更多内存时,这是一个常见问题。要解决此问题,请将max_old_space_size选项传递给 Node 进程,如下所示:
$ node --max_old_space_size=8000 ./node_modules/.bin/ng update @angular/material @angular/cdk
Ngrx:类型“Observable”不能分配给类型“Observable”。
将基于 NX 的 monorepo 从 v7 升级到 v8 时,我遇到了另一个奇怪的错误:
ERROR in libs/r3-core/src/lib/+state/app-config/app-config.effects.ts(22,5): error TS2322: Type '(action: LoadAppConfig, state: AppConfigPartialState) => Observable<AppConfigLoaded>' is not assignable to type '(a: LoadAppConfig, state?: AppConfigPartialState) => void | Action | Observable<Action>'.
Type 'Observable<AppConfigLoaded>' is not assignable to type 'void | Action | Observable<Action>'.
Type 'Observable<AppConfigLoaded>' is not assignable to type 'Observable<Action>'.
Types of property 'source' are incompatible.
Type 'import("/Users/jstrumpflohner/myapp/node_modules/rxjs/internal/Observable").Observable<any>' is not assignable to type 'import("/Users/jstrumpflohner/myapp/node_modules/@nrwl/angular/node_modules/rxjs/internal/Observable").Observable<any>'.
Types of property 'operator' are incompatible.
Type 'import("/Users/jstrumpflohner/myapp/node_modules/rxjs/internal/Operator").Operator<any, any>' is not assignable to type 'import("/Users/jstrumpflohner/myapp/node_modules/@nrwl/angular/node_modules/rxjs/internal/Operator").Operator<any, any>'.
Types of property 'call' are incompatible.
Type '(subscriber: import("/Users/jstrumpflohner/myapp/node_modules/rxjs/internal/Subscriber").Subscriber<any>, source: any) => import("/Users/jstrumpflohner/myapp/node_modules/rxjs/internal/types").TeardownLogic' is not assignable to type '(subscriber: import("/Users/jstrumpflohner/myapp/node_modules/@nrwl/angular/node_modules/rxjs/internal/Subscriber").Subscriber<any>, source: any) => import("/Users/jstrumpflohner/myapp/node_modules/@nrwl/angular/node_modules/rxjs/internal/types").TeardownLogic'.
Types of parameters 'subscriber' and 'subscriber' are incompatible.
Property '_parentOrParents' is missing in type 'Subscriber<any>' but required in type 'Subscriber<any>'.
这似乎是由于某个版本的 RxJS 和 Ngrx v7 不兼容造成的。升级到 Ngrx v8 或许可以解决这个问题(但我没有尝试过)。就我而言,将 RxJS 降级到某个版本后问题就~6.4.0解决了。
$ yarn add rxjs@~6.4.0
或者
$ npm i rxjs@~6.4.0 --save
