Just me on Taquile Island, near Puno in Peru https://goo.gl/maps/AYULxpQh4w52

Don’t use nodemon, there are better ways!

I have used nodemon a lot, it was my solution for a long time to not manually restart my node.js project. Then webpack appeared and along with that webpack-dev-server which automatically reloads the page when a change happens. That works perfectly when you are developing a pure client-side app.

Along comes isomorphic, no sorry, universal app

The smart things really start when you can share things between frontend and backend, but here it is that is starts failing, because when I then edited a file shared by both environments, both apps would restart at the same time, but sometimes the node.js server would be down for just enough time that the reload in the browser would not be able to connect and then show a 404.

Solution: don’t restart the server

Okay, we know the solution is to not restart simply because then the server can not be down, but we still want to reload the server somehow.

We have our express.js server in server.js:

var express = require('express')
var app = express()
app.get('/', indexRoute)
app.listen(9000)

We can see that we have our app loading index.js. We need to make some changes, first, we need to move out the routing.

We need to change ./app/index.js from this:

module.exports = function (req, res) {
res.send('Hello Medium.com')
}

to this:

let express = require('express')
let router = express.Router()
router.get('/', function (req, res) {
res.send('Hello Medium.com')
})

What we did was to create a express router, because that can be used in our server like this instead.

server.js

var express = require('express')
var app = express()
var indexRoute = require('./app/index')
app.use(function (req, res, next) {
require('./app/index')(req, res, next)
})
app.listen(9000)

Now we are using the express.js router in our main server, and I know it is a bad habit to not have require at the top, but we will get to it!

File watching

We need to watch the files and know we only need to watch the app/ folder because server.js should not have anything that is changing often.

var chokidar = require('chokidar')
var watcher = chokidar.watch('./app')
watcher.on('ready', function() {
watcher.on('all', function() {
console.log("Clearing /app/ module cache from server")
Object.keys(require.cache).forEach(function(id) {
if (/[\/\\]app[\/\\]/.test(id)) delete require.cache[id]
})
})
})

chokidar is an excellent and simple file watcher and every time it detects a change, we simply go through was node.js require and delete it’s cache. What that means is that next time the server loads, it will not load it from the cache, but read the file again.
In our case, if we had changed app/index.js it would be reloaded.

Boom, done!

That was it, now you have a server that reloads, but never goes down so you will not experience a 404 now in your universal app.

How the final server.js would look:

var express = require('express')
var app = express()
var chokidar = require('chokidar')
var watcher = chokidar.watch('./app')
watcher.on('ready', function() {
watcher.on('all', function() {
console.log("Clearing /dist/ module cache from server")
Object.keys(require.cache).forEach(function(id) {
if (/[\/\\]app[\/\\]/.test(id)) delete require.cache[id]
})
})
})
app.use(function (req, res, next) {
require('./app/index')(req, res, next)
})
app.listen(9000)

“But I don’t want a file watcher in production?”

You don’t have to, you simply put an if statement around chokidar and only loads it in production, then everything works like normal.

var production = process.env.NODE_ENV === 'production'
if(!production) {
var chokidar = require('chokidar')
var watcher = chokidar.watch('./dist')
  watcher.on('ready', function() {
watcher.on('all', function() {
console.log("Clearing /dist/ module cache from server")
Object.keys(require.cache).forEach(function(id) {
if (/[\/\\]dist[\/\\]/.test(id)) delete require.cache[id]
})
})
})
}

“Could I use this for zero-downtime deploy?”

Yeah, but I don’t recommend it ;) Node.js is not good at SSL/TLS termination either, but look the awesome Caddy Server todo that https://caddyserver.com.


Did you like the article or do you have a better way to reload?

Please tell me, I love to learn better ways to program.

P.S. don’t hate on me for not using ES6 ;) This is a tutorial

Shoutout to Glenjamin that showed me this perfect hack! Also, check out his awesome Ultimate Hot Reloading app https://github.com/glenjamin/ultimate-hot-reloading-example/