112

I'm looking for a way to use npm scripts to run tsc --watch && nodemon --watch at the same time. I can run these commands independently, but when I want run both of them, only the first one is executed. eg:

"scripts": {    
    "runDeb": "set NODE_ENV=development&& tsc --watch && nodemon --watch"
  }

tsc --watch is executed but nodemon is never called, and vice versa.

Nicolas Dominguez
  • 1,243
  • 2
  • 10
  • 10

11 Answers11

179

I think what you want is something like this (my current setup):

"scripts": {
    "compile": "tsc && node app.js",
    "dev": "./node_modules/nodemon/bin/nodemon.js -e ts  --exec \"npm run compile\""
}

I created two scripts "compile" and "dev". To start developing you simply run npm run dev which starts nodemon and makes it watch .ts files (using the -e flag). Then, every time a .ts file changes nodemon will exec the compile task which basically compiles and runs the node app.

While using concurrently is a good option, my setup guarantees that tsc's work is done before attempting to execute the resulting .js files.

AlterX
  • 2,131
  • 2
  • 14
  • 9
  • Make sure to set `"watch": false` in your `tsconfig.json` file. Otherwise `node app.js` will never run. – Matt Nov 21 '16 at 22:14
  • 1
    Yeah but tsc won't watch the files unless you tell it to do so by using either `-w`/`--watch` or, as you mentioned `"watch": true` in the `tsconfig.json` so it should be just fine to use this technique – AlterX Nov 25 '16 at 01:36
  • any way to make this work with express 4? I keep getting a "[nodemon] clean exit" after it runs. – APalmer Apr 26 '17 at 22:33
  • Hmm, Express version should have anything to do with this. This will just run whatever's in the app.js file. I've used this technique with Express 4 and Koa. Do you have your code available somewhere? – AlterX May 03 '17 at 21:07
  • 11
    `tsc -w` uses incremental compilation and cache for already parsed files so it must be faster to compile, this is why I prefer concurrently run `tsc -w` with nodemon – Andzej Maciusovic May 10 '17 at 17:28
  • 5
    If you use concurrently, it concurrently runs both tasks, the problem with that, as stated in the other response, is that nodemon starts before tsc is done compiling so it doesn't serve the latest changes. See Nicolas Dominguez's comment. – AlterX May 10 '17 at 18:38
  • 3
    Great trick! Thanks @AlterX. To all readers, if your TypeScript files are in a subfolder (such as "src"), then you need to run the following: `nodemon --watch src/ --exec \"npm run compile\" --verbose -e ts`. – Benny Code Feb 03 '18 at 22:44
  • This setup worked for me! Also didn't have https://stackoverflow.com/a/38695935/1942263 issue of nodemon starting before tsc finished building. – Alexander May 02 '18 at 15:18
  • 1
    Better: `"start": "nodemon -w src --exec 'npm run compile'"` 1. Path to `nodemon` is not necessary. 2. I had to add a path to watch (`-w src`), otherwise it perpetually rebuilds, because te target (here `dist`) is watched too. Just add `nodemon` to `devDependencies` first: `npm i -D nodemon` – Marc Wäckerlin Jul 07 '21 at 08:31
  • You can also concatenate these if you like `"dev": "./node_modules/nodemon/bin/nodemon.js -e ts --exec \"tsc && node app.js\""` – s4l4x Nov 10 '21 at 23:11
  • 1
    1. [Path to nodemon isn't necessary](https://stackoverflow.com/questions/38276862/is-there-a-way-to-use-npm-scripts-to-run-tsc-watch-nodemon-watch#comment120679408_40093215) 2. [You can concatenate commands](https://stackoverflow.com/questions/38276862/is-there-a-way-to-use-npm-scripts-to-run-tsc-watch-nodemon-watch#comment123600169_40093215) 3. Why not use `tsc --incremental` for better speed? Combined this looks like: `"dev": "nodemon -e ts --watch src --exec \"tsc --incremental && node app.js\"",` – bmaupin Feb 01 '22 at 13:52
  • This is probably the simplest answer when you don't wanna use any external packages. – Farzad Soltani Apr 04 '22 at 07:06
  • That made it for me, thanks. You may also want to add `exit 1` flag like so: `node dist/index.js || exit 1` - this will keep nodemon alive on compilation errors – DamianoPantani Sep 17 '22 at 08:55
141

I have been using AlterX's solution for a while now and it has worked perfectly, but I have found it to be rather slow. Instead, I am now using tsc-watch. It makes tsc use incremental compilation similar to the -w flag, making the restart of the application much faster.

It's as easy as putting something similar to this in your package.json:

"scripts": {
  "start": "tsc-watch --onSuccess \"node .\""
}
abernier
  • 27,030
  • 20
  • 83
  • 114
Borre Mosch
  • 4,404
  • 2
  • 19
  • 28
  • 3
    This is a great solution! I was able to chain multiple commands in the callback like this: `--onSuccess "sh -c 'babel && uglifyjs'"` – Adam Mazzarella Jan 02 '18 at 22:13
  • After I installed tsc-watch, when I run the script I get this error: "sh: tsc-watch: command not found". – overcomer Nov 09 '18 at 11:34
  • Are you sure you have installed tsc-watch into your project? You could try using `./node_modules/.bin/tsc-watch` instead of `tsc-watch` – Borre Mosch Nov 09 '18 at 11:44
  • @Borre, Really strange: I repeat the installation and now is correctly installed. But it needs tsc installed locally. After doing that, it works fine. – overcomer Nov 09 '18 at 11:54
  • 3
    Better than the accepted answer (if speed is important) – jugglingcats Jun 28 '19 at 12:02
  • This post just put an end to my 3,5 day hunt to fixing my gulp-typescript and gulp-sourcemap pipeline. If only I had found this earlier... For the next reader: the vscode debugger can be attached to this if you execute `node --inspect .`, and add a simple task to attach. Another note, it could be handy to install `notify-send` on your machine with `apt`, and use that to send system notifications on the `--onFailure` event. – MagicLegend Mar 19 '20 at 14:55
  • 11
    Best answer, P.S. you don't need to specify the module path in an npm script this works fine - `"tsc-watch --onSuccess \"node dist/index.js\""` – Dominic Jun 22 '20 at 10:50
  • in case someone's looking how to run another npm script: `"watch": "tsc-watch --onFirstSuccess \"npm run inspect\"",` – GorvGoyl May 20 '21 at 23:19
  • `tsc-watch` is greeat! But running node [caused errors](https://stackoverflow.com/questions/46977296/cannot-read-property-on-of-undefined-in-electron-javascript/53962520) here. Better use: `"watch": "tsc-watch --onSuccess \"electron .\""` – udondan Sep 26 '21 at 15:15
  • FYI ts-watch also supports using different compilers - like ttsc: `tsc-watch --compiler ttypescript/bin/tsc --onSuccess 'npm start'` – Shl Jan 11 '22 at 13:20
  • Thanks for this solution. I've been figuring out how to watch ts file changes but wanted to run the distributed file as the entry point so it's same as prod. Amazing! – Woppi Oct 19 '22 at 04:57
  • 1
    We've found that `tsc-watch` has a lot of issues, including restarting too many times and not properly killing running processes. So I can't recommend `tsc-watch`. – dimiguel Dec 08 '22 at 17:43
  • tsc-watch no longer works when you are running in a container and editing source files on the host mounted via a volume. This used to work, but no longer. – java-addict301 Jan 04 '23 at 21:32
  • Jumping into 2023 with this and `ts-watch` v6.0.0 works like a charm, no issues so far. – vitaly-t Apr 27 '23 at 16:13
  • @vitaly-t you mean "tsc-watch", right? – Winand Aug 20 '23 at 18:55
33

Try to add this to your package.json:

"scripts": {
  "start": "concurrently --kill-others \"tsc -w\" \"nodemon dist/app.js\"",
}

And also add this npm packages (concurrently, nodemon, typescript) to your package.json:

"devDependencies": {
  "concurrently": "^2.2.0",
  "typescript": "^1.8.10",
  "nodemon": "^1.9.2",
}
arman1991
  • 1,166
  • 1
  • 18
  • 28
Alexander
  • 357
  • 3
  • 3
  • 10
    The only problem is that `nodemon` starts before typescript finish its work, one hack solution maybe set a delay to nodemon like `nodemon --delay x` its gives some moments to `tsc`. – Nicolas Dominguez Aug 13 '16 at 21:51
  • @NicolasDominguez, see my response for a way that guarantees tsc's changes are done before executing the app. – AlterX Nov 29 '16 at 18:16
  • @AlterX Yeah but isn't `tsc --watch` more efficient? – Alex Booker May 27 '17 at 21:02
  • @AlexBooker it probably is but it doesn't work for this specific use case as we can't guarantee that `tsc` is done before running. In practice this means that you cannot guarantee the latest changes are included in the code `nodemon` is running which is the whole point of watching the changes in the first place. To be clear, if you use concurrently both tasks will run *concurrently* which means that you'll run both `tsc` and `nodemon` at the same time and since `tsc` takes some time to compile, chances are `nodemon` won't pick the latest changes since it will start before `tsc` finishes. – AlterX May 29 '17 at 16:05
  • 11
    @AlterX My solution is to use [`tsc-watch`](https://www.npmjs.com/package/tsc-watch): `tsc-watch --onSuccess \"node ./bin\"`. What do you think? – Alex Booker May 30 '17 at 09:05
  • Yeah, it seems to solve our main issue here: kicking up a new process after the compilation is done. It was published a couple of months ago so idk about stability but it looks like another good solution for the issue. – AlterX May 30 '17 at 21:41
  • @AlexBooker care to post that as an answer? `tsc-watch` worked for me nicely. – Arjan Jul 17 '17 at 12:26
  • 1
    tsc-watch works great; in my package.json `dev` script: `"tsc-watch --onSuccess \"nodemon\""` – Leo Nov 29 '18 at 13:51
22

What's going on

The problem is there are two watchers here on all the files. One is tsc -w and one is nodemon.

When a change to a .ts file is made, tsc detects that, compiles it, and creates the .js version in your destination folder.

Now from the Nodemon's perspective, it detects two changes (at least) -- one for .ts and one for .js. On the first change it restarts itself, but on the second change it doesn't know that another "start" is going on already, so it tries to restart again and it fails. To me it's a nodemon bug -- see https://github.com/remy/nodemon/issues/763.

Solutions

1) Use tsc-watch --onSuccess

tsc-watch has --onSuccess which you can put node on there. This way you will have only one watcher.

2) Delay nodemon

You can easily delay nodemon restarts (See --delay). It requires the least set up change.

3) Have nodemon only monitor destination folder of TSC

I couldn't get it to set up, but this way nodemon will detect only one change hopefully. It might cause problems in future or when tsc generates multiple files.

Community
  • 1
  • 1
Aidin
  • 25,146
  • 8
  • 76
  • 67
  • 2
    Thanks, used tsc-watch and works perfectly, just added `"start": "node_modules/.bin/tsc-watch --onSuccess 'node ./src/app.js'"` to `package.json` and now works fine with `npm start` :) – Blingers Apr 28 '20 at 07:35
  • 1
    `tsc-watch` works very well for my use-case. – Matthew Feb 02 '22 at 13:43
10

My solution in october 2018 using newest versions of nodemon.

first:
install nodemon(npm install nodemon --save-dev) and ts-node(npm install ts-node --save-dev)

second:
create a nodemon.json . I like to keep my nodemon config in a seperat nodemon.json to make the npm scripts a tad easier to read. So create nodemon.json in the root of the project with the following content:

{
    "ignore": ["**/*.test.ts", "**/*.spec.ts", ".git", "node_modules"],
    "watch": ["src"], // your .ts src folder
    "exec": "npm start", // your npm script created in package.json
    "ext": "ts"
}

then create your npm start script e.g like this:

"scripts": {
    ...
    "start": "ts-node src/server.ts",
    "dev:ts": "nodemon",
    ...
  }

Then run npm run dev:ts or yarn dev:ts should run and watch your typescript server code.

For more configs like Jest units tests etc... you can take a look into this article

billyjov
  • 2,778
  • 19
  • 35
  • What if the `nodemon.json` is not in the same directory as `package.json`? – CodyBugstein Oct 08 '18 at 03:51
  • 1
    Also there are some serious issues with using nodemon and ts-node together. See https://github.com/remy/nodemon/issues/1025 – CodyBugstein Oct 08 '18 at 03:54
  • yeah, you are right. But the most issues are Unix and OSX related operating systems. I never had the issue using vscode and powershell/git bash under windows. I will check this on other systems. – billyjov Oct 08 '18 at 05:38
  • To your first question. You can also use `nodemon` config in your `package.json` using the `nodemonConfig` key. here is a workflow for this https://alligator.io/workflow/nodemon/ – billyjov Oct 08 '18 at 05:44
7

The TypeScript-Node-Starter is fast

https://github.com/microsoft/TypeScript-Node-Starter/blob/master/package.json

"dev": "concurrently -k -n \"TypeScript,Node\" -c \"yellow.bold,cyan.bold\" \"npm run watch-ts\" \"nodemon ./dist/app.js\"",
"watch-ts": "tsc -w"

Here we are giving npm run watch-ts the TypeScript name (by using concurrently -n) and adding the color yellow.bold by using the concurrently -c.

So, I can recognize pretty easy the messages for each process.

Coyolero
  • 2,353
  • 4
  • 25
  • 34
4

Simple way to have nodemon watching the .ts files

Add this script to your package.json


  "scripts": {
      "start": "nodemon --exec ts-node-esm ./src/*.ts",
  },

Install ts-node to your devDependencies with npm i ts-node -D

Then you could run npm run start or with yarn start

enter image description here

here is a medium article in regards https://medium.com/@jonathans199/how-to-create-a-simple-node-api-with-typescript-4ab631b43503

Jonathan Sanchez
  • 7,316
  • 1
  • 24
  • 20
3

Here is another way, use sleep in your concurrently command before starting nodemon.

eg,

"scripts": {
    "dev": "concurrently -k \"tsc -p ./src/server -w\" \"tsc -p ./src/client -w\" \"sleep 5 && nodemon ./dist/server/server.js\"",
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "node ./dist/server/server.js"
  },

In my situation, I generate both client and server typescript projects at the same time, which causes nodemon to actually start 3 times when I execute npm run dev. But if I sleep 5 seconds before starting the nodemon process, then both tsc processes have already finished, and then continue watching.

You could also use the delay option of nodemon, but I only need it to delay the first time when I execute npm run dev. After that, every individual recompilation of which ever file in whichever project, correctly restarts nodemon only once.

caveat, If your server is slow, you may need to increase the sleep delay longer than 5.

Also, I did try the accepted answer, but my solution was faster for subsequent recompilations while nodemon and the tsc watch processes continued to run.

1 second for my solution, versus 5 seconds for the accepted. I couldn't get the accepted answer to actually run tsc in watch mode, so that's why it was slower, since both TypeScript projects were getting a full recompile on every change.

Sean Bradley
  • 3,254
  • 1
  • 17
  • 10
1

TL;DR; Have nodemon watch for changes in tsc's output (i.e. .js files)

You want nodemon set up to monitor when tsc --watch is finished, as some have alluded to in other comments, so just ask it to watch the destination directory of tsc for changes in .js files.

For example, in package.json:

"scripts": {
  ...
  "watch": "tsc --build src/tsconfig.json --watch",
  "watch-tests": "nodemon --watch dist -e js --exec \"yarn run tests\"",
  "tests": "some script to run my tests",
  ...
}

and in src/tsconfig.json:

{
...
  "compilerOptions": {
    "outDir": "../dist",
    ...
  },
...
}

Where

  • --watch <folder> will point to the same place that you have defined in your compilerOptions->outDir from your tsconfig.json file,
  • -e js will only watch for changes in javascript files, and
  • --exec <some arbitrary thing to run> let's nodemon run more than just node.js scripts.

If the thing you want to have nodemon run is a node script, it can be further simplified to just nodemon --watch dist -e js my-node-script.js

Note: If you find nodemon kicking off it's script too soon, you can increase the throttle delay for checking for changes with --delay

Brad P.
  • 298
  • 3
  • 11
1

You can directly run .ts files with ts-node. Just install it globally and nodemon will use ts-node automatically.

M. Emre Yalçın
  • 608
  • 1
  • 7
  • 10
-5

Normal compilation is: if file name is main.ts

step 1: tsc main.ts

step 2: node main.js

Simple and Onetime(loop) compilation:

tsc main --watch