返回博客首页
← 所有文章

Angular 10 项目升级指南

2020 年 8 月 4 日 — 作者:Mahmoud Abduljawad

NativeScript 团队再次努力,为 NativeScript 提供了最新的 Angular 10 支持。@nativescript/schematics 包的新版本标志着统一 Web 和移动代码库之旅的又一个重要里程碑,同时在使用 Angular 构建 NativeScript 时提高了开发人员体验。如果您不熟悉 @nativescript/schematics,则需要查看GitHub 上的软件包源代码库以了解更多信息。如果您想现在试一试,可以执行以下操作

npm i -g @angular/cli // You could be needing to prefix sudo on GNU/Linux and other Unix-like OSes.
npm i -g nativescript // You could be needing to prefix sudo on GNU/Linux and other Unix-like OSes.
npm i -g @nativescript/schematics // You could be needing to prefix sudo on GNU/Linux and other Unix-like OSes.

ng new workspace
cd workspace
ng add @nativescript/schematics --skipAutoGeneratedComponent

// start apps:
npm run ios
npm run android 
ng serve

基于https://github.com/NativeScript/nativescript-schematics/pull/286#issuecomment-666116443

将您的项目升级到 Angular 10

更新您的项目实际上为即将发布的 NativeScript 7 做好了准备,因为它依赖于当前运行的 @nativescript/core rc,这些 rc 使用 es2017 目标构建以符合 Angular 10 因为 es5 支持已正式默认弃用。这是一个非常受欢迎的即将在 NativeScript 7 中出现的改变,它将允许使用 v8 引擎进行很好的优化,高级树形抖动以及将您的 NativeScript 代码与现代 JS 生态系统对齐。

如果您已经使用 Angular 与 NativeScript 并且希望与项目发布保持同步,以下是如何将您的项目升级到 Angular 10 的指南

警告:确保您的项目更改已提交并推送到远程存储库。此过程涉及一些更改,这些更改对于在当前项目中进行更改集差异非常有益

1. 更新 package.json

package.json 是您项目包含和依赖的内容的最终参考。为此,它目前列出了您项目依赖项的先前版本。Nathan WalkerTSC 成员,解释了并实施了 package.json 需要的样子。根据他的评论,我创建了一个示例 node 脚本,该脚本采用您当前的 package.json,并使用扩展语法更新需要更新的包,而不删除您项目的其他依赖项。该脚本还从 package.jsonnativescript 部分删除了平台版本定义,因为建议与 @nativescript/angular 包一起升级平台版本。要使用该脚本

  1. 将该文件从 https://gist.github.com/mahmoudajawad/351b7e90460b5d78942046049a6f7598 下载到您的项目根目录(与 package.json 相同的级别)。
  2. 在将工作目录设置为项目路径后,使用首选的控制台应用程序运行:node update_package.tns-ng10.js
  3. 该脚本将运行,希望它将以 🎉 已更新 package.json! 结束。a. 如果没有,并且您收到的消息是 "package.json.bak" 已找到...,则您可能之前已经尝试过运行该脚本,并且您的 package.json 文件已经更新。b. 要确认,请打开 package.json 并确认 @nativescript/angular 包版本是否设置为 ~10.0.0。c. 如果是,那么您的 package.json 可能已经通过之前运行的脚本更新。d. 如果没有,请删除 package.json.bak。e. 如果问题仍然存在,请告诉我,以便我可以与您一起解决。
  4. 检查更新后的 package.json 文件,并确保它看起来正常。
  5. 删除 webpack.config.js
    • 如果您对 webpack.config.js 进行了任何更改,则需要记住它们,以便在之后重新实现它们,因为 NativeScript 包将在 webpack.config.js 文件不存在时尝试创建更新的 webpack.config.js 文件。
  6. 运行 npm run clean && npm run PLATFORM,其中 PLATFORM 是您尝试为其部署应用程序的平台。
    • 请注意,运行 tns run PLATFORM 将导致应用程序无法正常工作,因为需要传递 --no-hmr 参数。使用 npm run PLATFORM 将为您提供对所需操作的简写访问。
    • 由于需要更新 Preview 应用程序并且正在进行中,因此目前无法使用 NativeScript Preview 应用程序在 Android 和 iOS 上以 preview 模式运行项目:https://github.com/NativeScript/nativescript-schematics/pull/286#issuecomment-667577731
  7. 如果您的应用程序无法正常工作,则很有可能某些导入已损坏,您将在下一步修复它们。

如果您想自己动手。以下是您需要执行的操作

  1. 根据此评论更新 package.json 包版本。
  2. nativescript 部分删除平台版本,但保留 id 属性。
  3. 删除 webpack.config.js
  4. 运行 npm run clean && npm run PLATFORM,其中 PLATFORM 是您尝试为其部署应用程序的平台。
  5. 如果您的应用程序无法正常工作,则很有可能某些导入已损坏,您将在下一步修复它们。

2. 修复导入

使用 Angular 10 的 NativeScript 为使用该框架带来了更标准化的体验。其中一个方面是导入该框架提供的工具和类。这将有助于提高您项目对框架更改的未来升级弹性,因为核心团队可以在幕后对框架类的组织进行改进,而不会影响大量的深层导入路径,这些路径在不同的项目之间可能会有很大差异。这意味着您项目中的一些旧导入样式需要更新。为此,请使用您的 IDE 或编辑器搜索以下术语并替换它们,因为

tns-core-modules

警告:您的搜索结果将包括来自 package.jsonpackage-lock.jsonpackage.json.bakwebpack.config.js 的结果。您不应尝试修改这些文件。

此包包含所有 NativeScript 的核心工具和类。您需要搜索所有从 tns-core-modules 导入的导入语句,并将其替换为 @nativescript/core。如果您有导入语句,则从嵌套模块导入,例如

import { screen } from 'tns-core-modules/platform';

您需要将导入替换为顶层,使其成为

import { screen } from '@nativescript/core'; // and not @nativescript/core/platform
// Still will give error, read next...

tns-core-modules@nativescript/core 的更改也导致某些类名发生了变化,例如 screen,它现在变成了 Screen。您可以通过按 IDE 或编辑器的自动完成组合(通常是 Ctrl+Space、Cmd+Space)来列出 @nativescript/core 包中可用的所有类,并找到可能的新的类名。

现在某些其他导入完全无效,例如

import * as applicationSettings from 'tns-core-modules/application-settings';

需要将其导入为

import { ApplicationSettings } from '@nativescript/core';

在代码库中搜索 tns-core-modules@nativescript/core/ 时,如果没有任何结果,则您将完成此步骤。

此评论中建议使用顶层导入,对于将我的项目升级到 Angular 10 至关重要。使用深层导入似乎破坏了我的项目,而根据评论建议简单地更改为顶层导入解决了我的升级问题。

nativescript-angular

警告:您的搜索结果将包括来自 package.jsonpackage-lock.jsonpackage.json.bakwebpack.config.js 的结果。您不应尝试修改这些文件。

类似地,您需要将所有导入 nativescript-angular 的导入替换为 @nativescript/angular。此处也应用相同的顶层规则,因此,如果您在修复导入后最终获得了 @nativescript/angular/ 的搜索结果,则需要删除这些深层导入语句并将其重新设定为顶层导入。一个常见的是 app-routing.module.tns.ts 中的导入语句,该语句由 @nativescript/schematics 创建,如下所示

import { NativeScriptRouterModule } from 'nativescript-angular/router';

如果您只是更改为

import { NativeScriptRouterModule } from '@nativescript/angular/router';

它仍然会破坏应用程序,但您需要完全删除深层导入,如下所示

import { NativeScriptRouterModule } from '@nativescript/angular';

升级后,某些类不可用,例如 DEVICE,它以前用于注入到您的 Angular 类中。现在,您只需要简单地从 @nativescript/core 中使用 Device,而无需注入它。

在代码库中搜索 nativescript-angular@nativescript/angular/ 时,如果没有任何结果,则您将完成此步骤。

其他提示

如前所述,要运行使用 Angular 10 的 NativeScript 应用程序,您可以使用

npm run PLATFORM
tns run PLATFORM --no-hmr

因为如果使用 tns 时未提供 --no-hmr 参数,则编译应用程序将失败。

如果您曾经使用过此不错的技巧将重新路由添加到 HMR,则需要撤消它,因为它会破坏您的应用程序。您只需要在 main.tns.ts 文件中注释掉 import './livesync-navigation.tns'; 这行即可。

最后,如果您遇到以下错误

com.tns.NativeScriptException: Calling js method onCreate failed

然后在 Android 和 iOS 上分别出现以下错误

java.lang.IllegalArgumentException: Cannot add a null child view to a ViewGroup

Root should be either UIViewController or UIView

那么,您可能遇到了我遇到的一个有趣的问题,即 app.component.tns.html 看起来像

<page-router-outlet></page-router-outlet>

并且,使用任何布局组件(例如 GridLayoutStackLayout)包装 page-router-outlet 解决了该问题。因此,您的 app.component.tns.html 应该类似于

<GridLayout>
    <page-router-outlet></page-router-outlet>
</GridLayout>

核心团队注意:使用 GridLayout 包装 page-router-outlet 有利,将来会分享有关此布局的一些优势的更多详细信息,这就是为什么它现在成为默认布局并必不可少的原因。

单元测试的状态

自 NativeScript 与 Angular 9 发布以来,单元测试一直处于中断状态。但是,NativeScript 团队似乎对此有一个想法,我希望围绕此问题的解决办法很快得到解决。目前,您必须没有测试(我知道您一直都在期待 xD)。

升级操作

如果您想查看升级操作,请查看我的存储库,我将其用作测试之一,以确认升级使用 Angular 的 NativeScript 项目的事件顺序。在升级之前,该项目基于 Angular 8,现在它在 Angular 10 上运行,没有任何问题。在此处找到确切的更改:https://github.com/mahmoudajawad/nativescript-pokedex/commit/2e9723dd093244761cd524cb068a0563d5813e22.