Fabian
Fabian

Reputation: 407

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.

Upvotes: 0

Views: 229

Answers (2)

jfriend00
jfriend00

Reputation: 707218

Use __dirname to construct your path as that will always point to the directory where your module was loaded from, regardless of the current directory. This is one of the variables that is passed into a module so it has a unique value in the scope of each module and it's purpose is for exactly what you want (to do file operations relative to your module's directory).

const fs = require('fs');
const path = require('path');

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

console.log(foo);

module.exports = {foo};

Reference info for __dirname here.

Upvotes: 0

Manny
Manny

Reputation: 46

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

Upvotes: 1

Related Questions