node.jsexpressrequirereload

Is it possible to clear node.js require cache using express.js?


I wrote node.js small app for myself which was using small js code to clear require cache before handling request:

let clearCache
if (process.env.NODE_ENV === 'development') {
  const {cache} = require
  clearCache = (except) => {
    for (let key in cache)
      if (!except.includes(key) && key.indexOf('/node_modules/') === -1)
        delete cache[key]
  }
} else {
  clearCache = () => {}
}

const { createServer } = require('http')
const persistentPaths = ['/path/to/my/db/file']
createServer((req, res) => {
  clearCache(persistentPaths)
  require('./handleRequest')(req, res)
}).listen(3000, () => {})

I believe this is the most efficient way to working with app in development.

When I change code it applies immediately and this worked fine to me.

Now I would like to work with express.js, and it seems to impossible to use this approach.

Okay, seems like it is self-answering question and I need to use nodemon.

But I really don't want to use tool which will be watch all files and will relaunch whole server. I'm afraid that it would be much slower.

In my example you can see that I reload files except db file, so my app in development connects to database only once and keeps that connection. In case of using nodemon app need to load also all node_modules code, make new connection to db each time when code changed, maybe it will connect each time to postgres and to redis.

Question is: I can't be the one who doing it this way, are there solutions to reload modules for express.js?


Solution

  • Did it! Would be glad if you will share your thoughts on it.

    Because I can google only nodemon and chokidar solutions, maybe I'm doing something wierd, here is my solution:

    server.ts:

    import express from 'express'
    const app = express()
    const port = 3000
    
    app.listen(port, () =>
      console.log(`Example app listening at http://localhost:${port}`)
    )
    
    if (process.env.NODE_ENV === 'development') {
      const {cache} = require
      const persistentFiles: string[] = []
      const clearCache = (except: string[]) => {
        for (let key in cache)
          if (!except.includes(key) && key.indexOf('/node_modules/') === -1)
            delete cache[key]
      }
      app.use((req, res, next) => {
        clearCache(persistentFiles)
        const {router} = require('config/routes')
        router.handle(req, res, next)
      })
    } else {
      const router = require('config/routes')
      app.use(router.handle)
    }
    

    And routes.ts:

    import {Router, Request, Response} from 'express'
    export const router = Router()
    
    router.get('/', function (req: Request, res: Response) {
      res.send('Hello world')
    })
    

    Usage: NODE_ENV=development NODE_PATH=src node src/server.js

    (my IDE compiles ts to js while editing and put it right there, if you are using VS code it might be more complicated, I guess)