The Ultimate `npm run dev`
Tags: showdev, node, javascript, opensource
Published: 2020-04-23 10:54:17

---
title: The Ultimate `npm run dev`
published: true
description: Automatically reloading node application accessible with a public URL. The ultimate npm run dev.
tags: showdev, node, javascript, opensource
cover_image: https://dev-to-uploads.s3.amazonaws.com/i/376kbej3kxp4ll9w6v7f.png
---

{% github lukeocodes/express-nodemon-ngrok-starter %}

## Express.js

Start with the Express Hello World, by running these commands from an empty directory. First, initialise NPM.

```shell
npm init -y
```

Now, install Express.

```shell
npm install express
```

Add this code to an `app.js` file.

```js
// app.js
const express = require('express')
const app = express()
const port = process.env.PORT || 3000

app.get('/', (req, res) => res.send('Hello World!'))

app.listen(port, () => console.log(`Example app listening at http://localhost:${port}`))
```

Start it and check it out at [localhost:3000](http://localhost:3000).

```shell
node app.js
```

Or, if you like, add a script to your `package.json`.

```diff
    "scripts": {
+     "start": "node app.js"
    },
```

To run it like so:

```shell
npm start
```

And, we're done! (Just kidding).

## Ngrok

Now, you want to launch [Ngrok](https://ngrok.com/) so you can share your Hello World with THE world.

```shell
npm install ngrok -g
ngrok http 3000
```

Start it and check it out at **https://your-ngrok-hash.ngrok.io**.

Awesome! (this isn't it, bare with me until the end).

## Nodemon

Now, if you've ever worked on a React.js or Vue.js project and gone back to a normal Node.js project without Webpack, you've probably wanted to be able to reboot your app automatically whenever you make changes.

For which, you've probably stumbled on [Nodemon](https://www.npmjs.com/package/nodemon) for that. Install it as a `devDependency`.

```shell
npm install nodemon --save-dev
```

A quick update to your `package.json` file and you can run your app with Nodemon.

```diff
    "scripts": {
+     "dev": "nodemon app.js",
      "start": "node app.js"
    },
```

Now, you can run it with Nodemon like this:

```shell
npm run dev
```

## BUT, WHAT IF?

But, what if you can pop all these into your app itself? Yeh, you read that correctly! :exploding_head_emoji:

Firstly, create a `devApp.js` file.

Inside that file, add [this example code from Nodemon](https://github.com/remy/nodemon/blob/HEAD/doc/requireable.md), to run it as a module.

```js
// devApp.js
const nodemon = require('nodemon')

nodemon({
  script: 'app.js',
  ext: 'js'
})

nodemon.on('start', async () => {
  console.log('app.js just started')
}).on('quit', async () => {
  console.log('killing app.js')
})
```

Nextly, install Ngrok as a `devDependency`.

```shell
npm install ngrok --save-dev
```

Now, modify the `devApp.js` file and add this code.

```diff
  // devApp.js
  const nodemon = require('nodemon')
+ const ngrok = require('ngrok')
+ const port = process.env.PORT || 3000

  nodemon({
    script: 'app.js',
    ext: 'js'
  })

+ let url = null

  nodemon.on('start', async () => {
-   console.log('app.js just started')
+   if (!url) {
+     url = await ngrok.connect({ port: port })
+     console.log(`Server now available at ${url}`)
+   }
  }).on('quit', async () => {
-   console.log('killing app.js')
+   await ngrok.kill()
  })
```

Lastly, change your `package.json` up a little bit!

```diff
    "scripts": {
-     "dev": "nodemon app.js",
+     "dev": "node devApp.js",
      "start": "node app.js"
    },
```

Now, when you start your server, your local URL and public URL are now output in the console and when you update your code, the node app is refreshed (but you keep your ngrok URL!)

![Local URL and Remote URL output when the app starts and nodemon refreshes code automatically when it is changed](https://dev-to-uploads.s3.amazonaws.com/i/xwjifyjg68kqfukfmrpg.png)