返回博客首页
← 所有文章

迁移到 NativeScript 6.0

2019年7月16日 — 作者 Stanimira Vlaeva

备受期待的 NativeScript 6.0 版本即将发布!此版本中最大的两个变化是 AndroidX 支持和捆绑包 (仅限 webpack) 工作流程。这两个变化都可能需要对现有项目进行更改。请阅读本文,了解如何将您的应用程序代码迁移到 NativeScript 6.0。

tns migrate

tns migrate 是一个新的 CLI 命令,旨在帮助进行 NativeScript 6.0 迁移过程。在现有项目中执行此命令将更新

  • CLI 使用的构建配置文件 ("webpack.config.js", "karma.conf.js", "tsconfig.tns.json")。
  • 大多数插件依赖项到与 6.0 兼容的版本。

更新您的 NativeScript CLI 并执行项目中的迁移命令

npm install --global nativescript@latest
tns migrate

然后,使用熟悉的命令运行应用程序

tns run

如果您在开发工作流程中遇到问题,则可能需要更改应用程序代码以使其与 NativeScript 6.0 兼容。阅读本文的其余部分以了解如何操作。如果您的问题未提及,请在 Github 上提交问题

AndroidX

NativeScript 6.0 支持 Android 扩展库 (AndroidX)。不再支持 Android 支持库。任何依赖于支持库的应用程序和插件代码都必须改为使用 AndroidX。要了解如何迁移,请参阅专门的博文。 

CLI 钩子

NativeScript CLI 钩子允许您自定义 CLI 命令的执行。它们广泛用于 NativeScript 插件中。钩子 API 在 6.0 版本中发生了更改。如果您的构建失败并出现以下错误,则可能使用了过时的插件

Cannot read property X of undefined.

要了解如何更新过时的钩子,请参阅本文

捆绑包工作流程

在 6.0 版本之前,NativeScript 用于支持两种构建应用程序的方式: 

  • tns build - 传统工作流程,它将源代码目录 (src/) 的完整内容复制到构建的应用程序中;

  • tns build --bundle - 捆绑包工作流程,它依赖于 webpack 将源代码目录 (src/) 捆绑到几个输出文件中。

NativeScript 6.0 仅支持捆绑包工作流程。更新项目时,您需要确保它可以使用 webpack 进行构建。NativeScript 团队付出了很多努力来缩小传统工作流程和捆绑包工作流程之间的差距。但是,这两种方法非常不同,它们的行为无法完全统一。下面将列出它们之间最常见的差异,以及每个差异的迁移步骤。

必须手动加载静态资产

项目类型

全部

代码示例

以下代码尝试加载本地文件 - /assets/shipping.json

export class CartService {
...
  getShippingPrices() {
    return this.http.get('/assets/shipping.json');
  }
}
传统工作流程

源目录中的所有文件都是构建应用程序的一部分。因此,/assets/shipping.json 文件将可用并成功加载。

捆绑包工作流程

Webpack 仅编译源代码中明确需要的或由 webpack 插件包含的文件。使用默认设置,/assets/shipping.json 将不会在构建的应用程序中,并且请求将失败。

迁移

配置 CopyWebpackPlugin 以将静态资源从您的项目移动到构建的应用程序中。

webpack.config.js

module.exports = env => {
…
    const config = {
        ...
        plugins: [
        ...
             new CopyWebpackPlugin([
                { from: { glob: "assets/*.json" } },
                { from: { glob: "fonts/**" } },
                { from: { glob: "**/*.jpg" } },
                { from: { glob: "**/*.png" } },
            ], { ignore: [`${relative(appPath, appResourcesFullPath)}/**`] }),
}

工作线程

项目类型

全部

迁移

您需要使用 nativescript-worker-loader 插件来创建工作线程。确保使用下一个标记安装软件包

npm install nativescript-worker-loader@next --save-dev

请参阅文档以根据项目类型迁移您的代码。

模板和样式路径必须为相对路径

项目类型

Angular

代码示例

考虑以下位于 app/item/items.component.ts 中的代码,它对 templateUrl 使用绝对路径

@Component({
    selector: "ns-items",
    templateUrl: "app/item/items.component.html"
})
export class ItemsComponent {
...

传统工作流程

传统工作流程用于支持上述语法。

捆绑包工作流程

捆绑包工作流程不支持上述语法。templateUrlstyleUrls 路径相对于当前模块解析。

迁移

将绝对路径转换为相对路径

@Component({
    selector: "ns-items",
    templateUrl: "./items.component.html"
})
export class ItemsComponent {
...

TS 项目中无法使用 exports 对象

项目类型

TypeScript

代码示例

以下代码使用 exports 对象导出函数

exports.onTap = function () {
    alert("Hi there");
}

传统工作流程

传统工作流程用于支持上述语法。

捆绑包工作流程

捆绑包工作流程不支持上述语法。

迁移

改为使用 export 关键字

export function onTap() {
    alert("Hi there");
}

专业提示

使用捆绑包工作流程,您现在可以在所有类型的项目中使用 ES6 模块语法 (导入和导出)。优先使用它而不是 CommonJS (require 和 exports),以帮助 webpack 从捆绑包中消除所有未使用的导出。

__dirname 和 __filename 的不同值

项目类型

全部

代码示例

考虑以下位于 app/nested-folder/test.ts 中的代码

console.log("__dirname", __dirname);
console.log("__filename", __filename);

传统工作流程

在传统工作流程中,项目结构在构建的应用程序中保持不变。执行上述代码将导致以下控制台输出

__dirname /data/data/org.nativescript.ns5/files/app/nested-folder
__filename /data/data/org.nativescript.ns5/files/app/nested-folder/main-page.js

捆绑包工作流程

在捆绑包工作流程中,构建的应用程序打包在几个输出文件中。文件位置不会持久化。上述代码的输出将为

__dirname /data/data/org.nativescript.ns6/files/app
__filename /index.js

迁移

您可以使用 module.id 获取原始文件路径。 

console.log(module.id) // ./nested-folder/main-page.ts

但是,如果您构建生产版本,则 module.id 将为一个数字。要强制 webpack 继续对模块 ID 使用文件路径,请将 namedModules 优化属性设置为 true

module.exports = env => {
…
    const config = {
        ...
        optimization: {
             namedModules: true
         }
}

__dirname 将指向捆绑包文件的绝对路径。使用 __dirnamemodule.id,您可以计算模块的原始绝对文件路径和目录。

枚举值未内联

项目类型

TypeScript

代码示例

以下代码声明了一个枚举,但未定义它,然后使用它

declare const enum TestEnum {
    value1 = 1,
    value2 = 2
}

console.log("Printing the second enum value: ", TestEnum.value2);

传统工作流程

上述语法受支持。传统工作流程用于依赖于 nativescript-dev-typescript 插件来执行 TypeScript 编译。该插件用于启动 TypeScript 编译器 - tsc

捆绑包工作流程

捆绑包工作流程在 transpileOnly 模式下使用 ts-loader。枚举值未内联。运行上述代码会导致引用错误

ReferenceError: TestEnum is not defined

迁移

您需要修改 webpack.config.js 文件中的几个设置。在 ts-loader 的配置中,将 transpileOnly 设置为 false。此外,请确保删除 ForkTypeChecking 插件。