返回博客首页
← 所有文章

我们非常喜欢 Angular...这次的喜爱程度是 10 倍

2020 年 7 月 16 日 — 作者 Nathan Walker

NativeScript 团队致力于 Angular,并且非常喜欢用它来构建应用程序。我们很高兴能带来 Angular 10 支持,并且已经期待着 Angular 11 了。

在这个更新中,我们想要更进一步,并且还对 @nativescript/core 进行了一些主要的清理工作,以带来适当的 TypeScript 3.9 支持,以与 Angular 10 保持一致。事实上,我们在其中一些支持中引入了即将推出的 NativeScript 7 的一些 rc 版本,因此那些想要升级的人可以在这里获得多个更新。

我们还将展示一个以前从未在 NativeScript Angular 中支持过的很酷的新功能。最终实现真正的异步 APP_INITIALIZER 支持!🎉

TL;DR 版本!

如果您想快速尝试一下,本节适合您。如果您想了解更多详细信息,请继续阅读。

安装 {N} cli(至少 7.0.0 及更新版本)

npm i -g nativescript

这将安装即将推出的 cli 版本,该版本支持范围包(所有 {N} npm 包的未来)。这仍然可以与旧项目一起使用,因此您可以立即开始使用它。它还引入了一个新的 cli 别名,我们称之为 ns(可以解释为 NativeScript Compiler 或简单地 NativeScript)。tns 仍然有效,并且将永远有效。我们将在 2020 年路线图中使用 ns 来介绍它,以便逐渐开始摆脱 tns 的东西。

ns create sampleapp --ng

现在您有了可以用来玩的 Angular 10 版本的 NativeScript 应用程序。

详细更新说明

让我们分解一下现在在您自己的项目中尝试这一功能需要做些什么。我们计划将此版本保持为 rc 另一个星期,以验证任何剩余的问题。您可以通过报告遇到的任何问题来帮助我们发布更好的最终版本 这里 - 只要在问题前加上 [Angular 10],这样我们就能快速看到它。

  1. npm i -g nativescript

这将安装最新的 cli 版本。

  1. 修改您的 package.json,使其包含以下内容
"scripts": {
  "ngcc": "ngcc --properties es2015 module main --first-only",
  "postinstall": "npm run ngcc"
},
"dependencies": {
  "@angular/animations": "~10.0.0",
  "@angular/common": "~10.0.0",
  "@angular/compiler": "~10.0.0",
  "@angular/core": "~10.0.0",
  "@angular/forms": "~10.0.0",
  "@angular/platform-browser": "~10.0.0",
  "@angular/platform-browser-dynamic": "~10.0.0",
  "@angular/router": "~10.0.0",
  "@nativescript/angular": "~10.0.0",
  "@nativescript/core": "~7.0.0",
  "@nativescript/theme": "~2.3.0",
  "reflect-metadata": "~0.1.12",
  "rxjs": "^6.6.0",
  "zone.js": "~0.10.3"
},
"devDependencies": {
  "@angular/compiler-cli": "~10.0.0",
  "@nativescript/types": "~7.0.0",
  "@nativescript/webpack": "~3.0.0",
  "@ngtools/webpack": "~10.0.0",
  "typescript": "~3.9.0"
}

确保您完全从依赖项和/或 devDependencies 中删除了 nativescript-angulartns-core-modules

ngccpostinstall 仍然是一个好主意,我们稍后会详细说明。

如果您习惯使用 tns-platform-declarations,现在您可以安全地使用 @nativescript/types,它与 tns-platform-declarations 相同,只是名称更清晰一些。这使您能够更新您的 references.d.ts,如下所示

/// <reference path="./node_modules/@nativescript/types/ios.d.ts" />
/// <reference path="./node_modules/@nativescript/types/android.d.ts" />

如果您习惯使用 nativescript-dev-webpack,现在您可以安全地使用 @nativescript/webpack,它与 nativescript-dev-webpack 相同,但现在包含了来自 webpack 和瞬态依赖项的所有最新更新,其中还包括最新的 webpack.config.js 文件。要替换您自己的项目的 webpack.config.js,您可以简单地将其删除,然后使用上面类似的 npm 脚本清理您的项目,然后重新运行项目,@nativescript/webpack 将简单地将一个全新的更新版本放入您的项目中。如果您有自定义的 webpack 更改,您可以使用您的 git 更改集来保留您的自定义部分。

如果您在 webpack 配置方面遇到问题,您可以将此配置复制粘贴到此处: https://github.com/NativeScript/NativeScript/blob/204b5a427b11a411ffd70468155e149bda168755/packages/webpack/templates/webpack.angular.js

  1. 使用类似的设置更新您的 tsconfig.json(取决于您的项目,它不一定必须完全反映此配置,但您可以将其用作良好的参考)。通常,moduletarget 会更新为较新的目标。
{
  "compilerOptions": {
    "module": "ESNext",
    "target": "es2015",
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,
    "noEmitHelpers": true,
    "noEmitOnError": true,
    "skipLibCheck": true,
    "lib": [
      "es2018", "es2017", "dom", "es6"
    ],
    "baseUrl": ".",
    "paths": {
        "~/*": [
            "app/*"
        ]
    }
  },
  "include": [
    "references.d.ts",
    "src/tests/**/*.ts"
  ],
  "files": [
    "./src/main.ts"
  ],
  "exclude": [
    "node_modules",
    "platforms",
    "e2e"
  ]
}
  1. 将所有导入更新为简单地使用 @nativescript/angular,如果它们以前是 nativescript-angular/{anything}。这包括 Angular 9 的 import { platformNativeScriptDynamic } from '@nativescript/angular/platform'; 在您的 main.ts 中,可以将其简化为在整个代码库中保持 100% 一致。因此只需 import { platformNativeScriptDynamic } from '@nativescript/angular';

  2. 关于 ngcc.config.js 和 postinstall 等的说明

市面上很多插件都没有使用 ng-packagr 构建,或者使用 Angular 9 或 10 构建...还没有。这不是一件坏事,现在完全可以接受。因此,此文件可以帮助弥合差距,使这些插件能够立即与您的 Angular 10 项目一起使用。一般来说,经验法则是,如果您遇到关于插件的构建错误,您可能需要在此文件中添加一个条目。您可以根据示例 ngcc.config.js 文件,按照类似的模式添加不同依赖项的条目,该文件作为方便之举与 nsc create sampleapp --ng 示例应用程序一起提供。

  1. 现在运行一下:ns run ios --emulatorns run android --emulator

并报告任何问题 这里,谢谢您!❤️

故障排除

问题 1

file: node_modules/@angular/core/fesm2015/core.js:3380:0: JS ERROR ReferenceError: Can't find variable: setTimeout
(CoreFoundation) *** Terminating app due to uncaught exception 'NativeScript encountered a fatal error: ReferenceError: Can't find variable: setTimeout

解决方案:

确保 import { platformNativeScriptDynamic } from "@nativescript/angular";main.ts 中的**第一个**导入。例如

  • 之前
import { enableProdMode } from "@angular/core";
import { platformNativeScriptDynamic } from "@nativescript/angular";
  • 之后
import { platformNativeScriptDynamic } from "@nativescript/angular";
import { enableProdMode } from "@angular/core";

问题 2

CONSOLE ERROR file:///app/bundle.js:3489:19: No value accessor for form control with name: 'someControl',ZoneAwareError(file: node_modules/@nativescript/zone-js/zone-nativescript.js:1298:0)
at _throwError(file: node_modules/@angular/forms/fesm2015/forms.js:2440:0)

或者类似的问题。

解决方案:

如果您有一个扩展了 abstract 类且缺少装饰器的组件,则可能会出现这种情况。例如,要解决此问题

  • 之前
export abstract class SomeParentClass { ...
  • 之后
@Directive()
export abstract class SomeParentClass { ...

正确的异步 APP_INITIALIZER 支持

有时,您需要在应用程序启动之前获取数据,或者在应用程序准备好与用户交互之前执行异步操作。或者,您可能只是想要一个整洁的启动序列,在应用程序启动之前进行动画。使用 Angular 10 和 NativeScript,您现在终于可以使用异步 APP_INITIALIZER,就像在 Angular Web 应用程序中一样。

以下是一个示例

export function asyncBoot(): Function {
  return (): Promise<any> => new Promise(resolve => {
    setTimeout(() => {
      resolve();
    }, 5000);
  })
}

@NgModule({
    imports: [NativeScriptModule],
    declarations: [AppComponent],
    bootstrap: [AppComponent],
    providers: [
      {
        provide: APP_INITIALIZER,
        useFactory: asyncBoot,
        multi: true
      },
    ]
})
export class AppModule {}

您也可以将 HttpClient 注入到该工厂函数中,以执行远程请求。

我们将在后续博客文章中详细讨论此问题,以探索一个新的 NativeScript Angular 启动选项,该选项提供创建引人入胜的自定义启动动画的能力。