user2541867
user2541867

Reputation: 444

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?

Upvotes: 0

Views: 7532

Answers (3)

Iglesias Leonardo
Iglesias Leonardo

Reputation: 544

You can use the Clear-Site-Data response header to

send a signal to the client that it should remove all browsing data of certain types (cookies, storage, cache) associated with the requesting website. Mdn Web Docs

In express, just set the headers with the method res.set(field [, value]). For example, to tell the browser to clear cache, use res.set('Clear-Site-Data', 'cache').

Just remember that Clear-Site-Data isn't widely available yet according to Mdn Web Docs. The only other way you can refresh cache is to clear on client side with window.location.reload(true).

Upvotes: 0

xdeepakv
xdeepakv

Reputation: 8125

You don't need to write your one util. You can use module like chokidar for so. You can specify directory and ignore the same time.

You can reload on callback the watch.

Sample from there wiki:: https://github.com/paulmillr/chokidar

const chokidar = require("chokidar");

// Full list of options. See below for descriptions.
// Do not use this example!
chokidar.watch("file", {
  persistent: true,

  ignored: "*.txt",
  ignoreInitial: false,
  followSymlinks: true,
  cwd: ".",
  disableGlobbing: false,
  awaitWriteFinish: {
    stabilityThreshold: 2000,
    pollInterval: 100,
  },

  ignorePermissionErrors: false,
  atomic: true, // or a custom 'atomicity delay', in milliseconds (default 100)
});
// One-liner for current directory
chokidar.watch(".").on("all", (event, path) => {
  // Reload module here.
});

Upvotes: 0

user2541867
user2541867

Reputation: 444

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)

Upvotes: 0

Related Questions