如何在 TypeScript 文件更改时观看并重新加载 ts-node

478

我想在不每次编译Typescript文件的情况下,运行一个带有TypeScript和Angular应用的开发服务器。

我发现可以使用ts-node来运行.ts文件,但我也想观察.ts文件并重新加载我的应用/服务器。一个例子是命令gulp watch

23个回答

981

现在你可以简单地通过 npm install --save-dev ts-node nodemon 命令安装这两个包,然后使用一个 .ts 文件来运行 nodemon 就能正常工作了:

nodemon app.ts

以前的版本:

我在我的开发环境中遇到了同样的问题,直到我发现 nodemon 的 API 允许我们更改其默认行为以执行自定义命令。

例如,对于最新版本的 nodemon

nodemon --watch "src/**" --ext "ts,json" --ignore "src/**/*.spec.ts" --exec "ts-node src/index.ts"

或者创建一个 nodemon.json 文件,内容如下:

{
  "watch": ["src"],
  "ext": "ts,json",
  "ignore": ["src/**/*.spec.ts"],
  "exec": "ts-node ./src/index.ts"      // or "npx ts-node src/index.ts"
}

然后不带参数运行nodemon

通过这样做,您将能够实现ts-node进程的实时重新加载,而不必担心底层实现。


即使是更早版本的nodemon也可以实现:

nodemon --watch 'src/**/*.ts' --ignore 'src/**/*.spec.ts' --exec 'ts-node' src/index.ts

或者更好的方法是将nodemon的配置外部化到一个nodemon.json文件中,其内容如下,并只需运行nodemon,正如Sandokan所建议的那样:

{
  "watch": ["src/**/*.ts"],
  "ignore": ["src/**/*.spec.ts"],
  "exec": "ts-node ./index.ts"
}

2
如果 index.ts 是一个 express 实例,我该如何终止它并重新启动? - hjl
31
你也可以创建一个nodemon.json文件,其中包含所有提到的选项,如下所示:{ "watch": ["src/**/*.ts"], "ignore": ["src/**/*.spec.ts"], "exec": "ts-node ./app-server.ts" },然后只需键入nodemon即可。 - Sandokan El Cojo
4
我曾经犯了一个错误,在文件夹名前添加了 ./ ,导致程序出现问题。以下这段代码可以解决问题: { "verbose": true, "watch": ["server/**/*.ts"], "ext": "ts js json", "ignore": ["server/**/*.spec.ts"], "exec": "ts-node index.ts" }。对应的命令行代码为:nodemon --watch server/**/*.ts --ignore server/**/*.spec.ts --verbose --exec ts-node index.ts - Adrian Moisa
4
我想提醒一下,您还需要在配置文件中设置ext,以便它能够查找.ts文件的更改。我的配置文件如下所示:{ "watch": ["src/**/*.ts"], "ignore": ["src/**/*.spec.ts"], "ext": "ts js json", "_exec": "node dist/startup.js", "exec": "ts-node src/startup.ts" } - Lasse D. Slot
2
在Windows机器上,不要在package.json文件中使用单引号。用\"替换它们可以使脚本正常运行:"nodemon --watch \"./src/**/*.ts\" -r dotenv/config --exec \"ts-node\" src/index.ts" - TJBlackman
显示剩余12条评论

294

为了寻求更好的替代方案,我已经抛弃了 nodemonts-node ,选择了一个更好的选择,ts-node-devhttps://github.com/whitecolor/ts-node-dev

只需运行 ts-node-dev src/index.ts

[编辑] 自从我写这篇答案以来,nodemon 得到了很大改善,所需配置更轻便,性能也更好。我目前同时使用两者(在不同的项目中),并对它们都感到满意。


27
为什么这样做会更好? - Deilan
62
它更快,并自动检测需要监视哪些文件,无需配置。 - Mikael Couzic
8
对于ts-node而言,这是最好的选择(如果不是唯一的选择),特别是对于较大的项目。它不会从头重新编译所有文件,而是进行增量编译,就像“tsc --watch”一样。 - Angelos Pikoulas
14
ts-node-dev 这个工具的想法很好,但是它有很多问题。它对于真实世界的使用来说可靠性不够。遗憾的是,维护者似乎没有足够的能力来处理这些问题。我只能回归 nodemon 了... - forresthopkinsa
7
我曾使用过这个,但最终我意识到它在捕捉更改的文件方面存在严重问题。保存一个文件后,进程被重新启动,但是旧文件仍在使用,非常令人恼火。这不是已接受答案中的问题。🤦‍♂️ - Svish
显示剩余15条评论

83

其他答案中的选项概述

注意tsx(其底层使用 ESBuild)和 swc 不进行类型检查;这应该是可以接受的,因为大多数编辑器都内置了类型检查,并且类型检查仍应作为构建过程的一部分。您也可以通过tsc --noEmit单独进行类型检查,与测试一起进行或作为预推钩子。

(推荐) tsx

ⓘ TL;DR:速度最快,配置最小

截至2023-02-01,tsx似乎是速度和最小配置的最佳组合:

  1. 安装 tsx

  2. npm install --save-dev tsx
    
  3. 更新您的package.json文件,例如:

    "scripts: {
      "dev": "tsx watch src/index.ts",
    
  4. 运行它

  5. npm run dev
    

    如果您仅想全局安装 tsx 并直接运行它,请调整以下步骤:

替代方案1:nodemon/node-dev + ts-node + swc

ⓘ TL;DR: 与 tsx 一样快,但具有更多配置

另一个选择是将 nodemon/node-dev 的可靠性与 ts-node-dev 的速度相结合,使用支持 TypeScript 的 Rust 实现的转译器 swc。 swc 比 TypeScript 转译器 “快一个数量级”。

  1. 安装 nodemon 或 node-dev(根据您的喜好)

    • nodemon

      npm install --save-dev nodemon 
      
    • node-dev

    • npm install --save-dev node-dev 
      
  2. 使用 swc 集成设置 ts-node

    https://github.com/TypeStrong/ts-node#swc-1

    1. 安装必要的包

    npm install --save-dev ts-node @swc/core @swc/helpers regenerator-runtime
    
  3. 将此添加到tsconfig.json中

  4.   "ts-node": {
        "swc": true
      }
    
  • 运行nodemon或node-dev,例如:

    nodemon --watch src src/index.ts
    
    或者:
    node-dev src/index.ts
    
  • 备选方案2:nodemon/node-dev + ts-node transpileOnly

    ⓘ TL;DR: 快速、可靠

    这里提供了另一种方案,它比前一个选项慢,因为它使用标准的TypeScript转换器,但在我的测试中,它仍然比nodemon/node-dev + ts-node更快。

    基本上,它与上一个选项相同,但没有swc。通过禁用类型检查,它比开箱即用的ts-node更快(请参阅上面有关为什么应该接受此做法的说明)。

    1. 按照上述步骤安装nodemon/node-dev

    2. 安装ts-node

    npm install --save-dev ts-node
    
  • 修改您的 tsconfig.json 以启用 transpileOnly 选项,以便在使用 ts-node 时进行转译。


  •   "ts-node": {
        "transpileOnly": true
      }
    
  • 按照上述方式调用 nodemon/node-dev

  • 备选方案3:nodemon + tsc --incremental

    ⓘ TL;DR:快速、可靠、类型检查、稍微有些挑剔

    这个方案的速度几乎与前一种方案相同。与其他选项相比,唯一的优势在于它可以进行类型检查。

    就缺点而言,它可能会更加挑剔;在我的测试中,我使用dotenv来获取本地开发的.env文件。但是,根据您在tsconfig.json中配置的tsc构建方式,您可能需要进行一些特殊的工作才能使其正常工作。

    但是有多重选择总是好的,所以在这里介绍一下:

    1. 按照上述方式安装 nodemon

      (node-dev也可能适用,但我没有看到node-dev的exec选项)

    2. 将tsconfig.json配置为将TypeScript转换为JavaScript

      特别是,noEmit不应设置为true

    3. 将nodemon配置为运行TypeScript编译器,在任何时候更改TypeScript文件时进行增量转换,例如:

      "dev": "nodemon -e ts --watch src .env --exec \"tsc --incremental && node src/index.js\"",
      

      您甚至可以删除--incremental以进一步简化它,但这将使其变得更慢,与nodemon/node-dev + ts-node相当。


    如果您在本地安装了 nodemon,则无法在 cmd 上运行 nodemon。相反,使用 -g 全局安装它。 - Timo
    6
    即使没有全局安装,你仍然可以运行它(例如:node_modules/.bin/nodemon),但是考虑到我几乎总是需要为 nodemon 提供标志,将它添加到 package.json 中作为脚本更加方便,以便使用所有所需的标志运行 nodemon(参见替代方案3中的示例)。这也在处理多个项目时更加方便;你只需要调用npm run dev,而不必记住每个项目需要如何配置。当然,如果你想的话,也可以全局安装。 - bmaupin
    “type checking should still be part of your build process” 是什么意思?我该如何在构建过程中包含类型检查? - thegoodhunter-9115
    @thegoodhunter-9115 此页面上推荐的工具是用于本地开发的。但是对于生产环境,通常建议将TypeScript转译为JavaScript,这是“构建”步骤。如果您正在使用TypeScript编译器(tsc),它默认进行类型检查(实际上我认为没有关闭它的方法)。由于您可能不想等到构建时才发现是否存在任何类型错误,因此您还可以使用tsc作为测试过程或预推钩子的一部分来进行类型检查。 - bmaupin
    救命之答案 - Kashif Nazar
    目前 tsx 不支持 emitDecoratorMetadata - Filip Seman

    78

    这里提供了一个替代 HeberLZ 的答案,使用 npm 脚本。

    我的 package.json 文件:

      "scripts": {
        "watch": "nodemon -e ts -w ./src -x npm run watch:serve",
        "watch:serve": "ts-node --inspect src/index.ts"
      },
    
    • -e 标志设置要查找的扩展名,
    • -w 设置要监视的目录,
    • -x 执行脚本。

    --inspectwatch:serve脚本中实际上是一个Node.js标志,它只是启用调试协议。


    2
    请确保在项目中本地安装了TypeScript。否则,您可能会收到不太清晰的错误提示。 - Aranir
    2
    这种方法似乎会产生相当多的无用输出。 - Freewalker
    我收到了“错误:未知或意外选项:--inspect”的提示。看起来“ts-node”没有这个标志。 - Timo
    1
    @Timo 看起来从 v5.0.0 开始,对于高级 node.js 标志(例如此处的 --inspect),您需要将 ts-node 作为 node -r ts-node/register 命令运行。 - im.pankratov
    我还必须使用 --legacy-watch 标志才能实现自动重载。有什么想法为什么要这样做? - Timo
    显示剩余2条评论

    57

    2
    这对我也有效,但是为什么?似乎有点神奇。是什么编译了TypeScript?我没有安装ts-node - d512
    2
    @d512 你确定它不在你的 node_modules/ 目录下吗?如果没有,对我来说会失败。 - DLight
    3
    确实需要安装ts-node才能运行此命令。如果没有安装ts-node,运行此命令将导致出现“无法启动进程,“ts-node”执行文件未找到”的错误。你可能在node_modules中留下了这个文件。话虽如此,这个解决方案更好,因为它不需要额外的配置。 - Brandon Clapp
    1
    全局安装 ts-node: npm install -g ts-node - Rafael Pizao

    21

    你可以使用ts-node-dev

    它可以在所需的文件更改时重新启动目标节点进程(如标准node-dev),但在重新启动之间共享Typescript编译过程。

    安装

    yarn add ts-node-dev --dev
    

    而你的 package.json 可能是这样的

    "scripts": {
      "test": "echo \"Error: no test specified\" && exit 1",
      "tsc": "tsc",
      "dev": "ts-node-dev --respawn --transpileOnly ./src/index.ts",
      "prod": "tsc && node ./build/index.js"
    }
    

    谢谢!这是我发现的最简单的方法,用于启用我的 Node 服务器的自动重新加载。 - Hisham Mubarak

    20

    针对这个问题,我创建了tsc-watch库。您可以在npm上找到它。

    显而易见的用例是:

    tsc-watch server.ts --outDir ./dist --onSuccess "node ./dist/server.js"


    1
    在 Express 或 Koa 服务器的情况下,由于它实际上并不终止先前的 Node 实例,所以这将如何运作? - brianestey
    "tsc-watch" 会自动停止并重新启动进程。 - gilamran
    这正是我一直在寻找的。不确定 ts-node-dev 的目的是什么,但我无法让它报告 TypeScript 错误。在花费数小时尝试让它工作后,我尝试了 tsc-watch,它像魔法般地运行! - Charles Naccio
    @gilamran 在你的包文档中有一个错别字:"[...] 类似于 nodemon,但用于TypeCcript。" :) - Massimiliano Kraus

    13
    "watch": "nodemon --exec ts-node -- ./src/index.ts"添加到package.json文件中的scripts部分。

    9

    我用的是

    "start": "nodemon --watch 'src/**/*.ts' --ignore 'src/**/*.spec.ts' --exec ts-node src/index.ts"
    

    并且运行yarn start时,ts-node不像'ts-node'


    9

    我希望不使用ts-node,而是始终从dist文件夹运行。

    为了实现这一点,只需在package.json中设置默认配置:

    ....
    "main": "dist/server.js",
    "scripts": {
      "build": "tsc",
      "prestart": "npm run build",
      "start": "node .",
      "dev": "nodemon"
    },
    ....
    

    然后添加nodemon.json配置文件:

    {
      "watch": ["src"],
      "ext": "ts",
      "ignore": ["src/**/*.spec.ts"],
      "exec": "npm restart"
    }
    

    我这里使用了"exec": "npm restart",因此所有的ts文件都会被重新编译为js文件,然后重启服务器。

    如果在开发环境下运行:

    npm run dev
    

    使用这个设置,我将始终从分布式文件运行,不需要使用ts-node。


    像在玻璃上行走。但是一种可替代的选择,无论如何。 - TamusJRoyce

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接