admin管理员组文章数量:1221310
recently i found out a strange problem regarding the node.js require mechanism
you might think, due to windows file system it doesn't matter if required modules are case sensitive or not. So ...
Module A:
require("fancyModule");
Module B:
require("fancymodule");
are both leading to to the same fancymodule.js file. but the constructor of that object will be called twice. so
var FancyModule = {
var name = "unkown";
var setName = function(val){
name = val
}
return {
setName:setName
}
}
module.exports = FancyModule();
will result into two separate FancyModule instances. so be aware of it.
I know that i always have to care about the right file name - no matter if the file system is case sensitive or not.
my question is, is there any way to setup or configure nodejs to prevent that - or at least print out a warning ?
recently i found out a strange problem regarding the node.js require mechanism
you might think, due to windows file system it doesn't matter if required modules are case sensitive or not. So ...
Module A:
require("fancyModule");
Module B:
require("fancymodule");
are both leading to to the same fancymodule.js file. but the constructor of that object will be called twice. so
var FancyModule = {
var name = "unkown";
var setName = function(val){
name = val
}
return {
setName:setName
}
}
module.exports = FancyModule();
will result into two separate FancyModule instances. so be aware of it.
I know that i always have to care about the right file name - no matter if the file system is case sensitive or not.
my question is, is there any way to setup or configure nodejs to prevent that - or at least print out a warning ?
Share Improve this question edited Apr 25, 2014 at 9:57 Daniel E. asked Apr 25, 2014 at 9:21 Daniel E.Daniel E. 2061 gold badge2 silver badges7 bronze badges 2 |3 Answers
Reset to default 14First of all, never make assumptions about the filesystem you are using. Always expect it to be case sensitive, in case you run it in a different environment.
Now to your problem:
When you require a module in node, node will cache the import exactly to prevent the case where you want to export a singleton and not have it initialized twice. While the filesystem lookup will return the same exact file because it's case insensitive, require's cache still treats the two cases as different modules. That's because it has to assume that it runs in a case sensitive environment, so there could actually be two different modules behind that.
That's why it initializes your singleton twice. It actually treats them as two different modules.
You were asking if there's any way to prevent it.
There is a very easy but horrible way to do it. You can patch global.require
to lowercase your imports:
var patchRequire = function () {
var oldRequire = global.require;
global.require = function (moduleName) {
return oldRequire.call(global, moduleName.toLowerCase());
};
};
patchRequire();
require('Foo-Bar'); // Will require 'foo-bar' instead
But please don't do that. Better make sure to keep your imports consistent and use all lower case names separated by dashes.
This function check for case sensitivity
const path = require('path');
const fs = require('fs');
const safeRequire = function (requiredPath) {
const splitted = requiredPath.split('/');
const upup = splitted.filter((e) => e == '..').join('/');
let upMost = path.resolve(upup);
let down = splitted.filter((e) => e !== '..' && e !== '.');
if (requiredPath.startsWith('./')) {
upMost = __dirname;
}
for (let each of down) {
const dir = fs.readdirSync(upMost);
if (!dir.includes(each) && !dir.includes(`${each}.js`)) {
throw 'Module Not Found (check casing)';
}
upMost = path.join(upMost, each);
}
return originalRequire.apply(this, [requiredPath]);
};
I agree with @Tim that all paths and file names should follow the consistent conventions which ensure the correct case is always used. But sometimes it may be onerous to enforce throughout code, or it may happen that the code with the problem is not under your control. For example, I have encountered this problem where parts of paths to modules may be indirectly supplied as parameters.
So, I have used a work-around which, while a kludge, has the practical advantages of a) avoiding the problem of loading two instances of the same module, b) giving you warning that the situation exists and thereby prompting you to do something about it and c) not modifying the require() function or using your own wrapper for require().
The kludge is to add code into the module itself, so that it will check to see if it has previously been loaded and, if so, issue a warning and return that original instance instead of a new one:
"use strict";
if(!global.MYMODULES) global.MYMODULES= {};
// Check if thisModule has already been loaded
if(global.MYMODULES.thisModule){
// issue a warning and use the original module
console.log("*****\n* WARNING: [thisModule.js] is being required from somewhere using module path or module name with the wrong case - INVESTIGATE!!!\n*****");
module.exports = global.MYMODULES.thisModule;
} else {
// **************************
// The whole code of the thisModule goes here
// **************************
// Save reference to this original module instance
global.MYMODULES.thisModule = module.exports;
};
本文标签: javascriptnodejs requiremodule name case sensitive issueStack Overflow
版权声明:本文标题:javascript - nodejs require - module name case sensitive issue - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1739295013a2156864.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
require()
-ing it twice in the first place? – Scimonster Commented Apr 25, 2014 at 9:25