The node.js Relative Path Case
Right now, it sucks because ___, as @izs told me to start with, I could not find a simple way to resolve a path from a module that exported a function into another one.
Spoiler: the reason I am trying to resolve paths is to load fresh modules runtime in polpetta. However, this might be a bad practice.
This case is quite easy to misunderstand so I'll skip extra explanations now and put down some code.
If we would like to use that module method, talking about the
Thankfully, this is easy but be aware of the caching problem:
I am able to resolve relatively from any outer module its path the same way
Still I believe there should be a better way to do this ... what do you say?
Spoiler: the reason I am trying to resolve paths is to load fresh modules runtime in polpetta. However, this might be a bad practice.
@WebReflection Lest I commit malpractice, I must tell you this is a terrible idea. Now warned, rock on with your bad self. Hack away :)Still, my point is that it might be handy to be able to resolve paths relatively form the invoker regardless the why, even if you should always ask yourself that ;)
This case is quite easy to misunderstand so I'll skip extra explanations now and put down some code.
relative.js
This example file aim is to log ASAP two different path resolutions: the one from the path, passing through theprocess.cwd()
, and the one from the relative.js
file itself. Running this from
Object.defineProperties(this, {
parent: {
get: function () {
// used later on
return module.parent;
}
},
resolve: {
value: function (path) {
// it will resolve from this file
// not from the invoker
return require.resolve(path);
}
}
});
// path module resolves relatively
// from the current process.cwd()
console.log(require('path').resolve('.'));
// require resolves relatively from
// the current file
console.log(require.resolve('./relative.js'));
node
terminal will most likely show something like: Neither logs or resolution are actually OK if we would like to resolve relatively from that path.
require('./test/relative.js');
/Users/yourname/code
/Users/yourname/code/test/relative.js
If we would like to use that module method, talking about the
resolve()
one, we cannot trust the current path. If we install that module through
// will throw an error
require('./test/relative.js').resolve('./test/relative.js');
// will pass
require('./test/relative.js').resolve('./relative.js');
npm
as global, or even local in some super folder, gosh knows where we should start the relative path resolution accordingly with the module itself, you know what I mean? Being Relative To The Invoker Path
In order to be able to resolve relatively from the invoker, we need to know at least where is the invoker.Thankfully, this is easy but be aware of the caching problem:
At this point we can invoke the method as expected without having erros, from the process folder.
// relative.js
var
path = require('path'),
relativeDir = path.dirname(
module.parent.filename
)
;
this.resolve = function (module) {
return require.resolve(
path.join(relativeDir, module)
);
};
Good, we are able to resolve module names, problem is ... only from the very first one that required
// will log the right path
require('./test/relative.js').resolve('./test/relative.js');
relative.js
due module caching so that module.parent
will be one, and only one, for any other module. A Hacky Solution
In order to avoid the caching problem within the required module itself, I came up with such trick at the end of the file:In this way every single module that will
// .. same content described above ...
// remove the module itself from the cache
delete require.cache[__filename];
require('./some-path/relative.js')
will have a fresh new version of that module so that module.parent
, and its filename
, will be always the right one: how cool is that?I am able to resolve relatively from any outer module its path the same way
require.resolve(path)
would do inside that module which is exactly needed and the goal of require-updated so that any module can use paths as if these were resolved from the file itself in order to require
some other file, relative, absolute, or globally installed.Still I believe there should be a better way to do this ... what do you say?
Comments
Post a Comment