qntm
qntm

Reputation: 4407

How to invalidate cached require.resolve() results

Note: this is NOT the same question as node.js require() cache - possible to invalidate?.

I'm writing a script which modifies the main entry point in the package.json of a Node.js package and I am having difficulty testing its behaviour.

Here's the example package whose main entry point I'm trying to modify. It consists of three files.

./node_modules/example/package.json:

{
  "name": "example",
  "version": "1.0.0",
  "main": "a.js"
}

./node_modules/example/a.js:

module.exports = { letter: 'A' }

./node_modules/example/b.js:

module.exports = { letter: 'B' }

As you can see, this package loads a.js right now, but my script will change it to load b.js instead.

Here's my script:

const fs = require('fs')

// Here is what we get at first
const first = require('example')
console.log(first) // { letter: 'A' }

// Now rewrite the package.json
const p = JSON.parse(fs.readFileSync('./node_modules/example/package.json', 'utf8'))
console.log(p.main) // 'a.js'
p.main = 'b.js'
fs.writeFileSync('./node_modules/example/package.json', JSON.stringify(p, null, 2))

// Require the module a second time
// We get the same object a second time, because of well-documented caching behaviour
// <https://nodejs.org/api/modules.html#modules_caching>
const second = require('example')
console.log(second === first) // true
console.log(second) // { letter: 'A' }

// Clear the cache, as documented
// <https://nodejs.org/api/modules.html#modules_require_cache>
// <https://stackoverflow.com/questions/9210542/node-js-require-cache-possible-to-invalidate/16060619>
delete require.cache[require.resolve('example')]

// Require the module a third time
// We get a new object... but it's still the old entry point
const third = require('example')
console.log(third === first) // false - a new object
console.log(third) // { letter: 'A' } - STILL THE SAME? should be 'B'

As you can see, after rewriting and saving the new package.json, and clearing the require cache, Node.js is still loading the old module!

Digging a little deeper, I've discovered that the value returned from require.resolve('example') is still ./node_modules/example/a.js, even though it should be ./node_modules/example/b.js now. In other words, it looks as if there is some kind of secondary cache for the results of require.resolve.

My question is this: is there any way for me to access and modify this secondary cache?

Upvotes: 3

Views: 729

Answers (1)

qntm
qntm

Reputation: 4407

Currently it is impossible to do this. The contents of each package.json loaded by Node.js is cached separately in a variable packageJsonCache, which is not externally reachable without the addition of a new feature to Node.js' Modules API.

Upvotes: 3

Related Questions