首页
/ @puppeteer/browsers BrowserProvider.getExecutablePath:自定义浏览器 Provider 的可执行文件定位协议

@puppeteer/browsers BrowserProvider.getExecutablePath:自定义浏览器 Provider 的可执行文件定位协议

2026-09-07 14:06:10作者:邓越浪Henry

导读

BrowserProvider.getExecutablePath() 是 Puppeteer 浏览器下载/缓存工具链中决定"解压后的可执行文件到底在哪一层目录里"的关键方法。它告诉安装流程:一个下载并解压完毕的浏览器归档,其真正的启动程序(如 chromechromedriverfirefox)相对于解压根目录位于哪个路径。阅读本文后,你将掌握 getExecutablePath 的签名语义、同步/异步两种实现形态、它在安装与路径解析流程中的调用位置,以及如何为自定义下载源编写一份可用的 getExecutablePath 实现。

关联文档:BrowserProvider.getExecutablePath(),接口总览见 BrowserProvider

方法签名与语义

getExecutablePathBrowserProvider 接口(定义于 packages/browsers/src/provider.ts)的四个成员之一,其余为 supportsgetDownloadUrlgetName。其完整签名如下:

interface BrowserProvider {
  getExecutablePath(options: {
    browser: Browser;
    buildId: string;
    platform: BrowserPlatform;
  }): Promise<string> | string;
}

参数与返回

参数 类型 说明
options.browser Browser 目标浏览器标识,例如 Browser.CHROMEBrowser.CHROMEDRIVERBrowser.FIREFOX
options.buildId string 浏览器构建号(如 131.0.6778.109),可能为别名解析前的原始值
options.platform BrowserPlatform 运行平台,如 BrowserPlatform.LINUXBrowserPlatform.WIN64BrowserPlatform.MAC_ARM

返回:Promise<string> | string —— 可执行文件相对于解压根目录的相对路径。方法既可同步返回字符串,也可返回 Promise(源码注释明确指出两种形态均被接受,见 provider.ts),这为需要在返回值前做异步平台探测/版本判断的自定义 Provider 保留了余地。

在安装流程中的调用位置

getExecutablePath 并不由使用者直接调用,而是被安装器内部驱动。在 packages/browsers/src/install.ts 中,install 内部的下载解压逻辑拿到归档后会这样做:

// Get executable path from provider once (used for both cached and new installations)
const relativeExecutablePath = await provider.getExecutablePath({
  browser: options.browser,
  buildId: options.buildId,
  platform: options.platform,
});
logger?.(DEBUG_PREFIXES.install)?.(
  `Using executable path from provider: ${relativeExecutablePath}`,
);

从源码结构看,这一调用发生在 unpackArchive 解压前、outputPath(即缓存中 浏览器名/平台-buildId 目录)确定之后,返回值随后被写入安装元数据(仅对非默认 Provider),并最终拼出 InstalledBrowser.executablePath 的完整绝对路径。

自定义 Provider 的路径持久化

同段源码显示,若执行安装的 Provider 不是内置的 DefaultProvider 实例,安装器会调用 cache.writeExecutablePath(...) 把该相对路径写入浏览器的 .metadata 文件(见 install.ts):

// Write metadata for the installation (only for non-default providers)
if (!(provider instanceof DefaultProvider)) {
  cache.writeExecutablePath(
    options.browser,
    options.platform,
    options.buildId,
    relativeExecutablePath,
  );
}

对应地,在 packages/browsers/src/Cache.tscomputeExecutablePath 中,路径解析遵循"先读元数据、后走内置规则"的顺序:如果 .metadata 里已存有由自定义 Provider 提供的相对路径,就直接 path.join(installationDir, storedExecutablePath);否则回退到按浏览器类型查表计算的内置相对路径。

一个值得注意的校验点

同样在 install.ts 中,当 outputPath 已存在时,安装器会用 existsSync(installedBrowser.executablePath) 校验可执行文件是否真实存在;缺失时抛出 IncompleteInstallationError,提示"安装目录存在但可执行文件缺失,上一次安装可能未完成"。这解释了 getExecutablePath 返回值为何必须与实际归档内部结构严格一致——任何不一致都会在后续启动或二次安装校验中暴露。

内置 DefaultProvider 如何实现

内置默认 Provider 的 getExecutablePath 实现非常薄,本质是委托给按浏览器分派的路由表(见 packages/browsers/src/DefaultProvider.ts):

getExecutablePath(options: {
  browser: Browser;
  buildId: string;
  platform: BrowserPlatform;
}): string {
  return executablePathByBrowseroptions.browser;
}

executablePathByBrowser 定义在 packages/browsers/src/browser-data/browser-data.ts,为当前支持的 5 种目标分别注册了相对路径函数:

浏览器枚举 路径函数来源文件
Browser.CHROMEDRIVER browser-data/chromedriver.ts
Browser.CHROMEHEADLESSSHELL browser-data/chrome-headless-shell.ts
Browser.CHROME browser-data/chrome.ts
Browser.CHROMIUM browser-data/chromium.ts
Browser.FIREFOX browser-data/firefox.ts

以 Chromedriver 为例,其 relativeExecutablePathchromedriver.ts)按平台分支返回形如 chromedriver-<folder>/chromedriver 的路径;Windows 平台(WIN32/WIN64)返回同一路径加 .exe 后缀,macOS 与 Linux 保持一致。类似的平台化差异逻辑同样存在于 Chrome、chrome-headless-shell 与 Firefox 的路径函数中。这说明:相对路径不是固定字符串,而通常是 platform 参数的函数,因为 Windows 可执行文件带 .exe 扩展名,且归档内部的顶层目录名常随平台与构建号变化。

官方文档示例与增强版实现

关联文档给出了两个示例,第一个针对目录结构固定的 Electron 场景,第二个面向需要平台区分的自定义 Provider。此处结合接口注释(provider.ts)给出可落地的增强版本:

示例 1:固定目录结构(Electron 风格)

// Electron uses simple structure
getExecutablePath() {
  return 'chromedriver/chromedriver';
}

适合归档内部结构恒定、不随平台变化的下载源。若目标平台包含 Windows,还应补充扩展名判断:

getExecutablePath(options) {
  const ext = options.platform.includes('win') ? '.exe' : '';
  return `chromedriver/chromedriver${ext}`;
}

示例 2:平台相关的动态路径

// Custom provider with platform-specific paths
getExecutablePath(options) {
  return `binaries/${options.browser}-${options.platform}`;
}

一个更完整的写法可以借鉴内置实现的平台分支思路:

async getExecutablePath(options) {
  const ext =
    options.platform === BrowserPlatform.WIN32 ||
    options.platform === BrowserPlatform.WIN64
      ? '.exe'
      : '';
  const platformFolder = {
    linux: 'linux64',
    win32: 'win64',
    mac: 'mac',
  }[options.platform];
  return `my-browser-${platformFolder}/mybrowser${ext}`;
}

异步返回的合法用法

由于签名允许 Promise<string>,Provider 也可以在返回路径前执行异步探测(例如读取解压目录后再确定结构),这正是 supports/getDownloadUrl 也同时接受同步与异步形态的设计意图。

编写自定义实现时的注意事项

基于源码,编写 getExecutablePath 时应注意以下几点:

  1. 返回的是"归档内相对路径"而非绝对路径。最终绝对路径由安装器以 缓存目录/浏览器名/<platform>-<buildId> 为基准拼接而成(installationDirCache.ts),不要在此返回以 / 或盘符开头的绝对路径。
  2. 必须与 getDownloadUrl 指向的归档内部结构一致。接口注释同时强调下载 URL 不被预先校验,URL 指向不存在的归档会推迟到下载阶段才失败;而结构不一致则会在解压后因找不到可执行文件而失败。
  3. 目录顶层通常含平台与构建号。内置实现中 folder(platform, buildId) 参与了路径构成,若你的下载源采用了不同的顶层命名,请务必在你的 Provider 中如实反映。
  4. 路径持久化仅对非默认 Provider 生效instanceof DefaultProvider 的实例会跳过元数据写入(install.ts),因此自定义 Provider 返回的相对路径会被持久化到 .metadata 并在后续 computeExecutablePath 中被优先读取。
  5. Windows 特殊处理:Windows 平台除 .exe 后缀外,Chrome 安装还会在解压后运行 setup.exe --configure-browser-in-directory 完成沙箱权限配置(见 install.ts),自定义 Provider 应保证归档内含所需文件结构。

自定义 Provider 的完整上下文

getExecutablePath 只是 BrowserProvider 的一个环节。要实现一个可用的自定义下载源,需同时实现四个方法(完整接口见 provider.ts):

class MyBrowserProvider implements BrowserProvider {
  supports(options) { /* 是否处理该 browser/platform 组合 */ }
  getDownloadUrl(options) { /* 返回下载 URL 或 null */ }
  getExecutablePath(options) { /* 返回归档内相对路径 */ }
  getName() { /* 返回 Provider 名称,用于日志与报错 */ }
}

getName() 在源码中被特意设计为独立方法而非依赖 constructor.name,以避免生产构建中类名被压缩混淆后无法定位 Provider(接口注释见 provider.ts)。整套接口的意义在于:当官方默认下载源不可用时,你可以基于 getDownloadUrl(下载)+ getExecutablePath(定位)+ supports(筛选)这三个协议点接入私有镜像、Electron 发布源或企业内网归档。

值得强调的是:Provider 源码注释明确提示,自定义下载源并未得到 Puppeteer 官方测试保证,实现者需自行承担二进制兼容性、启动可用性以及 Puppeteer 与下载源各自演进时的维护责任,官方仅对 Chrome for Testing 二进制做测试保障(provider.ts)。

相关资源

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.13 K
2.75 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
857
1.35 K
docsdocs
暂无描述
Markdown
897
5.8 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
529
593
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
915
1.83 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.58 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.35 K
1.46 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.01 K
515
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
547
388