Tips for monitoring and automatically reloading ts-node when there are changes in TypeScript files

I'm experimenting with setting up a development server for my TypeScript and Angular application without having to transpile the .ts files every time.

After some research, I discovered that I am able to run .ts files using ts-node, but I also want the ability to watch .ts files and automatically reload my app or server. An example of this functionality can be seen in the command gulp watch.

Answer №1

If you want to effortlessly set up your development environment, just use

npm install --save-dev ts-node nodemon
and then execute nodemon with a .ts file:

nodemon app.ts

Past versions:

I faced the same issue in my setup until I discovered that you can customize the behavior of nodemon using its API.

For instance, in the latest version of nodemon:

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

Alternatively, create a nodemon.json file with these settings:

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

Then simply run nodemon without any arguments.

By following this approach, you can live-reload a ts-node process hassle-free, without concerning yourself with the details of the implementation.


For older versions of nodemon:

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

Or take it up a notch: move nodemon's configuration to a separate nodemon.json file with these specifications, and then just launch nodemon, as suggested by Sandokan:

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

Answer №2

I have made the switch from using nodemon and ts-node to a more superior alternative, ts-node-dev. https://github.com/whitecolor/ts-node-dev

Simply execute ts-node-dev src/index.ts

[EDIT] I should note that since posting this answer, nodemon has significantly improved in terms of configuration and performance. I now utilize both tools on separate projects and am content with their functionality.

Answer №3

Summary of Best Options for Running TypeScript in Node.js

  • nodemon plus ts-node: Stable but requires explicit configuration and can be slow.
  • node-dev plus ts-node: Less configuration than nodemon but still slow.
  • ts-node-dev: Fast but may have reliability issues.

Note: Use tsx or swc for fast transpilation without type checking, as most editors offer built-in type checking capabilities.

(Recommended) tsx

ⓘ TL;DR: fastest with minimal configuration

Tsx provides a fast and easy-to-configure solution for running TypeScript in Node.js:

  1. Install tsx

    npm install --save-dev tsx
    
  2. Update your package.json scripts

    "scripts": {
      "dev": "tsx watch src/index.ts",
    
  3. Run the script

    npm run dev
    

    (Adjust steps for global installation if needed)

Alternative Approaches:

1. nodemon/node-dev + ts-node + swc

ⓘ TL;DR: fast but more configuration required

Combine nodemon/node-dev with ts-node and swc for improved speed:

  1. Install nodemon or node-dev

  2. Set up ts-node with swc integration

  3. Run nodemon or node-dev

2. nodemon/node-dev + ts-node transpileOnly

ⓘ TL;DR: reliable with standard TypeScript transpiler

A faster alternative using standard Ts-node transpiler without swc:

  1. Install nodemon/node-dev

  2. Install ts-node

  3. Enable transpileOnly in tsconfig.json

  4. Start nodemon/node-dev

3. nodemon + tsc --incremental

ⓘ TL;DR: reliable with type checking, more complex

This approach includes type checking but requires more setup:

  1. Install nodemon

  2. Configure tsconfig.json for incremental transpilation

  3. Setup nodemon to run the TypeScript compiler on file changes

Answer №4

Instead of using HeberLZ's solution, you can try a different approach that involves npm scripts.

Below is an example from my own package.json:

  "scripts": {
    "watch": "nodemon -e ts -w ./src -x npm run watch:serve",
    "watch:serve": "ts-node --inspect src/index.ts"
  },
  • The -e flag specifies the extensions to be watched,
  • The -w flag sets the directory to watch,
  • The -x flag executes the specified script.

The --inspect option in the watch:serve script is related to node.js and enables debugging protocol.

Answer №5

I've found success using the following command:

nodemon src/index.ts

It seems that this method has been effective since the implementation of this pull request: https://github.com/remy/nodemon/pull/1552

Answer №6

If you're looking to streamline your development process, consider utilizing ts-node-dev

With ts-node-dev, the target node process is restarted every time a required file changes (similar to standard node-dev), but it also shares the Typescript compilation process between restarts.

Get Started

yarn add ts-node-dev --dev

Your package.json file can be configured like this:

"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"
}

Answer №7

If you're dealing with this particular problem, I have developed the tsc-watch library specifically for it. You can easily access it on npm.

An obvious scenario where you could use it is:

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

Answer №8

To include the command

"watch": "nodemon --exec ts-node -- ./src/index.ts"
in the scripts part of your package.json.

Answer №9

I believe it's best to avoid using ts-node and instead always run from the dist folder.

To achieve this, simply configure your package.json with the following settings:

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

Next, include a nodemon.json configuration file:

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

In this setup, I utilize "exec": "npm restart"
This ensures that all ts files will be recompiled to js files before restarting the server.

To run in a development environment, use the command:

npm run dev

By following this configuration, you can always run the application from the distributed files without relying on ts-node.

Answer №10

i tried using the following script:

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

when I ran 'yarn start', an error occurred with the message stating that it did not recognize 'ts-node'

Answer №11

Standard Solution

Starting from Node.js version v16.19.0, the CLI introduces a convenient --watch option, eliminating the need for external dependencies such as nodemon.

To run TypeScript code, leverage the popular package ts-node. Below is an example of how to configure it:

// package.json
{
    "scripts": {
        "dev": "node --watch --loader=ts-node/esm ./src/app.ts"
    },
    "devDependencies": {
        "ts-node": "~10.9.0"
    }
}

Alternative Approach

If you're open to exploring other options, consider checking out tsx, although it may not be as mature as ts-node.

Please note that tsx does not currently support emitDecoratorMetadata, which is essential for projects utilizing decorators. Despite this limitation, tsx offers quicker compilation (powered by esbuild backend):

// package.json
{
    "scripts": {
        "dev": "tsx watch ./src/app.ts"
    },
    "devDependencies": {
        "tsx": "~4.6.0"
    }
}

Answer №12

An alternative approach is to start by compiling the code in watch mode using tsc -w and then running nodemon on the generated JavaScript files. This technique offers a comparable speed to ts-node-dev while providing a more production-ready environment.

 "scripts": {
    "watch": "tsc -w",
    "dev": "nodemon dist/index.js"
  },

Answer №13

Step one - Start by installing the packages listed below in your project dependencies

npm i -D @types/express @types/node nodemon ts-node tsc typescript

You can also use yarn:

yarn add -D @types/express @types/node nodemon ts-node tsc typescript

Step two - Add the following configuration to your tsconfig.json file

{
  "compilerOptions": {
    "target": "es6" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', 'ES2021', or 'ESNEXT'. */,
    "module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */,
    "lib": [
      "DOM",
      "ES2017"
    ] /* Specify library files to be included in the compilation. */,
    "sourceMap": true /* Generates corresponding '.map' file. */,
    "outDir": "./dist" /* Redirect output structure to the directory. */,
    "rootDir": "./src" /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */,

    "strict": true /* Enable all strict type-checking options. */,
    "moduleResolution": "node" /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */,
    "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */,
    "skipLibCheck": true /* Skip type checking of declaration files. */,
    "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */
  },
  "exclude": ["node_modules"],
  "include": ["./src"]
}

Step three - Implement the following scripts in your package.json file

"scripts": {
    "start": "node ./dist/server.js",
    "dev": "nodemon -L ./src/server.ts && tsc -w"
},

Answer №14

Include the following code in your package.json file:

scripts {
"dev": "nodemon --watch '**/*.ts' --exec 'ts-node' index.ts"
}

In order for this to work, you must also install ts-node as a dev-dependency

yarn add ts-node -D

To start the development server, run yarn dev

Answer №15

STEP 1: To get started, you need to install nodemon and ts-node. If you have already installed them, you can skip this step.

npm install --save-dev nodemon ts-node

STEP 2: Next, configure the start script in your package.json file.

"start": "nodemon ./src/app.ts"

Nodemon now automatically detects TypeScript files in your project and uses the ts-node command. Simply run npm start to compile, watch, and reload your application.

If you encounter errors regarding TypeScript modules not being found in your project, simply run the following command in your project folder.

npm link typescript

Answer №16

Encountered an error with code: 'ERR_UNKNOWN_FILE_EXTENSION'. I required esm support, so to enable ES6 functionality, you can use the following commands:

npm i -D ts-node nodemon

Add the script below to your package.json file:

"dev": "nodemon --exec ts-node-esm ./src/index.ts"

Answer №17

To resolve the issue, simply update these 3 packages:

nodemon, ts-node, typescript
yarn global add nodemon ts-node typescript

Alternatively, you can use npm:

npm install -g nodemon ts-node typescript

Once updated, execute the following command to solve the problem:

nodemon <filename>.ts

Answer №18

Refresh console logs after making changes

Javascript:

"start": "nodemon -x \"clear && node\" index.js",

Typescript:

"start": "nodemon -x \"clear && ts-node\" index.ts",

Answer №19

The simplest solution would be to download Nodemon and execute the following command: "nodemon --exec npx ts-node --esm test.ts"

Answer №20

If you encounter any issues while using

"type": "module"
in your package.json file (as detailed in this GitHub issue), you can resolve them by applying the following configuration:

{
  "watch": ["src"],
  "ext": "ts,json",
  "ignore": ["src/**/*.spec.ts"],
  "exec": "node --loader ts-node/esm --experimental-specifier-resolution ./src/index.ts"
}

You can also use the following command line options:

nodemon --watch "src/**" --ext "ts,json" --ignore "src/**/*.spec.ts" --exec "node --loader ts-node/esm --experimental-specifier-resolution src/index.ts"

Answer №21

To activate the --poll feature on your package.json file, simply add the option within your scripts section. The --poll flag instructs ts-node-dev to actively monitor source code files for changes by intermittently scanning them, rather than relying on the file system's change notifications. This ensures that any modifications made to the files are promptly detected, even in cases where the file system may not reliably report changes.

   "start": "ts-node-dev --poll src/index.ts"

Answer №22

Utilize ts-node-dev version 2.0.0+ with the following command:

ts-node-dev --respawn ./src/index.ts

*Note: In case of an error stating "command not found", you can execute it directly from node-modules as follows:

./node_modules/.bin/ts-node-dev --respawn ./src/index.ts

Answer №23

If you're looking to integrate tsc and the payload more tightly without resorting to running them in parallel, there's an alternative approach that involves incorporating them together. You can achieve this by creating a Node.js script that waits for the TypeScript compiler to finish building before initiating your process.

For one of my projects, I devised the following solution (note: this requires the installation of the tree-kill package):

#!/usr/bin/env node

import { spawn } from 'node:child_process';
import { join } from 'node:path';
import { createInterface } from 'node:readline';
import process from 'node:process';
import kill from 'tree-kill';

const cwd = process.cwd();
const tscConfigPath = join(cwd, 'tsconfig.build.json');
const tscArgs = ['tsc', '--build', '--watch', '--pretty', tscConfigPath];
const command = process.argv.slice(2);

// adjust params above as necessary

const tsc = spawn('yarn', tscArgs, { // change if not using yarn
  stdio: ['ignore', 'pipe', 'inherit'],
  cwd,
});

let proc;

const startCommand = () => {
  proc && kill(proc.pid);
  proc = spawn(command[0], command.slice(1), { stdio: 'inherit', cwd });
};

const rl = createInterface({
  input: tsc.stdout,
  terminal: false,
});

rl.on('line', (line) => {
  console.log(line);
  if (line.includes('Found 0 errors. Watching for file changes.')) {
    startCommand();
  }
});

tsc.on('exit', (code) => {
  console.log('tsc exited with code', code);
  proc && kill(proc.pid);
  process.exit(code);
});

process.on('SIGINT', () => {
  kill(tsc.pid);
  proc && kill(proc.pid);
  process.exit(0);
});

process.on('exit', () => {
  kill(tsc.pid);
  proc && kill(proc.pid);
});


I implement it in other packages within my monorepo like so in the package.json configuration:

"scripts": {
  "start:dev": "run-on-tsc-build yarn node dist/main.js"
}

This method functions by waiting for the message "Found 0 errors. Watching for file changes." from TypeScript before executing the specified command.

Answer №24

Utilizing nodemon in conjunction with ts-node:

nodemon --watch source --ext ts,json --exec "node --loader ts-node/esm ./source/index.ts"

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Utilize the value of one variable to determine access to another variable in Javascript

I am working with several boolean variables and I want to create a new variable that keeps track of the most recently changed boolean variable. This way, every time a new boolean variable is modified, I can toggle the previous one. If you have any ideas o ...

Display Bootstrap Modal using Typescript in Angular

Looking for some creative ideas here... My Angular site allows users to register for events by filling out a form. They can also register themselves and other people at the same time. https://i.sstatic.net/a44I7.png The current issue ~ when a user clicks ...

Using TypeScript generics to efficiently differentiate nested objects within a parsed string

Consider the following type code: const shapes = { circle: { radius: 10 }, square: { area: 50 } } type ShapeType = typeof shapes type ShapeName = keyof ShapeType type ParsedShape<NAME extends ShapeName, PROPS extends Sh ...

Writing Data to Google Cloud Firestore Map using NextJS and Typescript with nested objects

I could use some assistance. I'm developing an application using NextJS (React), TypeScript, and Google Cloud Firestore. Everything seems to be working fine so far. However, I'm facing an issue with storing the address and phone number in a neste ...

next-intl failing to identify the primary language setting

When testing next-intl for the app directory in the Next.js v13.4.0, I encountered an issue where the default locale was not recognized. Despite following the documentation step by step, I also faced significant challenges with the client-side version in p ...

Extracting an array from an HTTP response in Angular/Typescript using the map operator or retrieving a specific element

Q1: How can I extract an array of objects from a http response using map in Angular? Q2: Is there a way to retrieve a specific object from a http response by utilizing map in Angular? Below are the example URL, sample data, CurrencyAPIResponse, and Curre ...

What is the best way to showcase images at random in Angular?

I am trying to display a random array of images in the UI, but I'm encountering an error with innerHTML when using the code below in TypeScript. randomPic(){ this.randomNum= Math.floor(Math.random() * this.myPix.length); console.log(this.rando ...

Guiding you on exporting a Typescript class with parameters in Node.js

Trying to find the Typescript equivalent of require('mytypescriptfile')(optionsObject); This is the TS code provided: export class Animal { name: string; public bark(): string { return "bark " + this.name; } constructor(color:string) ...

Fixing a wrong path in the problem matcher of vscode while compiling using $tsc-watch: A step-by-step

My project workspace directory can be found at C:\salix\fantasy. The TypeScript configuration file is located at C:\salix\fantasy\tsconfig.json Despite my efforts, I'm struggling to have the problem matcher for my project dir ...

Determine the data type of an object's key

I have a XInterface defined as: export interface XInterface { foo: (() => Foo[]) | Foo[], bar: string, baz: number } When declaring an object using this interface, I want the type of foo to be Foo[], like so: const myObj: XInterface = { ...

Invoke a static method from within a class in Typescript (Angular HttpInterceptor)

Recently, I've been working on an http interceptor that was functioning smoothly until just yesterday. It consists of static methods, and for some reason, one of them is now causing issues. Here is the error message displayed in the console: my.c ...

The variable 'BlogPost' has already been declared within the block scope and cannot be redeclared

When working with Typescript and NextJS, I encountered the following Typescript errors in both my api.tsx and blogPost.tsx files: Error: Cannot redeclare block-scoped variable 'BlogPost'.ts(2451) api.tsx(3,7): 'BlogPost' was also dec ...

A guide on resolving deprecated warnings for typographical errors

Every time I try to npm install I am bombarded with numerous errors. typings WARN deprecated 9/9/2016: "registry:dt/node#6.0.0+20160831021119" is deprecated (updated, replaced or removed) My experiences with typescript have been nothing but a series ...

Generate a dynamic interface using properties and options provided in a JavaScript object

Can Typescript support the following scenario: I have a structure where keys represent properties and values are arrays of options for those properties: const options = { foo: [fooOption1, fooOption2, ...], bar: [barOption1, barOption2, ...], ... } ...

Steps for aligning the upper rectangular text in the center of the larger rectangular border

https://i.stack.imgur.com/7yr5V.png I was aware of a particular element in html that had text positioned in the upper left corner, but my knowledge didn't go beyond that. Should I be adjusting the translation on both the X and Y axes based on the par ...

Strange occurrences observed while looping through an enum in TypeScript

Just now, I came across this issue while attempting to loop through an enum. Imagine you have the following: enum Gender { Male = 1, Female = 2 } If you write: for (let gender in Gender) { console.log(gender) } You will notice that it iter ...

Using React to make an API call without utilizing hooks

Hello, I am currently working on developing a webpart using SharePoint and React. However, I am facing some issues with fetching data from a simple API. export default class Testing100 extends React.Component<ITesting100Props, {}> { constructor(p ...

What is the best way to retrieve the output value using the EventEmitter module?

I have an element that sends out a simple string when it is clicked Here is the HTML code for my element: <div (click)="emitSomething($event)"></div> This is the TypeScript code for my element: @Output() someString: EventEmitter<string& ...

What causes the discrepancy in results between these two NodeJS/Typescript imports?

Within my NodeJS project, I have integrated typescript version 3.2 alongside express version 4.16 and @types/express version 4.16. My development is focused on using Typescript with the intention of transpiling it later on. The guidelines for @types/expre ...

Create Joi Schema based on TypeScript types/interfaces

Searching for a way to convert Typescript types or interfaces into joi schema objects led me to various solutions that did the opposite, such as generating Typescript types/interfaces from joi schemas. I came across options like ts-interface-builder and ts ...