@snapka/browsers
v0.1.4
Published
Download and launch browsers for Puppeteer and Playwright
Downloads
635
Maintainers
Readme
@snapka/browsers
基于 Puppeteer 的浏览器下载与启动工具,提供 CLI 与 Node.js API,支持自动下载、安装和管理多种浏览器。
✨ 特性
- 🚀 支持多种浏览器:Chrome、Chromium、Firefox、ChromeDriver、Chrome Headless Shell
- 📦 自动下载和管理浏览器版本
- 🔄 支持多个发布渠道:stable、beta、dev、canary 等
- 🌐 支持代理和自定义镜像源
- 💻 提供 CLI 和 Node.js API 两种使用方式
- 🇨🇳 命令行输出完全本地化为中文
📊 与上游差异
相比官方 @puppeteer/browsers:
- ✅ 移除
proxy-agent,使用 Axios 原生代理(支持HTTP_PROXY/HTTPS_PROXY环境变量) - ✅ 解压工具改为
decompress,移除tar-fs和extract-zip依赖 - ✅ 包体积大幅缩减:约 12 MB → 800 KB+(数据来源:pkg-size.dev)
- ✅ 新增
probeUrls()工具函数,支持自动选择最快的镜像源 - ✅ Chromium 版本解析失败时提供兜底版本号,避免下载中断
📋 环境要求
- Node.js: 18.0 或更高版本
- 平台: Linux / macOS / Windows(自动检测,可手动指定)
📦 安装
npm install @snapka/browsers
# 或
pnpm add @snapka/browsers
# 或
yarn add @snapka/browsers🚀 快速开始
CLI 使用
# 安装最新版 Chrome
npx @snapka/browsers install chrome
# 安装特定通道的 Chrome
npx @snapka/browsers install chrome@beta
# 安装特定版本的 Chrome
npx @snapka/browsers install [email protected]
# 安装到指定目录
npx @snapka/browsers install chrome --path ./my-browsers
# 列出已安装的浏览器
npx @snapka/browsers list
# 启动已安装的浏览器
npx @snapka/browsers launch [email protected]Node.js API 使用
import {
Browser,
install,
launch,
resolveBuildId,
detectBrowserPlatform,
computeExecutablePath,
} from '@snapka/browsers'
// 1. 检测当前平台
const platform = detectBrowserPlatform()
// 2. 解析版本标识
const buildId = await resolveBuildId(Browser.CHROME, platform, 'stable')
// 3. 下载并安装浏览器
await install({
browser: Browser.CHROME,
buildId,
platform,
cacheDir: './.browsers',
downloadProgressCallback: 'default', // 显示下载进度
})
// 4. 获取可执行文件路径
const executablePath = computeExecutablePath({
browser: Browser.CHROME,
buildId,
platform,
cacheDir: './.browsers',
})
// 5. 启动浏览器
const process = await launch({
executablePath,
args: ['--headless=new', '--no-sandbox'],
})
// 6. 使用完毕后关闭
await process.kill()🌐 支持的浏览器
Chrome
标识符:
chrome支持的通道/标签:
@latest- 最新的 Canary 版本@stable- 稳定版@beta- 测试版@dev- 开发版@canary- Canary 版@<版本号>- 特定版本,如@120或@120.0.6099.109
示例:
npx @snapka/browsers install chrome@stable npx @snapka/browsers install [email protected]
Chromium
标识符:
chromium支持的标签:
@latest- 最新的快照版本@<修订号>- 特定修订版,如@1083080
示例:
npx @snapka/browsers install chromium@latest npx @snapka/browsers install chromium@1083080
Firefox
标识符:
firefox支持的通道/标签:
@latest/@nightly- Nightly 版本@stable- 稳定版@beta- 测试版@devedition- 开发者版@esr- ESR 长期支持版@<版本号>- 特定版本,如@stable_111.0.1
示例:
npx @snapka/browsers install firefox@stable npx @snapka/browsers install firefox@nightly
ChromeDriver
标识符:
chromedriver支持的通道/标签:
@latest/@canary- 最新 Canary 版本@stable- 稳定版@beta- 测试版@dev- 开发版@<版本号>- 特定版本,如@115或@115.0.5790
示例:
npx @snapka/browsers install chromedriver@stable npx @snapka/browsers install [email protected]
Chrome Headless Shell
标识符:
chrome-headless-shell支持的通道/标签:
@latest/@canary- 最新 Canary 版本@stable- 稳定版@beta- 测试版@dev- 开发版@<版本号>- 特定版本
示例:
npx @snapka/browsers install chrome-headless-shell@stable npx @snapka/browsers install chrome-headless-shell@118
🔧 CLI 命令参考
install
下载并安装指定的浏览器。
npx @snapka/browsers install <browser>[@<buildId|channel>] [options]选项:
--platform <platform>- 指定平台(linux,mac,mac-arm,win32,win64)--path <path>- 指定缓存目录(默认:当前工作目录)--base-url <url>- 自定义下载源 URL--install-deps- 安装系统依赖(仅 Linux,需要 root 权限)
示例:
# 基本用法
npx @snapka/browsers install chrome
# 指定版本通道
npx @snapka/browsers install chrome@beta
# 指定具体版本
npx @snapka/browsers install [email protected]
# 指定平台和缓存目录
npx @snapka/browsers install firefox@stable --platform mac --path ./browsers
# 使用镜像源
npx @snapka/browsers install chrome --base-url https://example.com/mirrors镜像源参考:
- chrome:
https://registry.npmmirror.com/-/binary/chrome-for-testing - chromium:
https://registry.npmmirror.com/-/binary/chromium-browser-snapshots
launch
启动已安装的浏览器。
npx @snapka/browsers launch <browser>[@<buildId>] [options] [-- <browser-args>]选项:
--platform <platform>- 指定平台--path <path>- 指定缓存目录--detached- 以分离模式运行(不阻塞终端)--system- 使用系统已安装的浏览器--dumpio- 转发浏览器进程的 stdout 和 stderr
示例:
# 启动已安装的浏览器
npx @snapka/browsers launch [email protected]
# 启动并传递浏览器参数
npx @snapka/browsers launch chrome@stable -- --headless=new --disable-gpu
# 启动系统安装的 Chrome Canary
npx @snapka/browsers launch chrome@canary --system
# 以分离模式启动
npx @snapka/browsers launch firefox@stable --detachedlist
列出所有已安装的浏览器。
npx @snapka/browsers list [options]选项:
--path <path>- 指定缓存目录
示例:
npx @snapka/browsers list
npx @snapka/browsers list --path ./my-browsersclear
清空缓存目录中的所有浏览器。
npx @snapka/browsers clear [options]选项:
--path <path>- 指定缓存目录
示例:
npx @snapka/browsers clear
npx @snapka/browsers clear --path ./my-browsers📚 Node.js API 参考
枚举类型
Browser
浏览器类型枚举。
enum Browser {
CHROME = 'chrome',
CHROMIUM = 'chromium',
FIREFOX = 'firefox',
CHROMEDRIVER = 'chromedriver',
CHROMEHEADLESSSHELL = 'chrome-headless-shell',
}BrowserPlatform
支持的平台。
enum BrowserPlatform {
LINUX = 'linux',
MAC = 'mac',
MAC_ARM = 'mac-arm',
WIN32 = 'win32',
WIN64 = 'win64',
}ChromeReleaseChannel
Chrome 发布通道。
enum ChromeReleaseChannel {
STABLE = 'stable',
BETA = 'beta',
DEV = 'dev',
CANARY = 'canary',
}核心函数
detectBrowserPlatform()
自动检测当前操作系统平台。
function detectBrowserPlatform(): BrowserPlatform返回: 当前平台的 BrowserPlatform 枚举值
示例:
import { detectBrowserPlatform } from '@snapka/browsers'
const platform = detectBrowserPlatform()
console.log(platform) // 例如: 'win64'resolveBuildId()
将版本标签或通道名解析为实际的构建 ID。
function resolveBuildId(
browser: Browser,
platform: BrowserPlatform,
tag: string
): Promise<string>参数:
browser- 浏览器类型platform- 目标平台tag- 版本标签(如'latest','stable','120.0.6099.109')
返回: 解析后的构建 ID
示例:
import { Browser, resolveBuildId, detectBrowserPlatform } from '@snapka/browsers'
const buildId = await resolveBuildId(
Browser.CHROME,
detectBrowserPlatform(),
'stable'
)
console.log(buildId) // 例如: '120.0.6099.109'install()
下载并安装浏览器。
function install(options: InstallOptions): Promise<void>
interface InstallOptions {
browser: Browser
buildId: string
platform: BrowserPlatform
cacheDir: string
baseUrl?: string
downloadProgressCallback?: 'default' | ((downloadedBytes: number, totalBytes: number) => void)
installDeps?: boolean
}参数:
browser- 浏览器类型buildId- 构建 ID(通过resolveBuildId()获取)platform- 目标平台cacheDir- 缓存目录路径baseUrl- (可选)自定义下载源 URLdownloadProgressCallback- (可选)下载进度回调,传'default'显示默认进度条installDeps- (可选)是否安装系统依赖(仅 Linux)
示例:
import { Browser, install, resolveBuildId, detectBrowserPlatform } from '@snapka/browsers'
const platform = detectBrowserPlatform()
const buildId = await resolveBuildId(Browser.CHROME, platform, 'stable')
await install({
browser: Browser.CHROME,
buildId,
platform,
cacheDir: './browsers',
downloadProgressCallback: 'default',
})computeExecutablePath()
计算已安装浏览器的可执行文件路径。
function computeExecutablePath(options: ComputeExecutablePathOptions): string
interface ComputeExecutablePathOptions {
browser: Browser
buildId: string
platform: BrowserPlatform
cacheDir: string
}返回: 浏览器可执行文件的绝对路径
示例:
import { Browser, computeExecutablePath, detectBrowserPlatform } from '@snapka/browsers'
const executablePath = computeExecutablePath({
browser: Browser.CHROME,
buildId: '120.0.6099.109',
platform: detectBrowserPlatform(),
cacheDir: './browsers',
})
console.log(executablePath)launch()
启动浏览器进程。
function launch(options: LaunchOptions): Promise<Process>
interface LaunchOptions {
executablePath?: string
args?: string[]
dumpio?: boolean
detached?: boolean
env?: NodeJS.ProcessEnv
handleSIGINT?: boolean
handleSIGTERM?: boolean
handleSIGHUP?: boolean
}
interface Process {
pid: number
kill(signal?: NodeJS.Signals): Promise<void>
exitPromise: Promise<number | null>
}参数:
executablePath- 浏览器可执行文件路径args- (可选)传递给浏览器的命令行参数dumpio- (可选)是否转发浏览器的 stdout/stderrdetached- (可选)是否以分离模式运行env- (可选)环境变量handleSIGINT/SIGTERM/SIGHUP- (可选)是否处理信号
返回: Process 对象,包含进程 ID 和控制方法
示例:
import { launch, computeExecutablePath } from '@snapka/browsers'
const executablePath = computeExecutablePath({
browser: Browser.CHROME,
buildId: '120.0.6099.109',
platform: detectBrowserPlatform(),
cacheDir: './browsers',
})
const process = await launch({
executablePath,
args: [
'--headless=new',
'--no-sandbox',
'--disable-setuid-sandbox',
],
dumpio: true,
})
console.log('浏览器进程 PID:', process.pid)
// 等待进程退出
await process.exitPromise
// 或手动终止
await process.kill()canDownload()
检查浏览器是否可以下载(不实际下载)。
function canDownload(options: InstallOptions): Promise<boolean>返回: 如果可以下载返回 true
示例:
import { Browser, canDownload, detectBrowserPlatform } from '@snapka/browsers'
const isAvailable = await canDownload({
browser: Browser.CHROME,
buildId: '120.0.6099.109',
platform: detectBrowserPlatform(),
cacheDir: './browsers',
})
console.log('可以下载:', isAvailable)getInstalledBrowsers()
获取已安装的浏览器列表。
function getInstalledBrowsers(options: GetInstalledBrowsersOptions): InstalledBrowser[]
interface GetInstalledBrowsersOptions {
cacheDir: string
}
interface InstalledBrowser {
browser: Browser
buildId: string
platform: BrowserPlatform
cacheDir: string
executablePath: string
}示例:
import { getInstalledBrowsers } from '@snapka/browsers'
const browsers = getInstalledBrowsers({ cacheDir: './browsers' })
browsers.forEach(browser => {
console.log(`${browser.browser}@${browser.buildId} (${browser.platform})`)
console.log(` 路径: ${browser.executablePath}`)
})uninstall()
卸载已安装的浏览器。
function uninstall(options: UninstallOptions): Promise<void>
interface UninstallOptions {
browser: Browser
platform: BrowserPlatform
cacheDir: string
buildId: string
}示例:
import { Browser, uninstall, detectBrowserPlatform } from '@snapka/browsers'
await uninstall({
browser: Browser.CHROME,
buildId: '120.0.6099.109',
platform: detectBrowserPlatform(),
cacheDir: './browsers',
})Cache 类
管理浏览器缓存目录。
class Cache {
constructor(cacheDir: string)
getInstalledBrowsers(): InstalledBrowser[]
clear(): void
}示例:
import { Cache } from '@snapka/browsers'
const cache = new Cache('./browsers')
// 获取已安装的浏览器
const browsers = cache.getInstalledBrowsers()
console.log('已安装:', browsers.length, '个浏览器')
// 清空缓存(删除所有已安装的浏览器)
cache.clear()工具函数
computeSystemExecutablePath()
获取系统已安装浏览器的路径(仅支持 Chrome)。
function computeSystemExecutablePath(options: SystemOptions): string
interface SystemOptions {
browser: Browser
channel: ChromeReleaseChannel
platform: BrowserPlatform
}示例:
import { Browser, ChromeReleaseChannel, computeSystemExecutablePath, detectBrowserPlatform } from '@snapka/browsers'
const systemChromePath = computeSystemExecutablePath({
browser: Browser.CHROME,
channel: ChromeReleaseChannel.STABLE,
platform: detectBrowserPlatform(),
})getVersionComparator()
获取浏览器版本比较函数(用于排序)。
function getVersionComparator(browser: Browser): (a: string, b: string) => number示例:
import { Browser, getVersionComparator } from '@snapka/browsers'
const versions = ['120.0.6099.109', '119.0.6045.105', '121.0.6167.85']
const comparator = getVersionComparator(Browser.CHROME)
const sorted = versions.sort(comparator)
console.log(sorted) // ['119.0.6045.105', '120.0.6099.109', '121.0.6167.85']getDownloadUrl()
获取浏览器下载 URL。
function getDownloadUrl(
browser: Browser,
platform: BrowserPlatform,
buildId: string,
baseUrl?: string
): URL示例:
import { Browser, getDownloadUrl, detectBrowserPlatform } from '@snapka/browsers'
const url = getDownloadUrl(
Browser.CHROME,
detectBrowserPlatform(),
'120.0.6099.109'
)
console.log(url.toString())createProfile()
创建浏览器配置文件目录(仅支持 Firefox)。
function createProfile(browser: Browser, options: ProfileOptions): Promise<void>
interface ProfileOptions {
path?: string
}probeUrls()
URL 探针,返回第一个符合状态码条件的 URL。
function probeUrls(
urls: (URL | string)[],
options?: {
validStatusCodes?: number[]
timeout?: number
}
): Promise<string>参数:
urls- 要检测的 URL 列表options- (可选)配置选项validStatusCodes- 有效的状态码数组,默认[200]timeout- 超时时间(毫秒),默认5000
返回: 第一个成功的 URL,如果全部失败则抛出错误
示例:
import { probeUrls } from '@snapka/browsers'
// 使用默认配置(状态码 200,超时 5 秒)
const fastestUrl = await probeUrls([
'https://registry.npmmirror.com/-/binary/chromium-browser-snapshots',
'https://storage.googleapis.com/chromium-browser-snapshots',
'https://example.com/mirror'
])
// 自定义状态码和超时
const fastestUrl = await probeUrls(
['url1', 'url2', 'url3'],
{
validStatusCodes: [200, 301, 302],
timeout: 10000
}
)工作原理:
- 同时向所有 URL 发起 HEAD 请求
- 返回第一个符合状态码条件的 URL
- 使用
Promise.any,只要有一个成功就立即返回 - 所有 URL 都失败时抛出错误
🌍 代理与镜像配置
使用代理
设置环境变量:
export HTTP_PROXY=http://proxy.example.com:8080
export HTTPS_PROXY=http://proxy.example.com:8080
npx @snapka/browsers install chrome在 Windows PowerShell 中:
$env:HTTP_PROXY="http://proxy.example.com:8080"
$env:HTTPS_PROXY="http://proxy.example.com:8080"
npx @snapka/browsers install chrome使用镜像源
CLI 方式:
npx @snapka/browsers install chrome --base-url https://npm.taobao.org/mirrorsNode.js API 方式:
await install({
browser: Browser.CHROME,
buildId,
platform,
cacheDir: './browsers',
baseUrl: 'https://npm.taobao.org/mirrors',
})💡 实用示例
在 CI/CD 中使用
# GitHub Actions 示例
name: E2E Tests
on: [push]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
- name: Cache browsers
uses: actions/cache@v3
with:
path: ./.browsers
key: browsers-${{ runner.os }}-${{ hashFiles('**/package-lock.json') }}
- name: Install dependencies
run: npm ci
- name: Install Chrome
run: npx @snapka/browsers install chrome@stable --path ./.browsers
- name: Run tests
run: npm test与 Puppeteer 集成
import puppeteer from 'puppeteer-core'
import {
Browser,
install,
resolveBuildId,
detectBrowserPlatform,
computeExecutablePath,
} from '@snapka/browsers'
async function setupBrowser() {
const platform = detectBrowserPlatform()
const buildId = await resolveBuildId(Browser.CHROME, platform, 'stable')
await install({
browser: Browser.CHROME,
buildId,
platform,
cacheDir: './.browsers',
downloadProgressCallback: 'default',
})
const executablePath = computeExecutablePath({
browser: Browser.CHROME,
buildId,
platform,
cacheDir: './.browsers',
})
return await puppeteer.launch({
executablePath,
headless: true,
args: ['--no-sandbox', '--disable-setuid-sandbox'],
})
}
const browser = await setupBrowser()
const page = await browser.newPage()
await page.goto('https://example.com')
await browser.close()下载多个浏览器
import {
Browser,
install,
resolveBuildId,
detectBrowserPlatform,
} from '@snapka/browsers'
async function installMultipleBrowsers() {
const platform = detectBrowserPlatform()
const cacheDir = './browsers'
const browsers = [
{ browser: Browser.CHROME, tag: 'stable' },
{ browser: Browser.FIREFOX, tag: 'stable' },
{ browser: Browser.CHROMEDRIVER, tag: 'stable' },
]
for (const { browser, tag } of browsers) {
console.log(`正在安装 ${browser}@${tag}...`)
const buildId = await resolveBuildId(browser, platform, tag)
await install({
browser,
buildId,
platform,
cacheDir,
downloadProgressCallback: 'default',
})
console.log(`✓ ${browser}@${buildId} 安装完成`)
}
}
await installMultipleBrowsers()❓ 常见问题
如何指定具体的 Chrome 版本?
# 使用完整版本号
npx @snapka/browsers install [email protected]
# 使用主版本号(会自动解析为该主版本的最新构建)
npx @snapka/browsers install chrome@120如何在不同平台上安装浏览器?
# 为 macOS (Intel) 安装
npx @snapka/browsers install chrome@stable --platform mac
# 为 macOS (Apple Silicon) 安装
npx @snapka/browsers install chrome@stable --platform mac-arm
# 为 Linux 安装
npx @snapka/browsers install chrome@stable --platform linux
# 为 Windows 64位 安装
npx @snapka/browsers install chrome@stable --platform win64如何清理旧版本浏览器?
import { Cache, uninstall } from '@snapka/browsers'
const cache = new Cache('./browsers')
const installed = cache.getInstalledBrowsers()
// 按版本排序,保留最新的 3 个版本
const chromes = installed
.filter(b => b.browser === 'chrome')
.sort((a, b) => b.buildId.localeCompare(a.buildId))
// 删除旧版本
for (const browser of chromes.slice(3)) {
await uninstall({
browser: browser.browser,
buildId: browser.buildId,
platform: browser.platform,
cacheDir: browser.cacheDir,
})
}下载失败怎么办?
- 检查网络连接
- 尝试使用代理或镜像源
- 检查磁盘空间是否充足
- 使用
canDownload()函数检查该版本是否可用
const available = await canDownload({
browser: Browser.CHROME,
buildId: '120.0.6099.109',
platform: detectBrowserPlatform(),
cacheDir: './browsers',
})
if (!available) {
console.error('该版本不可用')
}📄 许可证
Apache-2.0(与 Puppeteer 上游一致)
🔗 相关链接
提示: 在 CI 环境中,建议缓存浏览器下载目录以加快构建速度。默认缓存目录为当前工作目录,可通过 --path 或 API 的 cacheDir 参数自定义。
