我报名参与金石计划1期应战——分割10万奖池,这是我的第1篇文章,点击检查活动详情

概述

运用 typescript 写 node ,本来以为在 vscode 上调试是件很简略的工作,成果还是踩了一些小坑。下文记载一下踩坑的过程和具体的处理计划

下文收拾运用两套计划在 vscode 中调试 typescript :

  1. 直接运用 tsc 编译 typescript 代码,然后运用 vscode 调试
    • PS:tsc 是 typescript 的指令行工具,能够将 .ts 文件编译成 .js 文件,具体能够官网文档或中文翻译文档
  2. 运用 ts-node 库帮忙编译,然后再运用 vscode 调试

PS,vscode、tsc、node 版本如下:

  1. vscode:1.71.2
  2. tsc:4.8.3
  3. node:16.13.1

计划一:tsc

demo 演示项目:demo-ts-debugger,能够 clone 下来然后跟着下文过程测验

这个计划是 vscode 官网文档——Debugging TypeScript 中的计划,但官网文档中提到的内容感觉不太全,有些坑和细节没细讲( 也许是官网大大觉得这些都是知识吧 (〒︿〒)

完整作用

如下图 gif,演示运用 tsc 编译 typescript 代码,然后运用 vscode 调试的作用:

浅谈在 vscode 中调试 typescript 的小坑

到达调试的预期作用:

  1. 直接定位ts 源文件,而不是跳去编译出来的 js 文件
    • 在代码中运用 debugger 或许直接在 vscode 中打断点都能够
  2. 支撑源文件中运用别号(alias)

launch.json

{
  "version": "0.2.0",
  "configurations": [
    {
      "type": "node",
      "request": "launch",
      "name": "Launch Program",
      "program": "${workspaceFolder}/src/index.ts",
      "preLaunchTask": "tsc: build - tsconfig.json",
      "outFiles": ["${workspaceFolder}/out/**/*.js"]
    }
  ]
}

launch.json 的具体字段阐明能够参阅:官网文档,部分字段中文意义能够参阅:vscode调试学习

挑三个对这次调试使命来说比较重要的字段阐明一下:

  1. program
    • “发动调试器时要运转的可履行文件或文件”
    • 我猜:这个应该是调试器加载需求调试代码的入口文件吧
    • 试了把这个字段的值改成 "${workspaceFolder}/out/index.js" 也能够正常运转,可能是有 map 吧,暂时没找到具体解说,期望有了解里边细节的朋友谈论区告知一下
    • 别的,假如把这个字段删掉就有问题,无法正常调试
  2. preLaunchTask
    • “要在调试会话开端之前发动使命,请将此属性设置为 tasks.json 中指定的使命标签(在工作区的 .vscode 文件夹中)。或许,这能够设置 ${defaultBuildTask} 为运用您的默许构建使命”
    • 翻译一下便是在调试发动之前会先履行 tasks.json 指定的使命,至于指定的是哪个使命呢?就看 preLaunchTask 的值和 tasks.jsonlabel 的对应关系,如下图:
      • 浅谈在 vscode 中调试 typescript 的小坑
      • 这样阐明,调试发动之前会先履行 tasks.jsonlabel 标签是 tsc: build - tsconfig.json 的使命
      • PS:这里有一个坑,假如一开端没有 task.json 文件的话,直接发动调试会弹出一个对话框,提示并帮助你生成 task.json 文件,如下图:
        • 浅谈在 vscode 中调试 typescript 的小坑
        • 但假如 vscode 运用了中文版(中文语言包)的话,自动生成的 task.json 文件中的 label 的值是 "tsc: 构建 - tsconfig.json" ,要手动换成 "tsc: build - tsconfig.json"
        • 反正记住 preLaunchTask 的值和 tasks.jsonlabel 的值向对应就准没错
  3. outFiles
    • 按照官网的说法:Mapping the output location
      • If generated (transpiled) JavaScript files do not live next to their source, you can help the VS Code debugger locate them by setting the outFiles attribute in the launch configuration. Whenever you set a breakpoint in the original source, VS Code tries to find the generated source by searching the files specified by glob patterns in outFiles.
    • 但好像去掉这个字段也是能够正常调试的,暂时不确定具体原因和用法

别的,装备中如:${workspaceFolder} 之类的特别变量,具体可参阅:官方文档 —— variables-reference,这里就不一一翻译里,文档里边还挺具体的 (~ ̄▽ ̄)~

tasks.json

{
  "version": "2.0.0",
  "tasks": [
    {
      "type": "typescript",
      "tsconfig": "tsconfig.json",
      "problemMatcher": [
        "$tsc"
      ],
      "group": "build",
      "label": "tsc: build - tsconfig.json"
    }
  ]
}

关于 vscode 中 tasks 的用法和介绍,能够参阅:官方文档 —— tasks

关于 tasks.json 文件中各个字段的解析,能够参阅:官方文档 —— tasks-appendix

上述这份 tasks.json 文件中的内容作用便是运用 tsc 指令行工具,将 typescript 代码编译成 javascript 代码

如安在源码中运用“别号”(alias)?

用过 webpack 别号 alias,应该不陌生,能够十分优雅地处理两个问题:

  1. 相对途径太长
  2. 运用相对途径 import 的文件,一旦移动了文件,要重新修正相对途径

比方,在文档: webpack 别号 alias 中的事例,界说了 src/utilities/ 途径的别号为:Utilities 后,就能够运用 import Utility from 'Utilities/utility'; 替换本来的相对途径的写法:import Utility from '../../utilities/utility'; ,灰常方便

tsc 并不支撑这种做法,需求借助第三方库:module-alias 才干完结上述作用。

要想运用 module-alias 一共有三步:

  1. tsconfig.json 文件中添加 baseUrlpaths 两个字段
    • 浅谈在 vscode 中调试 typescript 的小坑
    • baseUrl 字段指代当前根目录
    • paths 里边则用于界说自己想界说的别号(alias)
      • 如上图,咱们把 src 目录下的一切途径都起一个别号,叫: @
      • 这样,后续 demo 源码 中 import sum from './utils/sum' 的写法就能够替换成 import sum from '@/utils/sum'
  2. 装置 module-alias 依靠,并且在 package.json 文件中界说 _moduleAliases 字段
    • 浅谈在 vscode 中调试 typescript 的小坑
    • 细心的朋友可能现已发现,为什么 _moduleAliases 中界说的别号跟 tsconfig.json 文件中的 paths 不一样?下面咱们一起看看编译出来的 out 目录下的 js 文件内容就知道:
      • 浅谈在 vscode 中调试 typescript 的小坑
      • 能够看到 import sum from '@/utils/sum' 编译出来的内容是 var sum_1 = require("@/utils/sum")
        • 即:在编译阶段,tsc 并没有因为多了 module-alias 就把 @ 这个自界说别号“翻译”出来。实际上我猜 module-alias 应该是在 js 运转时才完结的这步“翻译”操作
  3. 在项目的入口文件中引进 import 'module-alias/register';
    • 浅谈在 vscode 中调试 typescript 的小坑

失利记载

一开端查找 tsc 文档时,发现了这个编译选项:–paths (在 compiler-options 能够检查一切 tsc 的编译选项)

一开端以为能够完结预期的别号作用,但实际上并不行,会报一下过错:

error TS6064: Option ‘paths’ can only be specified in ‘tsconfig.json’ file or set to ‘null’ on command line.

暂时没搞懂,就没走这条路了,换成了上述成功的路途

计划二:ts-node

demo 演示项目:demo-father-ts-debugger,能够 clone 下来然后跟着下文过程测验

这个计划是运用 ts-node 库帮忙编译,然后再运用 vscode 调试

别的,运用了 Umi 的 father 作为项目的脚手架

完整作用

如下图 gif,演示运用 ts-node 库帮忙编译,然后再运用 vscode 调试

到达调试的预期作用:(跟上面 tsc 的计划的预期作用一致)

  1. 直接定位到 ts 源文件,而不是跳去编译出来的 js 文件
    • 在代码中运用 debugger 或许直接在 vscode 中打断点都能够
  2. 支撑源文件中运用别号(alias)

装置 ts-node 和 tsconfig-paths

这个计划依靠 ts-node 和 tsconfig-paths 这两个第三方库

  1. ts-node,用来将 ts 编译成 js
  2. tsconfig-paths,用来完结上述别号(alias)的作用

launch.json

launch.json 文件内容字段就不赘述了,具体能够参阅上述 “计划一:tsc” 小节的内容

浅谈在 vscode 中调试 typescript 的小坑

这份装备基本是直接照抄: tsconfig-paths 中的运用文档

关于这个计划来说,最核心的应该便是上图中的 runtimeArgsargs 两个字段

我猜:(对又是合理性猜测)

  1. 上面 runtimeArgs 中的内容,是传给发动调试程序时的参数,表示运用 ts-node 编译以及运用 tsconfig-paths “翻译” 别号
  2. 上面 args 中的内容,表示从 "${workspaceFolder}/src/index.ts" 文件作为入口开端编译 ts 代码

为什么会有上述猜测?能够看看下图:

浅谈在 vscode 中调试 typescript 的小坑

这个是发动调试程序后,vscode 中 “调试控制台” 打印出来的内容

/Users/nicholas/.nvm/versions/node/v16.13.1/bin/node -r /Users/nicholas/Nicholas/my-pro/demo/demo-father-ts-debugger/node_modules/ts-node/register -r /Users/nicholas/Nicholas/my-pro/demo/demo-father-ts-debugger/node_modules/tsconfig-paths/register /Users/nicholas/Nicholas/my-pro/demo/demo-father-ts-debugger/src/index.ts

很明显,是调用了一个 node 程序的指令,其他内容都作为指令的参数传了进去

如安在源码中运用“别号”(alias)?

这个计划运用别号(alias)的办法比较简略,只需求修正 tsconfig.json 文件即可

浅谈在 vscode 中调试 typescript 的小坑

相对来说,这个计划简略一下,需求修正的地方也不多

One More Thing

按理来说,“计划一:tsc” 应该是能够扩展的,比方不用 tsc 编译代码之类的

比方,在 “计划二:ts-node” 中运用了 Umi 的 father 作为项目的脚手架,那么,应该是能够修正“计划一:tsc”中的 tasks.json ,不用 tsc 使命,换成是 father 的指令行工具,履行编译使命,应该也是能够的,各位看官有兴趣能够测验一下 (~ ̄▽ ̄)~