lukeocodes / express-nodemon-ngrok-starter
Express Nodemon and Ngrok - The Ultimate `npm run dev`
The Ultimate npm run dev
This is a starter app for Express.js.
The src/devApp.js
runs your src/app.js
using Nodemon as a module, starting Ngrok when the app is run, gracefully stopping Ngrok when the app is closed.
How Can I Use This?
src/app.js
is just a standard hello-world/app.js from the Express.js site. You probably just need to start as you normally would, editing src/app.js
as you build your app.
Clone this repository.
git clone https://github.com/lukeocodes/express-nodemon-ngrok-starter.git
Install the dependencies.
npm install
Production Mode
Nodemon, Ngrok and Dotenv are all devDependencies
and only required inside src/devApp.js
, so in production mode none of these libraries which are great for development are installed or required by the app.
Start the app without these modules.
npm start
Development Mode
Start development mode with the Nodemon, Ngrok, and Dotenv modules.
npm run dev
What Else?
You could use Livereload toβ¦
Express.js
Start with the Express Hello World, by running these commands from an empty directory. First, initialise NPM.
npm init -y
Now, install Express.
npm install express
Add this code to an app.js
file.
// 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.
node app.js
Or, if you like, add a script to your package.json
.
"scripts": {
+ "start": "node app.js"
},
To run it like so:
npm start
And, we're done! (Just kidding).
Ngrok
Now, you want to launch Ngrok so you can share your Hello World with THE world.
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 for that. Install it as a devDependency
.
npm install nodemon --save-dev
A quick update to your package.json
file and you can run your app with Nodemon.
"scripts": {
+ "dev": "nodemon app.js",
"start": "node app.js"
},
Now, you can run it with Nodemon like this:
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, to run it as a module.
// 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
.
npm install ngrok --save-dev
Now, modify the devApp.js
file and add this code.
// 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!
"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!)
Top comments (4)
I would add livereload to all that :)
Ohhh I was building an API at the time so I hadn't considered this. Great idea!
What abou use a package like npm-run-all
npmjs.com/package/npm-run-all
I personally use concurrently, but all are great. Either
npm-run-all
or concurrently run their processes side-by-side but AFAIK decoupled.I wanted this to gracefully terminate the Ngrok session when closing node. In concurrently you can use
--kill-others-on-fail
but that doesn't feel very graceful :)