Upgrade To Angular 8
文章目录
1. Upgrade Angular
-
确保 angular-cli 已经安装
npm install -g @angular/cli
-
执行
ng update
获取当前项目可用的更新
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iqotlai9-1576941188359)(evernotecid://7D5162EA-5D37-473F-9C81-E2FEC23DD3B2/appyinxiangcom/18499762/ENResource/p405)] -
执行
ng update --all
尝试更新
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-F0OllsHg-1576941188362)(evernotecid://7D5162EA-5D37-473F-9C81-E2FEC23DD3B2/appyinxiangcom/18499762/ENResource/p406)] -
处理异常依赖, 解决错误.
一起更新可能会存在冲突, 逐个更新相应组件
ng update @angular/cli @angular/core --allow-dirty
ng update @angular/cdk @angular/material --allow-dirty
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TGNJryCx-1576941188363)(evernotecid://7D5162EA-5D37-473F-9C81-E2FEC23DD3B2/appyinxiangcom/18499762/ENResource/p407)]
- 删除 node_modules 重新编译. 处理错误.
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AKWVm0rK-1576941188364)(evernotecid://7D5162EA-5D37-473F-9C81-E2FEC23DD3B2/appyinxiangcom/18499762/ENResource/p408)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wqW8OsMq-1576941188365)(evernotecid://7D5162EA-5D37-473F-9C81-E2FEC23DD3B2/appyinxiangcom/18499762/ENResource/p409)]
Upgrade Document
Angular Change Log
Useful Blog
2. Angular 8 新特性
2.1 Ivy 编译器
- Ivy 是新的 Angular 编译器,也是新的渲染管道。Ivy 有可能产生相当小 bundle,它使渐进式编译更容易,也是 Angular 领域未来创新的基础。
- 在 Angular 8 中 Ivy 的预览版现在可供测试。此版本的目标是获得早期反馈。因此,Angular 团队建议不要把 Ivy 用于生产环境,而是继续使用经典视图引擎(图1)。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CI548AMu-1576941188365)(evernotecid://7D5162EA-5D37-473F-9C81-E2FEC23DD3B2/appyinxiangcom/18499762/ENResource/p410)]
- 值得一提的是通过 ng build 创建的程序的大小。等到 Angular 9 发布时 Ivy 最终应该会默认激活(目前最新版本 8.2.14–2019/12/15)。在此之前,Angular 团队计划采取进一步措施以确保与旧版本的兼容性.
想尝鲜的人儿可以尝试一下未来的 Ivy API。目前这些 API 仍然被标记为私有。你可以通过查看它的类和函数来进行判断:它们以特殊字符ɵ
开头。
如果你想尝试 Ivy,可以通过 enable-ivy 开关生成一个新项目:
ng new ivy-project --enable-ivy
或者在你心有的项目的 tsconfig.app.json 文件中添加:
"angularCompilerOptions": {
"enableIvy": true
}
2.2 差异加载
目前将程序编译成旧 ECMAScript 5 代码仍然是很常见的,因为“古老的 JavaScript ”在今天仍然在到处运行。这意味着 IE 11 和 Google 搜索引擎后面的网络爬虫都可以执行这些代码。
但是,新的 ECMAScript 2015 及其后续版本更加高效:这些版本允许更紧凑的 bundle 包,浏览器也可以更有效地解释它们。
Angular 8 提供了一个名为差异加载的功能。其背后的想法是提供两组 bundle:一组基于 ECMAScript 5 并且针对较旧的浏览器,另一组基于较新的 ECMAScript 版本,例如 ECMAScript 2015,以此为现代浏览器提供优势。
激活差异加载
- 在
tsconfig.json
文件中修改版本信息:
"target": "es2015",
- 提供 browserlist 配置:
defaults config:
# This file is currently used by autoprefixer to adjust CSS to support the below specified browsers
# For additional information regarding the format and rule options, please see:
# https://github.com/browserslist/browserslist#queries
# For IE 9-11 support, please uncomment the last line of the file and adjust as needed
> 0.5% # 市场占有率
last 2 versions # 最新的两个版本
Firefox ESR # 延长支持版本
not dead # 不满足市场占有率要求, 且两年内没有官方支持与维护.
# IE 9-11 # 默认不支持 IE 9-11
2.3 懒加载
Angular 路由垃圾加载自 Angular 诞生就支持. 如下:
{
path: "monitor",
loadChildren: "./monitor/em-monitor.module#EmMonitorModule"
“#”号之前的值表示通向模块实现的文件的路径;之后的值代表其中包含的类。这种写法也适用于 Angular 8,但是已经被弃用了,现在支持动态 ECMAScript 导入:
{
path: "monitor",
loadChildren: () => import("./monitor/em-monitor.module").then(m => m.EmMonitorModule)
},
新的书写风格中仍然包含文件名作为魔术值。但是由于许多IDE支持导入,因此无效值将立即返回错误。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aLh2alwG-1576941188366)(evernotecid://7D5162EA-5D37-473F-9C81-E2FEC23DD3B2/appyinxiangcom/18499762/ENResource/p411)]
2.4 ViewChild 和 ContentChild
ViewChild 和 ContentChild 的使用方式发生了重大变化,但遗憾的是,过去并不总是表现出一致的行为。虽然它们在早期版本中被用于组件请求不在结构指令内的元素,如 ngIf 或 ngFor,但查询结果已在 ngOnInit 中可用。否则,程序代码或过早的可以在 ngAfterViewInit(或 ngAfterContentInit for ContentChild )中访问它。对于以后因数据绑定而仅加载到 DOM 中的元素,程序代码必须分别插入 ngAfterViewChecked 或 ngAfterContentChecked。
由于这种行为十分令人困惑,所以现在组件必须指定何时应该进行解决:
@ViewChild("info", { static: false })
elemRef: ElementRef;
如果 static 的值为 true,则 Angular 会在初始化组件时尝试查找该元素。这只在不在结构指令中时才有效。使用 static:false 时,在启动或刷新视图后进行解析。
ng update 命令 会自动尝试在此处输入正确的值。如果无法做到这一点,则会在其位置添加带有 TODO 的注释。
设置static: true将不允许您从动态模板分辨率(例如ngIf)获得结果。
与相关装饰器 ViewChildren 和 ContentChildren 的查询不受此更改的影响。他们总是表现出 static:false 意义上的动态行为。
如果需要在 construct, nginit…等方法中访问, 就设置为 true, 否则设置为 false.
2.5 upgrade: Location
Location 服务中添加了用于监视URL更改的新方法 onUrlChange 以及其他修改:
export class AppComponent {
constructor(loc: Location, pLoc: PlatformLocation) {
loc.onUrlChange((url) => console.debug('url change', url));
console.debug('hostname: ', pLoc.hostname);
}
}
PlatformLocation 服务提供对 URL 各个部分的附加访问.
2.6 SVG Template
您现在可以将SVG文件用作模板。到目前为止,我们只能选择使用内联HTML或外部HTML作为模板.
@Component({
selector: "app-icon",
templateUrl: "./icon.component.svg",
styleUrls: ["./icon.component.css"]
})
export class AppComponent {...}
2.7 Web worker
根据定义,JavaScript 是单线程的。因此,对于数据调用等较大任务异步处理是很常见的。不用说,这对计算密集型没有帮助。特别是那些广泛的 JavaScript 解决方案变得越来越普遍,这就是为什么现在几乎所有的浏览器都支持支持 Web worker。它们是浏览器在自己的线程中运行的脚本。通过发送消息与浏览器选项卡中的线程进行通信。
虽然 Web worker 本身与 Angular 无关,但在构建过程中必须考虑它们。目标是为每个 Web worker 提供一个 bundle 包。此任务由新的 Angular CLI 完成。
通过以下命令添加一个 Worker:
ng generate webWorker workerName
接口:
var myWorker = new Worker(aURL, options);
options:
- type: A DOMString specifying the type of worker to create. The value can be classic or module. If not specified, the default used is classic.
- credentials: A DOMString specifying the type of credentials to use for the worker. The value can be omit, same-origin, or include. If not specified, or if type is classic, the default used is omit (no credentials required).
- name: A DOMString specifying an identifying name for the DedicatedWorkerGlobalScope representing the scope of the worker, which is mainly useful for debugging purposes.
/// <reference lib="webworker" />
addEventListener('message', ({ data }) => {
const response = `worker response to ${data}`;
postMessage(response);
});
在 app.component.ts 中
if (typeof Worker !== 'undefined') {
// Create a new
const worker = new Worker('./workerName-worker.worker', { type: 'module' });
worker.onmessage = ({ data }) => {
console.log(`page got message: ${data}`);
};
worker.postMessage('hello');
} else {
console.log("===Web Workers are not supported in this environment.==");
}
2.8 Bazel
Bazel是谷歌开源的另一款工具。Bazel已经在内部使用了很长时间,现在可供所有人使用。您可以参考 Angular 的 Bazel 文档,并了解如何将其与Angular一起使用。
你可能想知道:“Bazel准备好了吗?”简答:还没有。目前,它处于“选择预览”模式。Bazel可作为选择加入,预计将包含@angular/cli在第9版中。
-
要为选择的为现有应用添加它,请运行
ng add @angular/bazel
-
要在新的应用中使用 Bazel,首先要全局安装@angular/bazel
npm install -g @angular/bazel
然后使用下列命令创建新的应用
ng new --collection=@angular/bazel
在某些情况下,你会想要绕过 Angular CLI 的构建器,并直接运行Bazel CLI。 Bazel CLI 位于 @bazel/bazel npm 包中。你可以全局安装它,以便你能通过路径获取 bazel 命令,或者用 $(npm bin)/bazel 代替下面的 bazel。
Bazel 的常用命令有:
- bazel build [targets]:编译指定目标的默认输出成果。
- bazel test [targets]:对于那些符合 *_test 模式的目标,运行测试。
- bazel run [target]:编译目标所代表的程序,然后运行它。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cECQGnWb-1576941188369)(evernotecid://7D5162EA-5D37-473F-9C81-E2FEC23DD3B2/appyinxiangcom/18499762/ENResource/p412)]
2.9 BUILDERS/Architect
"projects": {
"angboot-web": {
"root": "",
"sourceRoot": "src",
"projectType": "application",
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": {
"outputPath": "../server/build/resources/main/static/app/",
"index": "src/index.html",
"main": "src/main.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "src/tsconfig.app.json",
"showCircularDependencies": false,
"assets": [
"src/favicon.ico",
"src/assets"
],
"styles": [
"./node_modules/@angular/material/prebuilt-themes/pink-bluegrey.css",
"./node_modules/bootstrap/dist/css/bootstrap.css",
"src/styles.scss"
],
"scripts": []
},
"configurations": {
"production": {
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.prod.ts"
}
],
"optimization": true,
"outputHashing": "all",
"sourceMap": false,
"extractCss": true,
"namedChunks": false,
"aot": true,
"extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": true
}
}
},
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"options": {
"browserTarget": "angboot-web:build"
},
"configurations": {
"production": {
"browserTarget": "angboot-web:build:production"
}
}
},
"extract-i18n": {
"builder": "@angular-devkit/build-angular:extract-i18n",
"options": {
"browserTarget": "angboot-web:build"
}
},
"test": {
"builder": "@angular-devkit/build-angular:karma",
"options": {
"main": "src/test.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "src/tsconfig.spec.json",
"karmaConfig": "./karma.conf.js",
"styles": [
"./node_modules/@angular/material/prebuilt-themes/pink-bluegrey.css",
"src/styles.scss"
],
"scripts": [],
"assets": [
"src/favicon.ico",
"src/assets"
]
}
},
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": [
"src/tsconfig.app.json",
"src/tsconfig.spec.json"
],
"exclude": [
"**/node_modules/**"
]
}
}
}
},
"angboot-web-e2e": {
"root": "e2e/",
"projectType": "application",
"architect": {
"e2e": {
"builder": "@angular-devkit/build-angular:protractor",
"options": {
"protractorConfig": "e2e/protractor.conf.js",
"devServerTarget": "angboot-web:serve"
}
},
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": "e2e/tsconfig.e2e.json",
"exclude": [
"**/node_modules/**"
]
}
}
}
从现在开始,我们可以创建自定义构建器, 基本上,构建器只是一个带有一组命令的函数,您可以createBuilder()从@angular-devkit/architect包传递给方法。
import { createBuilder } from '@angular-devkit/architect';
function customBuild(options, context) {
return new Promise((resolve, reject) => {
// set of commands
})
}
createBuilder(customBuild);
2.10 表单改进
- 添加了markAllAsTouched方法以标记所有的控件FormGroupas as touched。如果要触发一个表单组中所有控件的验证,这个方法将是非常有用的。之前我们不得不使用下面的代码片段来实现相同的功能:
validateFormAndDisplayErrors(form: FormGroup) {
Object.keys(form.controls).map((controlName) => {
form.get(controlName).markAsTouched({onlySelf: true});
});
}
- 从 FormArray 中清除所有元素
formArray.clear()
以前要删除所有元素,formArray 我们必须循环删除第一个元素直到空:
while(formArray.length){
formArray.removeAt(0);
}
2.11 弃用的API
- 从 @angular/platform-browser中删除了已弃用的DOCUMENT
从@angular/platform-browser中移除了DOCUMENT。如果您使用DOCUMENT from @angular/platform-browser,则应从此处开始导入@angular/common。
- @angular/http
@angular/http在Angular 5中不推荐使用package,但由于@angular/platform-server依赖于它,所以仍然可用。从现在它已从包列表中删除。
- Angular Material工程重命名为Angular Components。包还是跟以前保持一样的。
最后
Angular 9 目前已经在筹备当中, 如果有兴趣, 可以关注 GitHub, 查看并了解最新进展