为什么您的 Puppeteer 部署在 Vercel 上失败(以及如何修复)
在本地设置上运行网页抓取或屏幕截图工具通常会很顺利,直到需要部署为止。我最近在尝试启动我的产品时遇到了这个问题 脚本上 。 🚀 虽然一切都在我的本地计算机上完美运行,但 Vercel 部署不断返回错误: 。
这个错误可能会令人沮丧,特别是因为它在本地测试期间没有出现。该问题通常表明部署环境中缺少浏览器版本,或者配置错误 Puppeteer 在 Vercel 上使用的。
默认情况下,Vercel 并不总是包含 Puppeteer 所需的特定 Chrome 可执行文件,这意味着您的脚本在运行时可能找不到它。本指南将引导您了解发生此错误的原因以及解决该错误的一些策略。
无论您是刚接触 Puppeteer 的开发人员还是只是对部署进行故障排除,了解这些细微差别都可以节省您数小时的调试时间。 🛠️ 让我们深入研究该解决方案,让您的 Puppeteer 设置在 Vercel 上无缝运行。
命令 | 使用示例和详细说明 |
---|---|
puppeteer.launch({ ... }) | 此命令启动具有特定配置选项(例如ignoreHTTPSErrors 和executablePath)的Puppeteer 实例。这些选项通过设置 Chrome 可执行文件的确切位置并管理安全设置,帮助解决 Vercel 等部署平台上 Chrome 版本的错误。 |
executablePath | 在 puppeteer.launch 中使用时,executablePath 指定 Chrome 二进制文件的路径。设置此路径可确保 Puppeteer 在远程服务器上使用正确的 Chrome 版本,这在默认情况下可能不会安装 Chrome 的 Vercel 等无服务器环境中至关重要。 |
args: ['--no-sandbox', '--disable-setuid-sandbox'] | 这些标志会禁用 Chrome 的沙箱功能,而该功能对于 Puppeteer 在许多云托管提供商上运行是必需的。通常禁用沙箱以避免共享服务器上的权限错误,但由于安全隐患,应谨慎执行。 |
cacheDirectory | 在 Puppeteer 的配置文件中,cacheDirectory 设置浏览器缓存的自定义目录。这对 Vercel 特别有用,因为它允许您控制 Puppeteer 存储下载的 Chrome 二进制文件的位置,从而防止与缓存相关的错误。 |
await page.goto(url, { waitUntil: 'networkidle2' }) | 此命令加载 URL 并等待,直到不超过两个网络连接才认为页面已完全加载。 networkidle2 选项可确保在截取屏幕截图之前加载所有资源,使其成为捕获复杂页面的理想选择。 |
page.setViewport({ width: 1920, height: 1080 }) | 设置 Chrome 实例的视口尺寸,模拟指定尺寸的屏幕。这对于屏幕截图和视觉测试至关重要,因为它控制捕获的网页的外观。 |
path.join(__dirname, '..', 'public', fileName) | 该命令通过将当前目录与公共文件夹连接起来构建文件路径,创建一个用于存储屏幕截图的特定目录。这对于组织输出文件至关重要,尤其是在将屏幕截图路径返回给客户端时。 |
uuid() | 为每个屏幕截图生成唯一标识符,确保每个文件名都是唯一的并避免覆盖。此功能对于同时存储多个图像或数据文件的应用程序特别有用。 |
chai.request(app) | 作为 Chai HTTP 模块的一部分,此命令向应用程序服务器(定义为 app)发送请求以测试端点响应。这对于自动化测试很有用,允许开发人员验证屏幕截图 API 是否按预期工作。 |
describe() and it() | 这些 Mocha 测试函数定义了用于验证功能的测试套件 (describe()) 和单独的测试 (it())。它们用于确认 Puppeteer 屏幕截图 API 的各个方面在各种条件下(从缺少参数到有效 URL)都能正确运行。 |
克服 Vercel 部署时 Puppeteer 的 Chrome 错误
提供的主要脚本是一个后端函数,它使用 捕获用户提供的 URL 的屏幕截图。此任务对于动态生成预览或网页抓取特别有用。但是,部署到像这样的平台 可能会导致错误,例如在环境中找不到 Chrome。发生这种情况是因为 Vercel 未在预期位置预安装 Chrome,这意味着必须配置 Puppeteer 才能找到或安装正确的版本。在我们的示例中,我们实现了一些选项来指定 Puppeteer 到自定义 Chrome 二进制文件的可执行路径,并使用ignoreHTTPSErrors 标志处理 SSL 问题,以确保设置可以跨环境运行。
该脚本首先定义从请求中获取 URL 的屏幕截图函数。如果 URL 丢失,它会发回 JSON 错误响应,但如果提供,它会使用必要的配置初始化 Puppeteer,例如 和 选项。这 此处至关重要,因为它将 Puppeteer 定向到确切的 Chrome 位置,从而解决 Vercel 上的“无法找到 Chrome”错误。此外, 参数 选项,特别是 和 ,禁用 Chrome 的沙盒功能,这是某些无服务器环境的要求。这些设置可确保脚本执行时不会遇到 Vercel 托管基础架构上的权限问题。
一旦 Puppeteer 启动,脚本将打开一个新的浏览器页面并使用 与 选项。这告诉 Puppeteer 等待页面完全加载,并且正在进行的网络请求不超过两个,确保即使是复杂的页面也能在截屏之前完全呈现。此步骤对于捕获可靠、准确的屏幕截图至关重要,尤其是在处理通常严重依赖异步加载的现代网页时。然后将视口大小设置为 1920x1080,模拟全高清屏幕,这保证捕获的内容反映大多数用户在桌面设备上看到的布局。
最后,该脚本使用以下命令生成一个唯一的文件名 库,将屏幕截图存储在公共目录中,可以在其中访问它并将其作为 JSON 响应返回给用户。通过使用 Node 仔细构建文件路径 方法,该脚本避免了由于环境设置差异而可能出现的文件路径问题。例如,虽然此结构在本地计算机上无缝运行,但相同的路径可能无法在 Vercel 上运行,因此以模块化且适应性强的方式定义每个文件路径至关重要。最终,此设置可确保 Puppeteer 功能在本地和无服务器环境中顺利运行,处理页面加载、错误处理和环境约束等所有关键方面。 🖥️
解决方案 1:配置 Puppeteer 以在 Vercel 上正确安装 Chrome
这个基于 Node.js 的后端解决方案配置 Puppeteer 的缓存路径和安装命令,以确保 Chrome 正确安装。
const puppeteer = require('puppeteer');
const path = require('path');
const { v4: uuid } = require('uuid');
const fs = require('fs');
// Main screenshot function
const screenshot = async (req, res) => {
const url = req.query.url;
if (!url) {
return res.status(400).json({ message: 'URL is required' });
}
let browser;
try {
// Launch Puppeteer with specific Chrome executable path and options
browser = await puppeteer.launch({
ignoreHTTPSErrors: true,
executablePath: process.env.CHROME_PATH || '/opt/bin/chromium',
args: ['--no-sandbox', '--disable-setuid-sandbox']
});
const page = await browser.newPage();
await page.goto(url, { waitUntil: 'networkidle2' });
await page.setViewport({ width: 1920, height: 1080 });
const fileName = \`${uuid()}.png\`;
const screenshotPath = path.join(__dirname, '..', 'public', fileName);
await page.screenshot({ path: screenshotPath });
res.json({ screenshotPath: \`/image/\${fileName}\` });
} catch (err) {
console.error('Error capturing screenshot:', err);
res.status(500).json({ error: 'Failed to capture screenshot' });
} finally {
if (browser) await browser.close();
}
};
module.exports = screenshot;
解决方案 2:使用 .puppeteerrc.cjs 文件为 Vercel 自定义 Puppeteer 配置
该解决方案调整 Puppeteer 的配置文件 (.puppeteerrc.cjs) 以指定 Chrome 缓存路径并确保与 Vercel 的文件结构兼容。
const { join } = require('path');
/
* @type {import('puppeteer').Configuration}
*/
module.exports = {
// Specify cache directory for Puppeteer
cacheDirectory: join(__dirname, '.cache', 'puppeteer'),
// Specify which Chromium version Puppeteer should install
executablePath: '/opt/bin/chromium',
args: ['--no-sandbox', '--disable-setuid-sandbox'],
};
解决方案 3:在 package.json 中为 Puppeteer 实现环境变量和脚本
该方法修改了 包.json 文件来安装特定的 Chrome 二进制文件并在部署期间自动设置 Puppeteer 配置。
// Add to package.json
"scripts": {
"postinstall": "npx puppeteer install --path ./.cache/puppeteer",
"start": "node index.js"
}
// Configure environment variable in Vercel
process.env.CHROME_PATH = "/opt/bin/chromium";
Puppeteer 屏幕截图功能的单元测试
此 Node.js Mocha 测试脚本验证了 Puppeteer 在各种环境中从 URL 捕获屏幕截图的能力。
const chai = require('chai');
const chaiHttp = require('chai-http');
const app = require('../app'); // Express app where screenshot endpoint is defined
chai.use(chaiHttp);
const expect = chai.expect;
describe('Screenshot API', () => {
it('should return an error for missing URL parameter', (done) => {
chai.request(app)
.get('/screenshot')
.end((err, res) => {
expect(res).to.have.status(400);
expect(res.body).to.have.property('message').eql('URL is required');
done();
});
});
it('should capture a screenshot successfully for a valid URL', (done) => {
chai.request(app)
.get('/screenshot?url=https://example.com')
.end((err, res) => {
expect(res).to.have.status(200);
expect(res.body).to.have.property('screenshotPath');
done();
});
});
});
针对云环境优化 Puppeteer
将基于 Puppeteer 的应用程序部署到云平台时,例如 或者 ,了解这些环境的局限性至关重要。与本地设置不同,云环境通常在托管或无服务器架构上运行,这意味着 Chrome 等依赖项并不总是可用。事实上,木偶师的 如果服务器上未安装所需的 Chrome 版本,该方法可能会失败,从而导致“无法找到 Chrome”之类的错误。一个好的做法是使用以下命令指定 Chrome 的可执行路径 executablePath,因为这确保 Puppeteer 可以在任何环境中有效地定位和启动 Chrome。
除此之外,添加必要的启动参数对于兼容性至关重要。标志如 和 特别有帮助。虽然这些标志会禁用 Chrome 的某些安全功能,但对于不支持 Chrome 沙箱的无服务器设置来说,它们通常是必需的。此外,使用 Puppeteer 指定自定义缓存目录 选项有助于防止潜在的缓存问题,尤其是在涉及多个浏览器版本时。例如,设置 cacheDirectory 到已知目录可确保所有依赖项在运行时可用。
最后,优化 方法可以大大提高性能。通过使用 选项,脚本等待页面完成加载,这对于互联网速度或资源加载变化的环境至关重要。这对于在异步加载内容的动态页面或应用程序中捕获准确的屏幕截图特别有用。这些技术的结合使 Puppeteer 能够在云平台上无缝运行,为生产中的自动化任务提供强大的解决方案。 🚀
- 为什么我在云平台上收到“无法找到 Chrome”错误?
- 这些错误经常发生是因为云平台默认不包含完整的 Chrome 二进制文件。您可以通过指定来修复此问题 在你的 Puppeteer 设置中。
- 如何确保 Puppeteer 在本地和云环境中都能正常工作?
- 使用 和 带有云友好标志,例如 可以使您的设置对于这两种环境都足够灵活。
- 什么是 Flag 在 Puppeteer 中做什么?
- 这 flag 会禁用 Chrome 的沙箱安全性,这使得 Puppeteer 可以在不支持沙箱的云服务上运行,但应谨慎使用。
- 为什么我需要定制 对于傀儡师?
- 设置自定义 确保 Puppeteer 将 Chrome 二进制文件下载到已知位置,这可以防止部署期间出现错误,尤其是在无服务器环境中。
- 目的是什么 选项中的 方法?
- 这 选项会等待,直到活动网络连接不超过两个。这对于捕获完全加载的页面和处理动态内容非常有用。
- Puppeteer 可以在没有指定 Chrome 版本的情况下工作吗?
- 是的,但建议指定 并确保可访问兼容的 Chrome 版本,以在云设置中获得一致的结果。
- 如何跨不同环境管理 Puppeteer 缓存?
- 您可以指定一个通用的 在 文件,允许 Puppeteer 跨 Vercel 和 Heroku 等平台查找 Chrome 二进制文件。
- 是 不同于 ?
- 是的, 排除捆绑的 Chrome 以减小大小,因此您需要指定 Chrome 二进制文件。完整的 软件包自动包含 Chrome。
- 如果 Puppeteer 在云环境下运行缓慢怎么办?
- 优化 设置并禁用不需要的选项,例如 可以提高资源受限环境中的性能。
- Puppeteer 是否与所有云提供商兼容?
- 一般来说,是的,但每个提供商可能有独特的要求。使用云友好设置,例如 确保更好的兼容性。
在 Vercel 上成功部署 Puppeteer 需要了解 Chrome 的特定设置需求。指定 正确配置 Puppeteer 的缓存路径有助于防止令人沮丧的“无法找到 Chrome”错误。这些调整确保 Puppeteer 在本地和云环境中可靠地运行。 🚀
一旦您将这些解决方案应用到您的项目中,从用户提供的 URL 捕获屏幕截图就会变得无缝,从而实现更加动态的 Web 应用程序。通过正确的设置,Puppeteer 仍然是自动化和网页抓取的宝贵工具,即使在 Vercel 这样的无服务器平台上也是如此。
- 本文参考了官方 Puppeteer 配置指南,了解详细的设置选项和故障排除步骤,特别是处理 Chrome 缓存路径和指定可执行路径。 Puppeteer 配置指南
- Vercel 文档深入了解无服务器环境如何处理依赖项以及部署依赖于无头浏览器的应用程序的独特要求。 Vercel 文档
- Stack Overflow 讨论提供了社区驱动的解决方案和错误处理的实际示例,涵盖了部署期间遇到的特定 Puppeteer 和 Chrome 问题。 堆栈溢出