在 Firefox DevTools 中调试 TypeScript

Firefox 调试器在过去几个月里发展成为一个快速可靠的工具链,现在它支持许多酷炫的功能。虽然主要用于调试 JavaScript,但您是否知道您也可以使用 Firefox 来调试您的TypeScript 应用程序?

在我们进入现实世界的示例之前,请注意,当今的浏览器无法直接运行 TypeScript 代码。重要的是要了解 TypeScript 需要在包含在 HTML 页面之前编译成 Javascript。

此外,调试 TypeScript 是通过源代码映射完成的,因此我们需要指示编译器为我们生成一个源代码映射。

您将在本文中学习以下内容

  • 将 TypeScript 编译成 JavaScript
  • 生成源代码映射
  • 调试 TypeScript

让我们从一个简单的 TypeScript 示例开始。

TypeScript 示例

以下代码片段显示了一个简单的 TypeScript hello world 页面。

// hello.ts
 
interface Person {
  firstName: string;
  lastName: string;
}
 
function hello(person: Person) {
  return "Hello, " + person.firstName + " " + person.lastName;
}
 
function sayHello() {
  let user = { firstName: "John", lastName: "Doe" };
  document.getElementById("output").innerText = hello(user);
}

TypeScript (TS) 与 JavaScript 非常相似,即使是不熟悉 TypeScript 的 JS 开发人员也应该能够理解这个示例。

相应的 HTML 页面如下所示

// hello.html
 
<!DOCTYPE html>
<html>
<head>
  <script src="hello.js"></script>
</head>
<body">
  <button onclick="sayHello()">Say Hello!</button>
  <div id="output"></div>
</body>
</html>

请注意,我们在 HTML 文件中包含的是 hello.js 而不是 hello.ts 文件。当今的浏览器无法直接运行 TS,因此我们需要将 hello.ts 文件编译成普通的 JavaScript。

HTML 文件的其余部分应该很清楚。有一个按钮执行 sayHello() 函数,<div id="output"> 用于显示输出(问候消息)。

下一步是将我们的 TypeScript 编译成 JavaScript。

将 TypeScript 编译成 JavaScript

要将 TypeScript 编译成 JavaScript,您需要安装 TypeScript 编译器。这可以通过 NPM(Node 包管理器)完成。

npm install -g typescript

使用以下命令,我们可以编译我们的 hello.ts 文件。它应该生成该文件的 JavaScript 版本,扩展名为 *.js

tsc hello.ts

为了生成描述原始代码(TypeScript)和生成代码(JavaScript)之间关系的源代码映射,您需要使用一个额外的--sourceMap参数。它会生成一个相应的 *.map 文件。

tsc hello.ts --sourceMap

是的,就这么简单。

如果您有兴趣,可以阅读更多关于其他编译器选项的信息。

生成的 JS 文件应该如下所示

function greeter(person) {
  return "Hello, " + person.firstName + " " + person.lastName;
}
var user = {
  firstName: "John",
  lastName: "Doe"
};
function sayHello() {
  document.getElementById("output").innerText = greeter(user);
}
//# sourceMappingURL=hello.js.map

最有趣的事情可能是生成的代码结尾处的注释。该语法来自旧的 Firebug 时代,并引用了包含所有原始源信息源代码映射文件。

您是否好奇源代码映射文件是什么样的?它在这里。

{
   "version":3,
   "file":"hello.js",
   "sourceRoot":"",
   "sources":["hello.ts"],
   "names":[],
   "mappings":
"AAKA,SAAS,OAAO,CAAC,MAAc;IAC7B,OAAO,SAAS,GAAG,MAAM,CAAC,SAAS,GAAG,GAAG,GAAG,MAAM,CAAC,QAAQ,CAAC;AAC9D,CAAC;AAED,IAAI,IAAI,GAAG;IACT,SAAS,EAAE,MAAM;IACjB,QAAQ,EAAE,KAAK;CAChB,CAAC;AAEF,SAAS,QAAQ;IACf,QAAQ,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAC9D,CAAC"
}

它包含有关生成文件(hello.js)、原始文件(hello.ts)的信息(包括位置),最重要的是,这两个文件之间的映射。有了这些信息,调试器就知道如何解释 TypeScript 代码,即使它对 TypeScript 一无所知。

原始语言可以是任何东西(RUST、C++ 等),通过正确的源代码映射,调试器就知道该怎么做。这难道不是魔法吗?

我们现在已经准备就绪。下一步是将我们的应用程序加载到调试器中。

调试 TypeScript

调试体验与调试标准 JS 的方式没有区别。您实际上是在调试生成的 JavaScript,但由于源代码映射可用,调试器知道如何向您显示原始 TypeScript。

这个例子可以在 网上找到,所以如果您正在运行 Firefox,您可以立即尝试它。

让我们从在原始 TypeScript 文件中的第 9 行创建一个断点开始。要命中断点,您只需单击之前介绍的“说你好!”按钮即可。

Debugging TypeScript

看,是 TypeScript!

请注意右侧的调用堆栈面板,它正确地显示了来自 hello.ts 文件的帧。

还有一件事:如果您有兴趣查看生成的 JavaScript 代码,可以使用上下文菜单直接跳转到它。

此操作应将您导航到 hello.js 文件,您可以从同一位置继续调试。

您可以看到“源”树(左侧)同时显示了这两个文件。

映射作用域

让我们看看另一个可以检查原始作用域和生成作用域中的变量的巧妙功能。

这是一个更复杂的glitch 示例

  1. 加载 https://firefox-devtools-example-babel-typescript.glitch.me/
  2. 打开 DevTools 工具箱并选择调试器面板
  3. Webpack/src/index.tsx 文件的第 45 行创建一个断点
  4. 断点应该立即暂停 JS 执行

Screenshot of the DevTools debugger panel allowing inspection of variables in both original and generated scopes

请注意右侧的“作用域”面板。它显示了来自生成代码(也是最小化代码)的变量,它与您在调试器面板中看到的原始 TSX(带有 JSX 的 TypeScript)代码不符。

有一个奇怪的 e 变量而不是 localeTime,而 localeTime 实际上是在源代码中使用的。

这就是“映射作用域”功能发挥作用的地方。要查看原始变量(在原始 TypeScript 代码中使用),只需单击“映射”复选框。

Debugger panel in Firefox DevTools,using the Map checkbox to see original TypeScript variables

看,“作用域”面板现在显示了 localeTime 变量(是的,魔法来自源代码映射)。

最后,如果您有兴趣了解 e 变量来自哪里,请使用上下文菜单跳转到生成的位置(就像我们在前面的示例中所做的那样)。

DevTools showing Debugger panel using the context menu to locate the e variable

敬请期待更多即将推出的调试器功能!

Jan ‘Honza’ Odvarko

关于 Jan Honza Odvarko

Honza 正在开发 Firefox 开发者工具

Jan Honza Odvarko 的更多文章…