本文档说明如何在基于 Node 模块的 Homebrew 公式中成功使用 Node 和 npm。
npm installHomebrew 在 Language::Node 模块中提供了两个帮助器方法:std_npm_install_args 和 local_npm_install_args。它们都为 npm 设置了正确的环境,并为 npm install 返回了针对其特定用例的参数。你的公式应使用这些方法,而不是显式调用 npm install。标准 Node 模块安装的语法为
system "npm", "install", *Language::Node.std_npm_install_args(libexec)
其中 libexec 是目标前缀(通常是 libexec 变量)。
如果 Node 模块也在 npm 注册表中可用,我们更喜欢 npm 托管的发布 tarball,而不是 GitHub(或其他地方)托管的源 tarball。这些 tarball 的优点在于,它们不包含 .npmignore 中的文件(例如测试),从而减小了下载大小,并且任何可能的转换步骤都已经完成(例如,无需将 CoffeeScript 文件编译为构建步骤)。
npm 注册表 URL 通常具有以下格式
https://registry.npmjs.org/<name>/-/<name>-<version>.tgz
或者,你可以在 https://registry.npmjs.org/<name> 上 curl JSON,并查找 versions[<version>].dist.tarball 的值以获取正确的 tarball URL。
与最新 Node 版本兼容的 Node 模块应声明对 node 公式的依赖项。
depends_on "node"
如果你的公式需要使用较旧的 Node 版本执行,则应使用其一个版本化公式(例如 node@12)。
如果你的 Node 模块是原生插件或其依赖项树中的某个位置有原生插件,则必须声明一个附加依赖项。由于原生插件的编译会导致调用 node-gyp,因此我们需要对 "python" 有一个额外的构建时间依赖项(因为 GYP 依赖于 Python)。
depends_on "python" => :build
另请注意,此类公式仅与最初编译时相同的 Node 主要版本兼容。这意味着我们需要在 node 公式的每次主要版本升级时,修改每个带有 Node 原生插件的公式。为了确保我们不会在 Node 主要版本升级时忽略你的公式,请编写一个有意义的测试,该测试在这种情况下会失败(使用 ABI 不兼容的 Node 版本调用)。
Node 模块应安装到 libexec。这可以防止 Node 模块污染全局 node_modules,这一点很重要,这样 npm 才不会尝试管理 Homebrew 安装的 Node 模块。
在下面,我们区分使用公式安装的两种类型的 Node 模块
std_npm_install_args(如 apollo-cli 或 webpack)npm install 调用不是唯一必需的安装步骤(例如,还需要编译非 JavaScript 源)的公式,必须使用 local_npm_install_args(如 emscripten 或 grunt-cli)这两种方法的共同点是,它们为在 Homebrew 中使用 npm 设置了正确的环境,并返回了为其特定用例调用 npm install 的参数。这包括通过在 HOMEBREW_CACHE 中使用我们自己的自定义 npm_cache 来修复 npm 缓存的一个重要边缘情况(由 Homebrew 在构建和测试过程中重定向 HOME 引起),否则会导致非常长的构建时间和较高的磁盘空间使用率。
要使用它们,您必须在公式文件的开头使用以下命令请求 Node 语言模块
require "language/node"
std_npm_install_args 将全局样式模块安装到 libexec在公式的 install 方法中,只需在必要时 cd 到 Node 模块的顶级目录,然后使用 system 调用 npm install,并使用 Language::Node.std_npm_install_args,如下所示
system "npm", "install", *Language::Node.std_npm_install_args(libexec)
这会将您的 Node 模块安装到 npm 的全局模块样式中,并使用自定义前缀 libexec。所有模块的可执行文件都将由 npm 自动解析到 libexec/bin 中,这些文件不会符号链接到 Homebrew 的前缀中。为了确保安装这些文件,我们需要使用以下命令将所有可执行文件符号链接到 bin
bin.install_symlink Dir["#{libexec}/bin/*"]
local_npm_install_args 本地安装模块依赖项在公式的 install 方法中,执行在 npm install 步骤之前需要完成的所有安装步骤,然后 cd 到包含的 Node 模块的顶级目录。然后,使用 system 调用 npm install,并使用 Language::Node.local_npm_install_args,如下所示
system "npm", "install", *Language::Node.local_npm_install_args
这会将所有 Node 模块的依赖项安装到您的本地构建路径。您现在可以继续执行构建步骤,并按照 通用 Homebrew 公式说明 自行处理安装到 Homebrew 前缀中的操作。
安装基于标准 Node 模块的公式如下所示
require "language/node"
class Foo < Formula
  desc "An example formula"
  homepage "https://example.com"
  url "https://registry.npmjs.org/foo/-/foo-1.4.2.tgz"
  sha256 "abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc1"
  depends_on "node"
  # uncomment if there is a native addon inside the dependency tree
  # depends_on "python" => :build
  def install
    system "npm", "install", *Language::Node.std_npm_install_args(libexec)
    bin.install_symlink Dir["#{libexec}/bin/*"]
  end
  test do
    # add a meaningful test here, version isn't usually meaningful
    assert_match version.to_s, shell_output("#{bin}/foo --version")
  end
end
您可以使用 homebrew-npm-noob 为 npm 软件包自动生成如上示例所示的公式。