原文作者:Shalitha Suranga
原文地址:https://blog.logrocket.com/how-to-debug-typescript-chrome/
翻译:一川
软件错误是编程错误或软件程序的意外行为。调试是指检查和删除软件系统中的错误的过程。程序员使用各种技术进行调试;一些开发人员将输出写入终端,而另一些开发人员则使用调试器工具来执行和监视源代码。
Google Chrome网络浏览器提供了一个内置的调试器,其中包含著名的DevTools模块,用于调试JavaScript。Chrome DevTools实现了对source map的支持,并且可以检查Node.js 和Deno调试器实例。因此,无论您是在客户端应用(即基于TypeScript的React应用)还是在服务器端应用中使用TypeScript,您都可以使用Chrome进行调试。
Chrome DevTools还可以检查Android WebViews。几乎所有基于JavaScript的跨平台移动应用开发框架都实现了DevTools协议或提供内置的基于Web的调试器 UI,因此在Chrome中也可以调试基于TypeScript的移动应用。
Web浏览器内置了对JavaScript和WebAssembly的支持,但不支持TypeScript。那么,如果 Chrome 中没有原生执行 TypeScript,如何调试它呢?Chrome 和所有标准网络浏览器都支持处理 JavaScriptsource maps。
JavaScriptsource maps通常将特定 JavaScript 源代码的特定形式映射到浏览器执行的 JavaScript 源代码。例如,很难在浏览器中调试缩小的 JavaScript 文件,但是如果您将源映射与缩小版本一起使用,则在执行其缩小版本时可以轻松调试可读的 JavaScript 文件。同样,您可以在 Chrome 中运行 TypeScript 文件的转译 JavaScript 版本时对其进行调试。
官方的 TypeScript 编译器tsc可以在转译过程中生成源映射,所以现在你可以编写 TypeScript 代码,连同源映射一起转译到 JavaScript,并在执行转译的 JavaScript 代码的同时在浏览器中调试 TypeScript 代码。这就是Chrome允许开发人员调试客户端TypeScript的方式。此外,Chrome可以通过内置的远程调试功能调试在Android WebView/Chrome上运行的客户端TypeScript代码。
使用服务器端运行时,如Node和Deno,您可以通过 v8 运行JavaScript/TypeScript并侦听Chrome DevTools 调试器事件。这就是在Chrome中调试服务器端TypeScript代码的方法。支持基于TypeScript开发的移动框架,如React Native和NativeScript,也可以与 Chrome 桌面应用程序互连,因此也可以在 Chrome 上调试 TypeScript 移动应用程序。
当您使用前端框架构建应用程序时,其 TypeScript 模板通常附带已包含的 TypeScript 编译器配置,并且它们会自动为您生成source map。但在某些情况下,您需要配置 TypeScript 编译器,生成自己的source map,并使用 HTMLscript标记手动链接转译的 TypeScript 文件。
这是了解如何在 Chrome 中调试TypeScript的好方法,因为手动配置和设置可帮助您了解TypeScript调试的内部结构。让我们准备一个开发环境来调试Chrome中的任何客户端TypeScript文件。
首先,在你喜欢的任何目录中创建一个新的npm项目,如下所示:
npm init
# --- or ---
yarn init
接下来,安装 typescriptpackage:
npm install typescript
# --- or ---
yarn install typescript
现在,生成TypeScript编译器配置文件:
npx tsc --init
默认配置不会启用source map生成,因此需要编辑自动生成的配置文件。取消注释以下tsconfig.json行以启用sourceMap生成:
"sourceMap": true,
添加一个 npm 脚本来生成JavaScript,方法是修改您的package.json:
"scripts": {
"build": "npx tsc"
},
现在,您可以使用npm run build或yarn build命令转译TypeScript文件。让我们调试以下TypeScript代码:
function sayHello(name: string): void {
let message = `Hello ${name}!`;
console.log(message);
if(name == 'TypeScript') {
console.log('.ts');
}
else if(name == 'JavaScript') {
console.log('.js');
}
}
sayHello('TypeScript');
sayHello('JavaScript');
将上述代码添加到main.ts中。接下来,在main.js中使用index.html:
<script src="./main.js"></script>
使用以下命令生成main.js和main.js.map(我们的source map):
npm run build
# --- or ---
yarn build
在以下位置http://localhost:3000提供网页内容:
npx serve
上面的代码在端口3000中启动一个静态服务器(Vercel的serve)。在 Chrome 中打开网址,打开开发者工具,然后点击来源标签。您将看到main.ts如下:
图片
尝试添加断点并重新加载应用。您可以像在Chrome中调试JavaScript一样调试TypeScript:
图片
Chrome 会自动加载source map,因为 TypeScript 编译器会将source map文件名附加到main.js:
//# sourceMappingURL=main.js.map
该debugger关键字也适用于TypeScript调试。在console.log(message); 语句后添加debugger并重新加载应用程序:
图片
为了试验,请尝试删除source map文件 (main.js.map) 并进行调试main.ts。该文件main.ts将从源面板中消失,因为 TypeScript 调试基于source map工作。
使用这种方法,可以调试与webpack、Rollup或任何其他支持TypeScript转译的JavaScript捆绑器捆绑在一起的TypeScript代码。您可以在 Chrome 中启用调试TypeScript,方法是将自动生成的源映射添加到您的网络目录。
前面,我们讨论了TypeScript调试如何在Chrome中使用手动配置进行。但正如我们提到的,几乎所有的前端框架/库都提供预先实现的TypeScript模板,其中通常包括用于生成源映射的编译器配置。结果是,当您在开发者模式下运行应用时,系统会在Chrome中自动启用TypeScript调试。
现在,我们将使用Create React App的官方TypeScript模板创建一个React应用程序,以学习如何调试使用现代前端框架构建的TypeScript应用程序。运行以下命令以创建新的TypeScript-React应用程序:
npx create-react-app my-app --template typescript
#--- or ---
yarn create react-app my-app --template typescript
现在,将以下代码添加到您的App.tsx文件中:
import React, { useState } from 'react';
import './App.css';
function App(): JSX.Element {
const [message, setMessage] = useState('');
function generateMessage(name: string): string {
let message: string = `Hello ${name}!`;
return message;
}
function handleClick(): void {
setMessage(generateMessage('TypeScript'));
}
return (
<div>
<div>{message}</div>
<button onClick={handleClick}>Say hello</button>
</div>
);
}
export default App;
上面的代码在我们单击“Say hello”按钮时呈现问候消息。使用以下命令运行项目以开始调试TypeScript:
npm start
# --- or ---
yarn start
现在,假设您需要为App.tsx的第 8 行设置断点。由于有多个源文件,因此您可以通过按Ctrl+P轻松导航到App.tsx:
图片
现在,设置断点并单击按钮。DevTools调试器按预期工作 TypeScript:
图片
尝试使用Call Stack部分来监视TypeScript函数调用:
图片
由于source map,每个调试器功能都适用于TypeScript调试。React 脚本模块进行实时TypeScript编译,因此您可以通过检查Chrome或您的终端来修复TypeScript编程错误。
让我们向generateMessage函数发送一个整数,仅用于实验目的:
function handleClick(): void {
setMessage(generateMessage(1));
}
现在,您将在Chrome和终端上看到TypeScript编译错误:
图片
所有流行的前端框架,如Angular,Vue,Svelte等,都提供TypeScript开发支持并自动生成JavaScript源映射。因此,当使用前端框架工具时,调试TypeScript变得非常容易。
如果您使用VS Code编写代码,则可以使用编辑器界面作为调试器界面,而不是Chrome DevTools。VS Code 通过预安装的JavaScript调试器扩展提供对调试JavaScript/TypeScript的内置支持。
启动您的 Web 开发服务器(即webpack开发服务器)并使用以下launch.json设置启动Chrome:
{
"version": "0.2.0",
"configurations": [
{
"type": "chrome",
"name": "Chrome",
"request": "launch",
"url": "http://localhost:3000"
}
]
}
按 F5 并开始调试时,可以从编辑器设置断点。下面是一个示例,演示如何调试App.tsx文件:
图片
您可以使用TypeScript编写Node.js和Deno后端项目。让我们讨论如何使用Chrome来调试它们。
与客户端TypeScript开发一样,在使用Node.js运行时执行项目之前,我们必须将TypeScript转换为JavaScript。客户端JavaScript执行使用 Chrome 内置的 v8 引擎,因此我们可以像以前一样直接使用DevTools调试器,但Node.js运行时使用自己的 v8 实例,因此它提供了一个内置的调试器工具,因为它不能直接使用 Chrome 的调试器JavaScript执行环境。
使用我们在客户端调试中遵循的相同步骤创建新的npm项目和一个TypeScript配置文件(启用了source map)。接下来,将以下代码添加到main.ts:
function sayHello(name: string): void {
let message: string = `Hello ${name}!`;
console.log(message);
if(name == 'TypeScript') {
console.log('.ts');
}
else if(name == 'JavaScript') {
console.log('.js');
}
}
sayHello('TypeScript');
sayHello('JavaScript');
将以下脚本添加到文件中package.json:
"scripts": {
"build": "npx tsc",
"debug": "node inspect main.js"
},
生成JavaScript文件和源映射:
npm run build
# --- or ---
yarn build
现在,使用以下命令启动Node.js调试器:
npm run debug
# --- or ---
yarn debug
上面的npm脚本初始化内置的Node.js调试器实用程序,并开始通过WebSockets侦听Chrome DevTools协议消息。您可以通过命令行使用内置的Node.js调试器实用程序,也可以通过Chrome DevTools使用 GUI 调试器。
运行上述命令后,调试器会自动将断点设置为第一个可执行语句,如下所示:
图片
内置调试器不支持TypeScript调试,因为它不理解source map— 它只是一个带有多个命令的最小调试器。例如,可以使用以下命令在第 5 行设置断点,并在新添加的断点处停止代码执行:
sb(5)
c
您可以在官方文档中查看所有内置的调试器命令。我们不会进一步讨论内置调试器,因为 Chrome 调试器是本教程的重点。
让我们在Chrome中调试这个TypeScript项目。使用debug npm脚本运行项目,然后在Chrome上转到以下网址:
chrome://inspect
现在,打开DevTools调试器 GUI,如下所示:
图片
您可以通过Chrome DevTools界面调试TypeScript文件。调试器实用程序反映终端上的调试操作。查看以下预览:
图片
早些时候,示例React项目在代码更改期间预转译了修改后的TypeScript代码。您可以使用tsc --watch和nodemon或ts-node-dev对服务器端TypeScript项目执行相同的操作。
Deno是一个安全的TypeScript运行时,您可以将其用作Node.js运行时的替代方案。在Deno中调试TypeScript不需要像基于TypeScript的Node.js应用程序那样手动配置,因为Deno本身支持TypeScript。
首先,请确保您的计算机上已经安装了Deno。如果没有,请根据官方安装指南安装最新的Deno运行时版本。
在我们之前创建的基于TypeScript的Node.js项目目录中使用以下命令启动Deno调试器:
deno run --inspect-brk main.ts
然后,打开DevTools并开始调试:
图片
可以按 F5 并调试Node.js应用,而无需额外的扩展,因为内置调试器扩展支持Node.js调试。
对于Deno,您可以安装Deno扩展以进行自动launch.json配置,也可以手动使用以下launch.json设置:
{
"version": "0.2.0",
"configurations": [
{
"name": "Deno",
"type": "node",
"request": "launch",
"cwd": "${workspaceFolder}",
"runtimeExecutable": "deno",
"runtimeArgs": ["run", "--inspect-brk", "-A", "${file}"],
"attachSimplePort": 9229
}
]
}
看看我如何使用VS Code调试TypeScript文件:
图片
基于JavaScript的跨平台移动应用程序开发框架,允许开发人员使用独立于平台的单一代码库构建应用程序,从而使开发工作流程更加轻松。有两种类型的基于JavaScript的移动框架:
使用webviews(即Android WebView)来执行JavaScript并呈现类似本机的HTML UI元素的框架,例如Ionic和Apache Cordova。
具有自己的JavaScript解释器实例(即 v8 实例)的框架,用于通过JavaScript原生接口或桥接执行JavaScript和呈现本机 UI 元素,例如React Native和NativeScript
我们可以使用TypeScript创建使用这两种框架类型的应用程序,因此能够调试基于TypeScript的移动应用程序代码非常重要。Chrome和Android WebView实现协同工作,让开发者通过Android开发者模式和Chrome远程调试功能在Chrome桌面应用上调试TypeScript Web应用(加载在WebView中)。第二种框架类型带有内置的调试工具,允许我们使用Chrome DevTools进行调试。
让我们仔细看看如何使用Chrome调试各种TypeScript移动应用程序。
调试基于Android Web View的应用
之前,我们看到了如何通过chrome://inspect内部页面输入Chrome DevTools来调试Node.js/Deno服务器端应用。同样,我们可以检查当前运行的Android WebView。如果WebView加载了TypeScript的source map,我们可以从Chrome桌面应用调试TypeScript Web应用源。为了演示此方案,我们需要一个运行TypeScript Web应用的Web视图。
首先,在开发模式下启动任何基于TypeScript的Web应用程序。如果您使用本教程创建了以前的TypeScript React应用程序,您也可以使用以下命令之一启动它:
npm start
# --- or ---
yarn start
这是我们将在Android WebView组件中加载的应用程序。我们无法引用来自手机的localhost URL,即使计算机和手机使用相同的 WiFi 网络也是如此。要从移动设备加载TypeScript应用程序,我们需要使用计算机的 IP 地址,如下所示:
图片
使用此 URL,您将能够在移动设备上查看您的TypeScript应用程序。接下来,让我们创建一个Android WebView实例并加载此 URL。我将使用Flutter轻松创建原生Web视图,因此请务必在开始之前安装最新的Flutter SDK版本。
创建一个新的Flutter应用程序:
flutter create webview_app_demo
cd webview_app_demo
安装webview_flutter插件:
flutter pub add webview_flutter
更新android/app/build.gradle种的最低 SDK 版本属性:
defaultConfig {
// ----
// ---
minSdkVersion 19
// ---
}
现在,让移动应用程序访问互联网并加载 HTTP 页面AndroidManifest.xml,方法是将以下权限和usesCleartextTraffic属性添加到:
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET" />
<application
android:usesCleartextTraffic="true"
....
....
....
最后,将以下代码添加到文件中main.dart,以将TypeScript Web应用加载到 Web 视图中。请务必替换为<computer_ip>您之前记下的真实计算机 IP:
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
useMaterial3: true,
),
home: const MyStatefulWidget());
}
}
class MyStatefulWidget extends StatefulWidget {
const MyStatefulWidget({super.key});
@override
State<MyStatefulWidget> createState() => _MyStatefulWidgetState();
}
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
late final WebViewController controller;
@override
void initState() {
super.initState();
controller = WebViewController()
..setJavaScriptMode(JavaScriptMode.unrestricted)
..loadRequest(Uri.parse('http://<computer_ip>:3000'));
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Flutter WebView Demo'),
),
body: WebViewWidget(controller: controller));
}
}
使用以下命令运行Flutter应用程序:
flutter run
现在,您可以使用Chrome远程调试功能检查此Web视图。首先,进入chrome://inspect内部页面,找到WebView实例,单击“检查”:
图片
要为TypeScript React应用设置断点,请点击手机上的“Say hello”按钮,然后查看DevTools。调试过程可以通过远程方式进行:
图片
在这里,我们使用Flutter创建了一个基于Android WebView的应用程序,但这种调试技术适用于使用原生Android SDK(基于Java/Kotlin)和其他框架(如Xamarin、React Native等)创建的 Web 视图。
您还可以使用这种Chrome远程调试方法来调试使用Ionic、Capacitor.js和Apache Cordova框架编写的基于TypeScript的混合移动应用。Chrome无法检查iOS移动设备中基于WKWebView的混合应用程序,但您可以使用Apple Safari的网络检查功能来执行此操作。
集成VS Code用于调试基于 Web 视图的应用
之前,我们看到了如何使用Chrome DevTools调试界面进行基于WebView的TypeScript移动应用程序调试。如果您是VS Code的死忠粉丝,您可以使用此免费扩展直接在编辑器中调试Android WebView。
继续在您的移动设备上运行以前的TypeScript混合应用程序。现在,让我们在VS Code上调试它。
安装Android WebView调试扩展后,可以使用以下launch.json配置将VS Code调试器接口附加到移动应用中正在运行的Android WebView实例。请确保为application属性使用正确的应用程序标识符:
{
"version": "0.2.0",
"configurations": [
{
"type": "android-webview",
"request": "attach",
"name": "Attach to Android WebView",
"application": "com.example.webview_app_demo"
}
]
}
将上述配置用于TypeScript Web应用项目后,可以按 F5,将VS Code内置调试器前端附加到首选WebView应用,然后开始调试,如以下预览所示:
图片
调试React Native应用程序
从 v0.71 开始,官方的React Native CLI脚手架应用程序默认使用TypeScript,因此我们有更多的动力使用TypeScript来构建React Native应用程序。React Native框架附带了一个内置的调试器Web应用程序,该应用程序在Web worker中托管TypeScript移动应用程序代码。因此,您可以使用Chrome或任何支持Web Worker规范的浏览器来调试TypeScript React Native应用程序源代码。
现在,让我们看看如何使用Chrome调试基于TypeScript的React Native应用程序。首先,使用以下命令创建一个新的React Native应用程序:
npx react-native init MyApp
cd MyApp
接下来,将以下TypeScript代码片段添加到您的App.tsx文件中:
import React, { useState } from 'react';
import {
SafeAreaView,
StyleSheet,
View,
Button,
Text
} from 'react-native';
function App(): JSX.Element {
const [message, setMessage] = useState('');
function generateMessage(name: string): string {
let message: string = `Hello ${name}!`;
return message;
}
function handlePress(): void {
setMessage(generateMessage('TypeScript'));
}
return (
<SafeAreaView style={styles.container}>
<View>
<Text style={styles.message}>{message}</Text>
<Button onPress={handlePress} </View>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
container: {
marginTop: 32,
padding: 24,
},
message: {
marginBottom: 32,
fontSize: 20
}
});
export default App;
接下来,使用以下命令启动应用程序并在移动设备上运行它:
npm start
# --- or ---
yarn start
加载应用程序后,您可以从终端按d打开移动应用程序中的开发人员工具菜单。然后,选择“调试”菜单项以启用调试功能。React Native将在您的默认浏览器中打开调试器 UI。如果Chrome不是您的默认网络浏览器,您也应该能够使用Chrome手动访问以下网址:
http://localhost:8081/debugger-ui/
打开调试器 Web 应用的DevTools并开始调试TypeScript移动代码:
图片
也可以从VS Code调试React Native应用程序。您可以阅读本文并了解VS Code React Native调试配置。
调试NativeScript应用
NativeScript是一个面向JavaScript的跨平台移动应用程序开发框架,使用React Native遵循的类似概念实现。它将JavaScript运行时 (v8) 嵌入到跨平台移动应用程序中,并创建一个JavaScript原生接口,让JavaScript访问原生 SDK,类似于React Native。
NativeScript允许开发人员使用TypeScript就绪的 Web 框架(如 Angular、React 和 Svelte)构建应用程序,因此我们能够调试TypeScript NativeScript应用程序非常重要。NativeScript实现了Chrome DevTools协议,让开发人员在Chrome中调试NativeScript应用。
让我们看看如何使用Chrome调试基于TypeScript的普通NativeScript应用程序。
首先,根据官方文档配置开发环境,使用TypeScript模板创建新的NativeScript应用,如下所示:
ns create MyApp --ts
此TypeScript初学者项目已经实现了一个按钮回调,因此您无需为即将到来的调试演示修改源代码。
在NativeScript调试模式下在移动设备上运行应用,如下所示:
ns debug android
# --- or ---
ns debug ios
在调试模式下加载应用后,NativeScript CLI将打印Chrome DevTools UI URL:
devtools://devtools/bundled/inspector.html?ws=localhost:40000
使用Chrome导航到此调试器网址。然后,您可以调试TypeScript应用源,如以下预览所示:
图片
若要使用 VS Code 内置调试器接口调试NativeScript应用,可以使用此免费扩展[https://marketplace.visualstudio.com/items?itemName=NativeScript.nativescript]。
总结
调试的主要目标是通过监视源代码执行和手动审查代码来识别软件错误。在大多数Web开发调试活动中,我们可以通过读取代码和使用众所周知的调试器实用程序功能来识别错误。但是,在某些复杂的场景中,我们必须生成许多测试用例并使用高级调试器功能。
大多数 Web 开发人员使用标准控制台API(即console.log)进行调试;其他人从Chrome DevTools调试器或VS Code的调试器UI开始。开始跟踪Bug时,首先从上到下分析可疑代码段。如果尚未找到bug,则尝试在逻辑流不复杂时记录运行时值。如果逻辑流很复杂,从Chrome调试器或VS Code调试器界面开始可以节省您的时间。
在本教程中,我们讨论了如何使用 Chrome 调试用TypeScript编写的浏览器、Node.js、Deno和移动应用程序。我们还讨论了如何使用VS Code的调试器 UI。
您可以根据自己的要求和个人喜好自定义和使用这些调试技术。与前端框架的TypeScript模板类似,您可以使用 通过node-typescript-boilerplate[https://github.com/jsynowiec/node-typescript-boilerplate]预配置的调试环境更快地创建基于TypeScript的Node.js项目。或者,您可以使用本教程中讨论的步骤创建自己的模板。