require('atom') 是如何工作的?

How does require('atom') work?

Atom 公开了一些您可以从 require('atom')

访问的全局 API

这在功能上是如何工作的? Atom 包没有明确地将 atom 作为依赖项,但它们仍然可以这样做。此外,如何在我自己的 Electron 应用程序中使用我自己的全局包执行此操作?

我自己仔细研究并分析了 Atom 的源代码以确定这是如何发生的,这就是我得出的结论。

使用 normal node require. However, according to the apm 自述文件需要 Atom 包:

The other major difference is that Atom packages are installed to ~/.atom/packages instead of a local node_modules folder...

因此 require('atom') 包不像普通节点模块那样从父 node_modules 目录中检索。相反,Atom 覆盖模块加载器以稍微改变行为。

更具体地说,它们覆盖了 Module._resolveFilename,如下所示:

Module = require 'module'

Module._resolveFilename = (relativePath, parentModule) ->
  resolvedPath = resolveModulePath(relativePath, parentModule)
  resolvedPath ?= resolveFilePath(relativePath, parentModule)
  resolvedPath ? originalResolveFilename(relativePath, parentModule)

在默认为正常行为之前,它会尝试使用自己的模块缓存逻辑解析模块的路径。这样做有几个原因,我可以告诉。

  1. 它允许他们对 'atom' 等内置模块的路径进行硬编码,即使正常行为永远找不到它。
  2. 当包与兼容版本具有相同的依赖关系时,它可以防止加载包依赖关系两次。如果 packageA 加载 lodash@4.x.x 并且稍后 packageB 尝试加载 lodash@>=3,那么 Atom 介入并为 packageB 提供 packageA 加载的 lodash。