65.9K
CodeProject 正在变化。 阅读更多。
Home

将我的 Angular 1 应用程序转换为 TypeScript

starIconstarIconstarIconstarIconstarIcon

5.00/5 (2投票s)

2016年3月24日

CPOL

6分钟阅读

viewsIcon

11014

如何将 Angular 1 应用程序转换为 TypeScript。

随着 Angular 2 的即将发布,开始将 Angular 1 应用升级到使用 TypeScript 是很有意义的。

我有一个名为“Extreme Results”的 Angular 1.x 应用,我打算在某个时候将其升级到 Angular 2。本文中提到的所有代码都可以在该应用的 GitHub 仓库中找到。

Typescript logo

Angular 团队的升级指南指出,升级到 Angular 2 的准备步骤之一是将您的应用迁移到 TypeScript。

对于这次迁移,我专注于构建步骤,而不是实际编写任何 TypeScript 特定的内容。这很有效,因为 TypeScript 是 JavaScript 的超集。我真正需要为我的源文件做的是将它们从 fileName.js 重命名为 fileName.ts

这次迁移的挑战在于设置构建系统来编译 TypeScript 文件,并确保一切都能正常工作。

那么,迁移后还需要保留哪些功能呢?

  • 开发环境
    • 我仍然可以启动一个开发服务器,该服务器会在每次我保存文件时自动编译并准备好一切。
    • 开发过程中不增加额外步骤至关重要。我使用 TypeScript 不应该让编码变得更复杂!
  • 分发构建
    • 通过一个简单的命令即可完成最小化和所有编译。创建适当的构建不应该更难!
  • 带覆盖率的单元测试
    • 事实证明,这是最难处理的部分。
    • 让测试正常运行并不难,但覆盖率并没有那么容易,因为它需要源映射和额外步骤才能正常工作。

现在我们知道了需要保留什么功能,让我们开始吧!

将所有文件转换为 TypeScript 文件

这是最容易的部分。只需将每个文件从 fileName.js 重命名为 fileName.ts

稍后我将修改它们以实际使用 TypeScript 功能。目前,TypeScript 没有任何价值,但这将在以后的博客文章中详细介绍。

如果在后续编译过程中看到任何错误,暂时都可以安全地忽略它们。我们以后再解决。现在,我们只关注让构建过程与 TypeScript 一起工作。

如果我想的话,我本可以手动使用 TypeScript 并编译所有内容,但我需要将其集成到我已有的构建过程中。这就引出了下一步。

捆绑包

我使用一个名为 gulp-bundle-assets 的工具来捆绑我的所有文件,开发环境和分发构建都使用它。

它基本上将所有 JavaScript 文件捆绑成更小的文件(我的文件 + 第三方文件)。

为了实现这一点,我需要在构建过程中添加一个额外的步骤来将我的所有 TypeScript 文件编译成 JavaScript。

我使用了一个名为 gulp-typescript 的 gulp 插件。

我使用 npm 安装了 TypeScript 和 gulp-typescript

npm install --save-dev typescript gulp-typescript

然后我添加了 gulp 任务来执行实际的编译。

gulp.task('typescript', ['clean'], function () {
    return gulp.src('src/app/**/*.ts')
        .pipe(typescript({
            target:'es5'
        }))
        .js
        .pipe(gulp.dest('tmp/typescript'));
    });

这将把每个 .ts 文件编译成 JavaScript(具体来说是 ES5,可以在所有浏览器上运行),并将它们保存到 ‘tmp/typescript’。

然后配置 gulp 任务在 bundle 任务之前运行。

gulp.task('bundle', ['clean', 'templates', 'typescript'], function() {

我还必须更新我的 bundle 配置文件,使其查找已编译的文件而不是普通的 JavaScript 文件(因为它们已不存在)。

scripts: [
    './tmp/typescript/app.js',
    './tmp/typescript/**/*.module.js',
    './tmp/typescript/**/*.js'
],

实际上,这就是开发和分发构建正常工作所需的所有内容。bundle 任务会像以前一样拾取所有已编译的文件并将它们捆绑起来。

如果您不使用 bundle,则需要进行调整以使其适合您。也许您需要将开发服务器指向已编译的输出文件夹,或者类似的东西。

它应该只需要比这多一点的努力,但您可能需要找到适合您特定构建过程的解决方案。

单元测试

运行单元测试所需的第一步是将 karma.conf.js 指向我的已编译文件,而不是常规的 JavaScript 文件(再次强调,这些文件已基本不存在)。

这也意味着您必须在运行测试之前进行构建。

如果您使用 Gulp 或 Grunt 来启动测试,那么您只需确保在启动 Karma 之前执行 TypeScript 编译。

所以,在 karma.conf.js 中,我只需要做

files: [
    ...,
    'tmp/typescript/**/*.module.js',
    'tmp/typescript/**/*.js',
]

现在测试加载已编译的文件,并且测试运行如预期。太棒了!

一切正常!除了一个问题……

覆盖率

我过去可以直接从 Karma 获取完整的覆盖率报告。现在我必须对这部分稍作修改,因为覆盖率需要应用于 TypeScript 文件,而不是已编译的 JavaScript 文件。

为此,我需要做几件事。

创建源映射

在编译 TypeScript 时,您还需要生成源映射。这相当容易,只需要一个为您完成所有工作的新的 gulp 插件。

我使用了 gulp-sourcemaps 并修改了 TypeScript 任务,使其执行以下操作:

gulp.task('typescript', ['clean'], function () {
    return gulp.src('src/app/**/*.ts')
        .pipe(sourcemaps.init())
        .pipe(typescript({
            target:'es5'
        }))
        .js
        .pipe(sourcemaps.write({sourceRoot: __dirname + '/src/app'}))
        .pipe(gulp.dest('tmp/typescript'));
    });

请注意,它在开始编译 TypeScript 文件之前执行了 sourcemaps.init()

然后它会将源映射写入这些文件,并带有非常特殊的 sourceRoot

sourcemaps.write 中的 sourceRoot 选项确保我们能从已编译输出的来源找到源文件。

这是必需的,因为我将已编译的文件输出到一个与源文件(可在 src/app 中找到)不同的文件夹(tmp/typescript)。

为测试创建覆盖率报告

我假设您已经有了覆盖率报告,并且已经安装了 karma-coverage 并进行了配置。

如果没有,请查看我之前的关于覆盖率的博客文章:将覆盖率添加到您的 Angular 项目

在创建完整的覆盖率报告之前,我们需要为针对 JavaScript 文件运行的测试创建一个报告。这在 Karma 中完成。

我仍然使用 karma-coverage 来完成此操作,但现在我仅将输出作为中间步骤,以稍后使用源映射生成完整的报告。

Karma 配置文件现在需要这些更改:

preprocessors: {
     'tmp/typescript/**/*.js': ['coverage']
}
coverageReporter: {
    type : 'json',
    subdir: '.',
    dir : 'coverage/'
}

我现在针对已编译的 TypeScript 文件(在我的 tmp/typescript 文件夹中)运行覆盖率,并为此生成一个 JSON 覆盖率报告。这个报告将在下一步中使用。

使用源映射为 TypeScript 文件创建完整的覆盖率报告

为了创建完整的报告,我使用了一个名为 remap-istanbul 的工具。我没有将此工具集成到任何构建过程中,而是为它创建了一个 npm 脚本。

这样做的原因是,我并不总是需要覆盖率报告。

我会在需要时创建它们,更具体地说,我会在 Travis(我的持续集成系统)中创建它们,并将它们发送到 codecov,以便在我的 GitHub README 文件中获得一个漂亮的覆盖率徽章。

生成完整报告所需的 npm 脚本如下:

"generateLcov": "remap-istanbul -b src/app/ 
-i coverage/coverage-final.json -o coverage/lcov.info -t lcovonly"

我在 .travis.yml 文件中创建覆盖率报告:

- npm run citest
- npm run generateLcov

我可能会,而且很可能会即时创建一些 HTML 报告,以最大限度地利用覆盖率报告。

使用测试覆盖率报告

有关如何使用 remap-istanbul 的更多信息,请参阅:
https://github.com/SitePen/remap-istanbul

接下来是什么?

好了,现在我已经有了 TypeScript,但没有任何好处。到目前为止,任何事情都没有真正添加价值。所以这是应用程序的下一步。实际使用 TypeScript 来获得一些价值。

我将在后续的博客文章中详细介绍。

但至少我们现在可以开始编写 TypeScript 了,而不用担心一切都会崩溃。

© . All rights reserved.