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





5.00/5 (2投票s)
如何将 Angular 1 应用程序转换为 TypeScript。
随着 Angular 2 的即将发布,开始将 Angular 1 应用升级到使用 TypeScript 是很有意义的。
我有一个名为“Extreme Results”的 Angular 1.x 应用,我打算在某个时候将其升级到 Angular 2。本文中提到的所有代码都可以在该应用的 GitHub 仓库中找到。
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 了,而不用担心一切都会崩溃。