记NG4 迁移到 NG6 的一次实践

记NG4 迁移到 NG6 的一次实践


如果在尝试升级过程中遇到问题,欢迎提出。
如果发现本指南存在遗漏/错误,请指出!
或者你遇到了新的问题并解决了,欢迎补充!

原文地址:记NG4 迁移到 NG6 的一次实践
官方指南:Angular Update Guide

前几天成功把项目从angular4迁移到angular6最新版本。(截止当天Angular最新版本是:6.1.4

于是做个记录:
思路是更新angular相关核心包到新版本之后,然后再自行修改依赖包的兼容性问题。


Before

在开始之前,请先备份你的项目

确保你的环境满足以下要求

$ node -v
node >= 8.9.0
$ npm -v
npm  >= 5.6.0

删除你项目根目录下的 package-lock.json 文件


Update Angular-Cli

首先更新你的Angular-Cli,请注意保持全局的和当前项目使用的版本一致。

// global
$ npm uninstall -g @angular/cli    // 卸载旧版本cli。
$ npm cache clean                  // 清除缓存,确保卸载干净
// 安装当前最新版本cli V6 (required node.js>=8.9)
$ npm install -g @angular/cli@latest

// local
$ npm install @angular/cli

$ ng update @angular/cli

注:如果卸载全局包失败可以在本地目录下手动删除(window10)
C:\Users\ Flcwl\AppData\Roaming\npm\node_modules

使用命令查看环境【确认无误】

$ ng -v
Angular CLI: 6.1.5

通过这一步,你的angular相关的配置信息将会从angular-cli.json迁移至根目录下的angular.json文件里。


Update angular v6

@angular/core 现在依赖于:
- TypeScript 2.7
- RxJS 6.0.0
- tslib 1.9.0

因此,我们需要在项目下执行以下命令完成angular v6 以及相关依赖的升级(包括typescriptrxjs):

$ ng update @angular/core
$ ng update

记NG4 迁移到 NG6 的一次实践_第1张图片

在官方指南里有说,如果用到了Angular Material,则可以用以下命令更新

$ ng update @angular/material

执行完后将会自动完成相关的它的废弃的APIs的迁移。

这里要注意的问题:

Typescript

尽量全局和本地typescript都使用统一的新版本

typescript尽量使用v2.7版本,做到最大化的向上向下兼容。
因为原先是NG4的项目,可能有很多依赖包并不支持最新版本的typescript
所以我们使用尽可能低的能使用的版本可能能帮助我们减少很多麻烦。

尽管这样,升级之后仍然可能会有包的依赖不匹配问题。请逐个升级解决问题

我的办法是逐个排查match error,逐个升级到它的最新版本,避免不必要的故事发生。
实在不行,遇到有些插件即使是最新版本也不支持angular 6 | typescript 2.7,那就弃用new issue或者更换,实在不济就自行造轮。

记NG4 迁移到 NG6 的一次实践_第2张图片

RXJS

rxjs v5 跨度到 v6, 变化还是是非常大的,我们可以使用Migration to RxJS 6 来完成RxJS 6的一些迁移。

$ npm install -g rxjs-tslint
$ rxjs-5-to-6-migrate -p src/tsconfig.app.json

RXJS-Change

可以看到有个名为rxjs-compat的兄弟包,它支持在RxJs 6中移除掉的功能。
建议升级完成后将rxjs-compat移除。使用真正的v6

可参考使用rxjs-compat升级RxJS的限制

RXjs 6使用过程中有很多变化:
- 运算符(operators) 统一在rxjs/operators中引入

// 例如导入`debounceTime`操作符等,推荐这么用
import { map, debounceTime } from 'rxjs/operators'
  • Observable 创建方法工具库等统一在 rxjs 中引入
import { Observable, fromEvent, Subject } from 'rxjs';
  • 运算符必须使用管道语法.pipe()来调用
source.pipe(
  map(x => x + x)
).subscribe(printResult); 
  • 其它废用的方法
    mergeconcat

具体使用细节、变动请参考:RxJS v5.x to v6 Update Guide


Some Other

NG-ZORRO

这里我是从ng-zorro v0.5直接跳到 v1.4 ,遇到的问题蛮多的,拿出来说说

// 更新到最新版本
$ npm install ng-zorro-antd@latest --save

在注入NgZorroAntdModule的模块里面,删除forRoot()

NgZorroAntd-import

样式修复
情况一 无自定义样式
angular.json配置文件中找到styles字段,添加对应样式:

"styles": [
+ "node_modules/ng-zorro-antd/src/ng-zorro-antd.min.css",
]

注:如果有其它包有样式导入的话都需要如上形式导入具体路径。

情况二 有自定义样式(摘自:NG-ZORRO v1 升级指南)
执行以下命令,降级 less 到 2.7 版本 为什么?

npm install less@2.7.0 -D

找到引入过 ng-zorro-antd 的样式文件,按照以下方式修改:

- @import "~ng-zorro-antd/**";
+ @import "../node_modules/ng-zorro-antd/**";

遇到的一些小细节
输入框

// v.5
<nz-input [(ngModel)]="abc">nz-input>
// v1.4
<input nz-input [(ngModel)]="abc">

对话框(自定义组件)

  • 创建对话框时create而不是open

  • 传入对象属性必须统一使用nz开头,变得更规范

  • 返回实例化对象类型为NzModalRef而不是NzModalSubject

  • 需要.afterOpen().afterClose()产生Observable回调监听

  • 自定义组件向组件外通信使用close(result) | destroy(result)方法而不能使用next(result)

// v.5
import {NzModalSubject} from 'ng-zorro-antd';
  constructor(private modal: NzModalSubject) {}
  ...
  // 向组件外通信
  this.modal.next(value);
  ...
// v1.4
import { NzModalRef } from 'ng-zorro-antd';
  constructor(private modal: NzModalRef) {}
  ...
  // 对话框自定义组件向组件外通信(我采用这种方式)
  this.modal.destroy(value);
  ...

注:如果使用Component模式,则需要在NgModule中的 declarationsentryComponents 加入自定义的Component


NG 6 more standard [坑]

  1. 对于一个Module | Service,在主模块中app.module.ts的导入声明后就可以使用了,但是在懒加载的子模块中想要使用,需要在该子模块的Xxx.module.ts里面再次声明。
// 注入错误 谨记
StaticInjectorError: no provider for ComponentFactoryResolver
  1. 书写导入组件、模块等路径时尽量去掉.ts后缀。
    如下代码是路由配置相关,子模块路径最后因为加了.ts后缀导致该module无法识别的错误(搞得我莫名其妙,项目之前本人并没有参与开发)。
{
  path: 'Xxx',
  // .ts 神坑
  // loadChildren: './Xxx/Xxx.module.ts#XxxModule'
  // Run OK~
  loadChildren: './Xxx/Xxx.module#XxxModule'
},

注:ng4貌似没有上述规则,迁移前都是和和气气的可以运行。


Over~
欢迎 补充 | 讨论 | 修正。

你可能感兴趣的:(Angular系列)