升级到 Angular v6
有关如何升级到新 Angular 版本的详细信息的最佳资源是https://update.angular.io/。即使您是从 v2 升级到 v6,它也会列出自 v2 到 v6 以来的所有重大更改!这是详细了解代码中需要更改的内容的好方法。
1:安装最新的 Angular CLI
第一步是确保你有最新的 CLI 可用:
npm install -g @angular/cli
随着 Angular v6 的发布,Angular CLI 现在也被版本化为 Angular,这意味着在 Angular v5 之前,我们将使用 Angular CLI 1.x,而现在 Angular CLI 也在版本 6.x 上。它使它更容易!
2:ng更新
不用说,请务必创建一个分支来更新您的项目,因为您永远不会知道升级到 Angular v6 后所有依赖项是否仍然有效。
所以首先,我们将从@angular/cli
. 为了让ng update
命令在项目中工作,我们首先需要将@angular/cli
版本更新到 6.x。
npm install --save-dev @angular/cli@latest
接下来,为 运行ng update
命令@angular/cli
,@angular/core
然后为所需的其他包运行命令 ( rxjs, @angular/material
):
ng update @angular/cli
ng update @angular/core
ng update @angular/material
ng update rxjs
一些项目结构文件已从 v5 更改为 v6。没有angular-cli.json
了,已经被替换了angular.json
。angular.json 的结构也发生了变化,以支持每个工作区的多个项目。当我们运行 ng update 时,@angular/cli
所有需要的文件都会被更新!
3:更新其他依赖
我还喜欢在 Angular 升级期间更新项目使用的其他 npm 依赖项。npm 包 npm-check-updates 对这项任务非常有帮助。
npm install -g npm-check-updates
使用命令 ncu 检查哪些软件包有可用的更新。并ncu -u
更新您的 package.json。
在更改 package.json 包的版本时,我个人也喜欢删除 node_module 并再次运行 npm i 以确保正确的版本在本地可用(并更新 package-lock.json)。
4:更新 RxJS
因此,下一步现在正在运行ng serve
以检查代码是否一切正常。不要忘记验证https://update.angular.io/的所有变化。
尽管我们能够从 Angular v5(使用 RxJS v5)更新 RxJS 代码以使用管道运算符,但在我升级到 v6 的项目中,我忘记更改一些地方。为了帮助我们完成这项任务,我们可以安装rxjs-tslint
以帮助我们删除所有已弃用的 RxJS 代码。
npm install -g rxjs-tslint
rxjs-5-to-6-migrate -p src/tsconfig.app.json
作为关于进口的快速总结:
import { Subject } from 'rxjs/Subject';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { Observable } from 'rxjs/Observable';
import { of } from 'rxjs/observable/of;'
至:
import { BehaviorSubject, Subject, Observable, of } from 'rxjs';
或者,如果你还没有使用 RxJS 管道操作符:
import 'rxjs/add/observable/of';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/do';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/mergeMap';
import 'rxjs/add/operator/switchMap';
至
import { of } from 'rxjs';
import { map, switchMap, catchError, mergeMap } from 'rxjs/operators';
以下运算符也已重命名:
do -> tap
catch -> catchError
switch -> switchAll
finally -> finalize
在我们的代码中,我们可以开始使用管道运算符。
从:
this.http.get('url')
.do(console.log)
.map(results => results.data)
.subscribe(results => {
console.log('Results', results);
});
至:
this.http.get('url')
.pipe(
tap(console.log), // old 'do' operator
map(results => results.data)
)
.subscribe(results => {
console.log('Results', results);
});
更新您的 RxJS 代码后,您可能仍然会从第三方依赖项中收到有关 RxJS 的错误。为了解决这个问题,安装 rxjs-compat 并且一旦依赖项也升级了他们的代码,你可以从你的项目中删除这个包。
npm install --save rxjs-compat
5:简化核心服务的依赖注入
Angular v6 中引入的一个新特性称为“tree-shakable providers”。这意味着我们不再需要使用 property 在模块中声明服务providedIn
,这将允许服务是可摇树的,这意味着如果它们没有被使用,它们将不会成为 prod 包的一部分。
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class MyCoreService { }
我在我的项目的所有核心服务(全局范围)中应用了此功能,但我仍在使用不可摇树的提供程序和不具有全局范围的服务。
这允许从 CoreModule 中清理提供程序部分。
6:更新 Angular 材质(可选)
如果您在项目中使用 Angular Material,请不要忘记运行ng update @angular/material
以更新材质依赖项。
从 v5 到 v6 的一个重大变化是我们如何在项目中导入 Material 模块:
从:
import {
MdToolbarModule,
MdIconModule,
MdButtonModule,
MdMenuModule,
MdCardModule
} from '@angular/material';
至:
import { MatToolbarModule } from '@angular/material/toolbar';
import { MatIconModule } from '@angular/material/icon';
import { MatButtonModule } from '@angular/material/button';
import { MatMenuModule } from '@angular/material/menu';
import { MatCardModule } from '@angular/material/card';
现在每个模块都有自己的包。这也是我喜欢为第三方导入创建单独的模块的原因之一,如本文所述。修复导入变得更加容易!
其他一些事情……我确实有一些自 Angular v2 以来创建的项目,并且在每次主要版本更新之后,我通常只更新 package.json 并修复代码中的重大更改,这没关系。
由于 Angular CLI v6 中有一些项目结构更改,我还决定通过使用 CLI 6 创建一个全新的项目并将 src 文件夹从旧项目复制到新项目来迁移项目。以下是一些受影响最大的更改。
对代码有一些影响的主要区别是 tsconfig.json 中的 baseUrl: './'。对于使用 CLI 1.x(针对 Angular v4 和 v5)创建的项目,默认情况下不存在此配置(但在 src/tsconfig.ap.json 中)。将 baseUrl 移动到根 tsconfig.json 会影响 tsconfig.json 中声明的自定义路径以及延迟加载模块的路径。
之前 - 自定义路径tsconfig.json
:
paths: {
"@env/*": ["environments/*"]
}
之后(使用 CLI v6 创建的单个项目):
paths: {
"@env/*": ["src/environments/*"]
}
并且需要使用相对路径声明延迟加载模块:
前:
{ path: 'home', loadChildren: 'app/home/home.module#HomeModule' }
后:
{ path: 'home', loadChildren: './home/home.module#HomeModule' }
如果您有嵌套模块,您还需要更新它们以使用相对路径:
之前(module1-routing.module.ts):
{ path: 'foo', loadChildren: 'app/module1/module2/module2.module#Module2Module' }
之后(module1-routing.module.ts):
{ path: 'foo', loadChildren: './module2/module2.module#Module2Module' }
CLI v6 命令也有一些变化。由于我的大多数专业应用程序在后端使用 Java,因此来自 ng build 的输出文件夹 (dist) 配置为不同的路径。在 CLI 1.x 之前,有一个标志 (output-path -op) 可以在 ng build 命令 (ng build -op ../other/path) 中使用。使用 CLI v6,如果您需要使用不同的输出路径,则需要更新 angular.json 并从 ng build 中删除 -op 标志:
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": {
"outputPath": "../other/path",
...
}
}
}