2

I prefer to import dependencies without lots of relative filesystem navigation like ../../../foo/bar.

In the front-end I have traditionally used RequireJS to configure a default base path which enables "absolute" pathing e.g. myapp/foo/bar.

How can I achieve this in Node.js?

4
  • Wouldn't it work create your own wrapper to require in the index file? Commented Jul 13, 2017 at 9:25
  • Yeah that could work - good idea! But I wonder if there is something built-in (a configuration option, for example). Commented Jul 13, 2017 at 9:26
  • As far as I know - no. I have never seen it anywhere. Commented Jul 13, 2017 at 9:27
  • 1
    I have found this - there are multiple solutions, unfortunately none of them are "build-in". gist.github.com/branneman/8048520 Commented Jul 13, 2017 at 9:30

2 Answers 2

1

What you can do is use require.main.require which would always be the module path of the starting file. See https://nodejs.org/api/modules.html#modules_accessing_the_main_module

This means, that when you run

const x = require.main.require('some/file/path/y')

It would require it based on the base path of your starting file (that was invoked , node app.js meaning the app.js file).

Other options include using process.cwd() to get the starting path of your app, but that would be depending on where you invoke your node process, not the location of the file. Meaning, node app.js would be different than of you would start it one level up, node src/app.js.

Sign up to request clarification or add additional context in comments.

6 Comments

Thank you. I have found relative pathing to be error-prone and tough to maintain on the front-end (I find it difficult to parse lots of ../. How do you avoid this kind of problem on the backend? Or is this a non-issue for you?
Never really had a problem with it, to be honest. Unless you move around files, the relative paths are static in node.js, since they are always relative to the file invoking the require. Not sure how requireJS load files in web context, but a script tag is always relative to the current HTML document, so if you are injecting a script tag to load a js file, it will not be relative to the js file doing the injection. Maybe that is where your problem stems from?
I have had use cases for the require.main.require though, but that was actually from a node-module that wanted to look for a configuration from the app root folder, which is a very specific use case (and probably discouraged most of the time).
In the initial stages of application development I find it quite a common requirement to move files. If a file brings in shared dependencies like ../../../shared/utils/foo then every file breaks if the nesting position changes. If the paths are instead "absolute" then this problem does not occur. I guess this is the use case I am thinking of...
@BenAston yeah, sure but any half decent IDE usually fixes that as part of refactoring move, so personally I never have issues with that.
|
1

Just to add to the other answer, you can put this few lines in your main file:

(function (module) {
  let path = require('path')
  let __require = module.constructor.prototype.require
  let __cpath = __dirname

  module.constructor.prototype.require = function (str) {
    if (str.startsWith('package:')) {
      let package = str.substr(8)
      let p = path.resolve(__dirname, package)

      return __require(p)
    } else {
      return __require(str)
    }
  }
})(module)

It extends your require in such way:

  • if path begins with package: (i.e. package:src/foo/bar) it translates it to require('/absolute/path/to/your/app/src/foo/bar'),
  • if it doesn't start with package: then it behaves like a normal require would.

1 Comment

after your snippet, i got this error: Error: Cannot find module 'express'

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.