【问题标题】:Order of resolution with nodejs require modulenodejs require 模块的解析顺序
【发布时间】:2013-05-01 21:57:23
【问题描述】:

假设我将所有foo.jsfoo.coffeefoo.json 放在同一个目录中,并且我说require './foo' 来自该位置的另一个(coffeescript)文件,那么将加载哪个规则是什么规则?

一个简短的实验(使用require.resolve './foo')似乎表明javascript 文件胜过其他两个文件。

确实,看看require.extensions看起来像 .js 被作为第一项被提及——但是,对象属性名称在 javascript 中本质上是无序的,对吧?所以添加任何名称到该属性可能会重新排序条目——这会导致另一个解析顺序吗?

只是想知道,因为我找不到任何文档。当你这样做时它确实变得相关(也许你不应该)coffee --compile route/to/directory

【问题讨论】:

标签: node.js module coffeescript require


【解决方案1】:

首先加载.js(这也意味着最好使用完整的name.json而不是name,因为它可能会被name.js遮蔽)

来自“模块”documentation

如果未找到确切的文件名,则 node 将尝试加载所需的文件名,并添加扩展名为 .js、.json 和 .node。

另外,读取pseudo-code中的名称解析算法:

LOAD_AS_FILE(X)
1.  If X is a file, load X as JavaScript text.  STOP
2.  If X.js is a file, load X.js as JavaScript text.  STOP
3.  If X.node is a file, load X.node as binary addon.  STOP

在 require.extensions 中设置的 (1,2,3) 扩展名之后,按照它们设置的顺序进行检查(对于 CoffeScript,require("coffe-script")installs.coffee 处理程序)。

【讨论】:

  • 非常感谢您的回答;我赞成它作为“分裂投票”的尝试(考虑到事情在 SO 上的运作方式,我真的不能这样做)。我知道文档中的那些引用,但我一直认为它们(1)太不具体,无法真正确定在那些已知的少数情况之外如何进行排序; (2) 关于如何扩展require 机制much 太短了。另请注意,虽然您确实正确引用了文档中的上述段落,但它们也有些矛盾,因为伪代码没有提及 .json 文件。
  • 最好的信息来源是 modeule.js 本身 - github.com/joyent/node/blob/master/lib/module.js 。它简短易读。并且文档确实提到了 .json。
  • 啊,是的,来源……当然……但是我们仍然需要一份关于事情如何运作的可靠文档,对吧? “这辆车能以 200 公里/小时的速度行驶”与在燃烧室内看是不同的。
  • 我会说你的例子中的“燃烧室”是 V8 内部 - 词法分析器、ast 解析器、优化器等。这里的 Module.js 源更像是速度计数据 - 它实际上应该被读取。并且有适当的文档说明事情的预期工作方式。
  • '有适当的文档说明事情是如何工作的'正是我发现在这种情况下缺少一点点的东西:文档不是很具体,来源不容易使用,而 javascript在迭代对象键时,引擎在规范/通常同意的一组行为中存在某种漏洞/白点(而 v8 恰好与其他孩子稍有不同)。 javascript 是一种应该在许多平台上运行的语言,并且 nodejs 模块是在 commonjs 之后模式化的,因此询问其他地方的模块解析会发生什么是有效的
【解决方案2】:

V8 中的行为是按照最初分配的顺序对命名属性进行迭代,所以我希望 .js 始终是第一个。

This post references that behavior

【讨论】:

  • 非常感谢您的回答;我将您的内容标记为正确,因为您提供的链接将讨论提升到了一个全新的水平——我不知道那里讨论的大多数方面。
  • 这实际上是不正确的。 .js 首先不是因为它是Object.keys(require.extensions) 的第一个元素,而是因为它被特殊对待。尝试将“.as”添加到require.extensions
  • @AndreySidorov 愿意犯错。你能举更多的例子吗?我不关注你的.as 案例。
  • 我也不知道。做d = zzz: yes, bbb: no, '.23': 'decimal', '42': 'integer'; log ( name for name of d ); log Object.keys d; d[ 'bbb' ] = 'reassigned'; log ( name for name of d ); log Object.keys d; 你会得到[ '42', 'zzz', 'bbb', '.23' ] 四次。整数放在前面(这是 v8-special),bbb 即使重新分配也不让步。
猜你喜欢
  • 2016-03-15
  • 1970-01-01
  • 1970-01-01
  • 2019-04-05
  • 2021-10-08
  • 1970-01-01
  • 1970-01-01
  • 2022-01-20
  • 1970-01-01
相关资源
最近更新 更多