Search code examples
node.jspathrequire

In Node, how do I elegantly handle requiring modules that read files in their directories?


For instance, in my project directory, I have:

|--bar.js
|--dir
   |--foo.txt
   |--readfile.js

readfile.js:

const fs = require('fs');

var foo = fs.readFileSync('foo.txt', 'utf8');

console.log(foo);

module.exports = {foo};

Running node readfile.js, everything works perfectly.

bar.js:

const readfile = require('./dir/readfile');

console.log(read.foo);

Running node bar.js, I get:

fs.js:663 return binding.open(pathModule.toNamespacedPath(path), ^

Error: ENOENT: no such file or directory, open 'foo.txt'
    at Object.fs.openSync (fs.js:663:18)
    at Object.fs.readFileSync (fs.js:568:33)
    at Object.<anonymous> (/Users/fterh/Documents/Projects/playground/dir/readfile.js:3:14)
    at Module._compile (module.js:660:30)
    at Object.Module._extensions..js (module.js:671:10)
    at Module.load (module.js:573:32)
    at tryModuleLoad (module.js:513:12)
    at Function.Module._load (module.js:505:3)
    at Module.require (module.js:604:17)
    at require (internal/module.js:11:18)
Fabians-MacBook-Pro:playground fterh$ 

I know it has to do with require('./dir/readfile') in bar.js, because Node then tries to search for "foo.txt" in the same directory as "bar.js". Currently, my fix is to use path.dirname(__filename) to get absolute paths, which would work regardless of whether I'm running the module directory or requiring it. I'm wondering if there is a more elegant way of doing things.


Solution

  • Use of require.resolve within readfile.js as follows:

    const fs = require('fs');
    
    let foo = fs.readFileSync(require.resolve('./foo.txt'), 'utf8');
    
    console.log(foo);
    
    module.exports = {foo};
    

    Note: in the original question for bar.js it may have been intended to write: console.log(readfile.foo);.

    require.resolve:

    ... return the resolved filename