包管理器提示
【Package manager tips】
Node.js require() 函数的语义设计得足够通用,以支持合理的目录结构。希望像 dpkg、rpm 和 npm 这样的包管理程序能够在不修改的情况下从 Node.js 模块构建本地包。
【The semantics of the Node.js require() function were designed to be general
enough to support reasonable directory structures. Package manager programs
such as dpkg, rpm, and npm will hopefully find it possible to build
native packages from Node.js modules without modification.】
下面给出了一个可行的建议目录结构:
【Below we give a suggested directory structure that could work:】
假设我们希望位于 /usr/lib/node/<some-package>/<some-version> 的文件夹保存某个特定版本的包的内容。
软件包可以相互依赖。为了安装软件包 foo,可能需要安装软件包 bar 的特定版本。bar 软件包本身也可能有依赖,在某些情况下,这些依赖甚至可能冲突或形成循环依赖。
【Packages can depend on one another. In order to install package foo, it
may be necessary to install a specific version of package bar. The bar
package may itself have dependencies, and in some cases, these may even collide
or form cyclic dependencies.】
因为 Node.js 会查找它加载的任何模块的 realpath(也就是说,它会解析符号链接),然后在 node_modules 文件夹中查找它们的依赖,所以这种情况可以通过以下架构来解决:
【Because Node.js looks up the realpath of any modules it loads (that is, it
resolves symlinks) and then looks for their dependencies in node_modules folders,
this situation can be resolved with the following architecture:】
/usr/lib/node/foo/1.2.3/:foo包的内容,版本为 1.2.3。/usr/lib/node/bar/4.3.2/:foo所依赖的bar包的内容。/usr/lib/node/foo/1.2.3/node_modules/bar:指向/usr/lib/node/bar/4.3.2/的符号链接。/usr/lib/node/bar/4.3.2/node_modules/*:指向bar所依赖的包的符号链接。
因此,即使遇到循环,或者存在依赖冲突,每个模块仍然能够获得一个可以使用的依赖版本。
【Thus, even if a cycle is encountered, or if there are dependency conflicts, every module will be able to get a version of its dependency that it can use.】
当 foo 包中的代码执行 require('bar') 时,它将获取符号链接到 /usr/lib/node/foo/1.2.3/node_modules/bar 的版本。然后,当 bar 包中的代码调用 require('quux') 时,它将获取符号链接到 /usr/lib/node/bar/4.3.2/node_modules/quux 的版本。
【When the code in the foo package does require('bar'), it will get the
version that is symlinked into /usr/lib/node/foo/1.2.3/node_modules/bar.
Then, when the code in the bar package calls require('quux'), it'll get
the version that is symlinked into
/usr/lib/node/bar/4.3.2/node_modules/quux.】
此外,为了使模块查找过程更加优化,我们可以将包放在 /usr/lib/node_modules/<name>/<version>,而不是直接放在 /usr/lib/node。这样,Node.js 就不会去 /usr/node_modules 或 /node_modules 中寻找缺失的依赖了。
为了在 Node.js REPL 中使用模块,将 /usr/lib/node_modules 文件夹添加到 $NODE_PATH 环境变量中可能会很有用。由于使用 node_modules 文件夹进行的模块查找都是相对的,并且基于调用 require() 的文件的真实路径,因此这些包本身可以位于任何地方。
【In order to make modules available to the Node.js REPL, it might be useful to
also add the /usr/lib/node_modules folder to the $NODE_PATH environment
variable. Since the module lookups using node_modules folders are all
relative, and based on the real path of the files making the calls to
require(), the packages themselves can be anywhere.】