面向公式作者的 Node

本文档说明如何在基于 Node 模块的 Homebrew 公式中成功使用 Node 和 npm。

运行 npm install

Homebrew 在 Language::Node 模块中提供了两个帮助器方法:std_npm_install_argslocal_npm_install_args。它们都为 npm 设置了正确的环境,并为 npm install 返回了针对其特定用例的参数。你的公式应使用这些方法,而不是显式调用 npm install。标准 Node 模块安装的语法为

system "npm", "install", *Language::Node.std_npm_install_args(libexec)

其中 libexec 是目标前缀(通常是 libexec 变量)。

下载 URL

如果 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 模块

这两种方法的共同点是,它们为在 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 软件包自动生成如上示例所示的公式。

Fork me on GitHub