Home > Article > Web Front-end > The story between node.js and macOS
This article uses a short story to share with you the story between node.js and macOS. I hope it can help everyone.
George G did a small test on his computer, but the results were quite different than expected.
So let’s first take a look at what is written in this small test:
There are three files in total, and the total code does not exceed 15 lines
<span style="font-size: 14px;">class Parent {}<br><br>module.exports = Parent<br></span>
<span style="font-size: 14px;">//加载时把模块文件名首字母大写了(不正确的)<br/>const Parent = require('./Parent')<br/><br/>class Son extends Parent {}<br/><br/>module.exports = Son<br/></span>
<span style="font-size: 14px;">//加载时把模块名首字母大写(不正确的)<br/>const ParentIncorrect = require('./Parent')<br/>//通过正确的模块文件名加载(正确)<br/>const Parent = require('./parent')<br/><br/>const Son = require('./son')<br/><br/>const ss = new Son()<br/><br/>//测试结果<br/>console.log(ss instanceof Parent) // false<br/>console.log(ss instanceof ParentIncorrect) // true<br/></span>
Classmate George G has the following questions:
##son.js<span style="font-size: 14px;"></span># Both ## and
test.js<span style="font-size: 14px;"></span> have incorrect file name references (case issues). Why is no error reported?
ss instanceof ParentIncorrect === true<span style="font-size: 14px;"></span>? I tolerated not reporting an error, but why did I still think that I was the instance of the module that was loaded with an incorrect name?
But if you don’t know why? Okay then, some of me will say it, and some of you will see it.
In fact, the method of diagnosis (debugging) is similar to that of traditional Chinese medicine. You can choose one or two of the four methods of looking, smelling, asking, and palpating to find the answer. .
Hope
hear
Ask
So what do I want to know? The following two things are more reasonable as the entrance to debugging:
node.js > 8.0<span style="font-size: 14px;"></span>; Command line
node test.js<span style="font-size: 14px;"> </span>
debug<span style="font-size: 14px;"></span> process, I will pretend that I don’t know everything below in advance)
Prepare the running environment
node.js > 9.3.0<span style="font-size: 14px;"></span>, Completed
Run it, it was amazing, no error was reported, and the running result was what George G said.
In order to prove that I am not blind, I tried again
in <span style="font-size: 14px;">test.js</span>
<span style="font-size: 14px;"> </span>require<span style="font-size: 14px;"></span> A file that does not exist at all
require('./nidayede')<span style="font-size: 14px;"></span>, run the code.
Error: Cannot find module './nidayede'<span style="font-size: 14px;"></span>, so I didn’t Crazy. That's a real joy.
Is it related to the operating system? Let's try again on So what is It turns out that the awesome but why? What is the purpose of such an anti-human design? More explanations, come and go So, this is the reason why you don’t report an error ? (blaming But the matter is not over yet I have vaguely heard of it. Is there any cache in Sure enough, is still wrong. You can't really solve the problem by guessing and pretending NaBibi So the idea of pretending to look at the source code of Come, let’s enter the mysterious ##src/node_main.cc => src/node. cc => lib/internal/bootstrap_node.js => lib/module.js lib/ module.js 好像没什么卵用,对不对?她就调用了另一个方法 lib/module.js => _load 似乎到这里差不多了,不过我们再深入看看 lib/module.js => tryModuleLoad 接下来就是真正的 好了,分析问题的关键在于不忘初心,虽然到目前为止我们前进的比较顺利,也很爽对不对?。但我们的此行的目的并不是爽,好像是有个什么疑惑哦!于是,我们再次梳理下问题: 既然没报错的问题前面已经解决了,那么,现在看起来就是加载模块这个部分可能出问题了,那么问题到底是什么?我们怎么验证呢? 这个时候我看到了这么一句话 真相已经呼之欲出了, 如果我们改改 没有认贼作父了对不对?再看 So, assuming your module file name has Isn’t it miserable! ? Fortunately Although the problem is not difficult, the determination and ideas to explore the problem are still important. Related recommendations: Why can Gouri’s module name still be loaded despite the wrong case?
<span style="font-size: 14px;">windows</span>
. Sure enough, we got to <span style="font-size: 14px;">windows</span>
, the case issue is a problem, <span style="font-size: 14px;">Error: Cannot find module './Parent'</span>
. <span style="font-size: 14px;">macOS</span>
doing? Can't you tell the difference between uppercase and lowercase? So hurry up<span style="font-size: 14px;">google</span>
(Don’t ask me why not baidu)<span style="font-size: 14px;">OS X</span>
uses the <span style="font-size: 14px;">case-insensitive</span>
file by default. system (detailed documentation). <span style="font-size: 14px;">node.js</span>
) But that’s the whole truth. So what the hell is it like to have a thief as your father?
<span style="font-size: 14px;">node.js</span>
? Is it caused by that thing? So in the mood to give it a try, I put <span style="font-size: 14px;">const ParentIncorrect = require('./Parent')</span>
and <span style="font-size: 14px;">const Parent = require('./parent')</span>
I changed the position and thought, would it be right to load it with the correct name first? <span style="font-size: 14px;">ParentIncorrect</span>
and## Where is #Parent<span style="font-size: 14px;"></span>
? So I wrote console.log(ParentIncorrect === Parent)<span style="font-size: 14px;"></span>
, and the result was false<span style="font-size: 14px;"></span>
. So they are really not the same thing, so the problem may be in the introduction part? node.js<span style="font-size: 14px;"></span>
was born (in fact, if you don’t look at it, the problem is ultimately I can also figure it out). After a long day, with a feeling of trepidation, I finally clone<span style="font-size: 14px;"></span>
node.js<span style="font-size: 14px;"></span>
Source code (it took a long time, so slow)node.js<span style="font-size: 14px;"></span>
Source code world. Since our question is about require<span style="font-size: 14px;"></span>
, let's start with her, but find require<span style="font-size: 14px;"></span>
The definition process requires some patience. I won’t go into details here. I’ll just talk about the search sequence. <span style="font-size: 14px;"> </span>
<span style="font-size: 14px;"></span>, get to the point:
<span style="font-size: 14px;">Module.prototype.require = function(path) {<br/> assert(path, 'missing path');<br/> assert(typeof path === 'string', 'path must be a string');<br/> return Module._load(path, this, /* isMain */ false);<br/>};<br/></span>
<span style="font-size: 14px;">_load</span>
,永不放弃,继续<span style="font-size: 14px;">Module._load = function(request, parent, isMain) {<br/> //debug代码,么卵用,跳过<br/> if (parent) {<br/> debug('Module._load REQUEST %s parent: %s', request, parent.id);<br/> }<br/><br/> if (isMain && experimentalModules) {<br/> //...<br/> //...<br/> //这段是给ES module用的,不看了啊<br/> }<br/><br/> //获取模块的完整路径<br/> var filename = Module._resolveFilename(request, parent, isMain);<br/><br/> //缓存在这里啊?好激动有没有?!?终于见到她老人家了<br/> //原来这是这样的,简单的一批,毫无神秘感啊有木有<br/> var cachedModule = Module._cache[filename];<br/> if (cachedModule) {<br/> updateChildren(parent, cachedModule, true);<br/> return cachedModule.exports;<br/> }<br/><br/> //加载native但非内部module的,不看<br/> if (NativeModule.nonInternalExists(filename)) {<br/> debug('load native module %s', request);<br/> return NativeModule.require(filename);<br/> }<br/><br/> //构造全新Module实例了<br/> var module = new Module(filename, parent);<br/><br/> if (isMain) {<br/> process.mainModule = module;<br/> module.id = '.';<br/> }<br/><br/> //先把实例引用加缓存里<br/> Module._cache[filename] = module;<br/><br/> //尝试加载模块了<br/> tryModuleLoad(module, filename);<br/><br/> return module.exports;<br/>};<br/></span>
<span style="font-size: 14px;">tryModuleLoad</span>
<span style="font-size: 14px;">function tryModuleLoad(module, filename) {<br/> var threw = true;<br/> try {<br/> //加载模块<br/> module.load(filename);<br/> threw = false;<br/> } finally {<br/> //要是加载失败,从缓存里删除<br/> if (threw) {<br/> delete Module._cache[filename];<br/> }<br/> }<br/>}<br/></span>
<span style="font-size: 14px;">load</span>
了,要不我们先停一停?
<span style="font-size: 14px;">son.js</span>
里用首字母大写(不正确)的模块名引用了 <span style="font-size: 14px;">parent.js</span>
<span style="font-size: 14px;">test.js</span>
里,引用了两次 <span style="font-size: 14px;">parent.js</span>
,一次用完全一致的模块名;一次用首字母大写的模块名。结果发现 <span style="font-size: 14px;">son instanceof require('./parent') === false</span>
<span style="font-size: 14px;">var cachedModule = Module._cache[filename];</span>
,文件名是作为缓存的 <span style="font-size: 14px;">key</span>
,来吧,是时候看看 <span style="font-size: 14px;">Module._cache</span>
里存的模块 <span style="font-size: 14px;">key</span>
都是什么牛鬼蛇神了,打出来看看吧,于是我在 <span style="font-size: 14px;">test.js</span>
里最后面加了一句 <span style="font-size: 14px;">console.log(Object.keys(require.cache))</span>
,我们看看打出了什么结果<span style="font-size: 14px;">false<br/>true<br/>[ '/Users/admin/codes/test/index.js',<br/> '/Users/admin/codes/test/Parent.js',<br/> '/Users/admin/codes/test/parent.js',<br/> '/Users/admin/codes/test/son.js' ]<br/></span>
<span style="font-size: 14px;">Module._cache</span>
里真的出现了两个 <span style="font-size: 14px;">[p|P]arent</span>
( <span style="font-size: 14px;">macOS</span>
默认不区分大小写,所以她找到的其实是同一个文件;但 <span style="font-size: 14px;">node.js</span>
当真了,一看文件名不一样,就当成不同模块了),所以最后问题的关键就在于 <span style="font-size: 14px;">son.js</span>
里到底引用时用了哪个名字(上面我们用了首字母大写的 <span style="font-size: 14px;">require('./Parent.js')</span>
),这才导致了 <span style="font-size: 14px;">test.js</span>
认贼作父的梗。<span style="font-size: 14px;">son.js</span>
,把引用换成 <span style="font-size: 14px;">require('./parEND.js')</span>
,再次执行下 <span style="font-size: 14px;">test.js</span>
看看结果如何呢?<span style="font-size: 14px;">false<br/>false<br/>[ '/Users/haozuo/codes/test/index.js',<br/> '/Users/haozuo/codes/test/Parent.js',<br/> '/Users/haozuo/codes/test/parent.js',<br/> '/Users/haozuo/codes/test/son.js',<br/> '/Users/haozuo/codes/test/parENT.js' ]<br/></span>
<span style="font-size: 14px;">Module._cache</span>
里,原来是 <span style="font-size: 14px;">parENT.js</span>
也被当成一个单独的模块了。<span style="font-size: 14px;">n</span>
characters, theoretically, in <span style="font-size: 14px;"> macOS</span>
In a case-insensitive file system, you can <span style="font-size: 14px;">node.js</span>
maximize it<span style="font-size: 14px;">2</span>
of <span style="font-size: 14px;">n</span>
power caches to <span style="font-size: 14px;">macOS</span>
You can still change it to case-sensitive, reinstall the system from a grid disk, or create a new partition.
The above is the detailed content of The story between node.js and macOS. For more information, please follow other related articles on the PHP Chinese website!