使用Puppeteer在Lambda生成PDF时出现浏览器断开导航失败错误
Puppeteer在Lambda中生成带图片的PDF时触发浏览器断开错误
我们基于Puppeteer开发了一个Lambda函数,用于将HTML内容转换为PDF文件,依赖包为chrome-aws-lambda@8.0.2和puppeteer-core@8.0.0。在QA环境中,当HTML不含图片时PDF生成正常,但只要包含图片(无论是background-image还是<img>标签),就会触发Puppeteer错误。目前已将Lambda的临时存储和内存调至最大值10240MB,问题仍未解决。
依赖安装命令:
npm install chrome-aws-lambda@8.0.2 puppeteer-core@8.0.0 --save-prod
异常信息
{ "errorMessage": "Navigation failed because browser has disconnected!", "stack": [ "Error: Navigation failed because browser has disconnected!", " at /var/task/node_modules/puppeteer-core/lib/cjs/puppeteer/common/LifecycleWatcher.js:51:147", " at /var/task/node_modules/puppeteer-core/lib/cjs/vendor/mitt/src/index.js:51:62", " at Array.map (<anonymous>)", " at Object.emit (/var/task/node_modules/puppeteer-core/lib/cjs/vendor/mitt/src/index.js:51:43)", " at CDPSession.emit (/var/task/node_modules/puppeteer-core/lib/cjs/puppeteer/common/EventEmitter.js:72:22)", " at CDPSession._onClosed (/var/task/node_modules/puppeteer-core/lib/cjs/puppeteer/common/Connection.js:247:14)", " at Connection._onClose (/var/task/node_modules/puppeteer-core/lib/cjs/puppeteer/common/Connection.js:128:21)", " at WebSocket.<anonymous> (/var/task/node_modules/puppeteer-core/lib/cjs/puppeteer/node/NodeWebSocketTransport.js:17:30)", " at WebSocket.onClose (/var/task/node_modules/ws/lib/event-target.js:124:16)", " at WebSocket.emit (events.js:400:28)" ] }
代码片段
async function getBrowser() { if (puppeteer) { return await puppeteer.launch({ headless: true }); } // if running in lambda return chromium lambda if (chromium) { return await chromium.puppeteer.launch({ args: chromium.args, defaultViewport: chromium.defaultViewport, executablePath: await chromium.executablePath, headless: chromium.headless, ignoreHTTPSErrors: true }); } } export const html2pdf = async (html = '', url = '', format = 'Legal') => { let myBrowser = await getBrowser(); const page = await myBrowser.newPage(); const loaded = page.waitForNavigation({ waitUntil: 'load' }); if (html) { await page.setContent(html, { waitUntil: 'networkidle0' }); } else if (url) { await page.goto(url, { waitUntil: 'networkidle0' }); } // await page.setViewport({ isMobile: true, width: 375, height: 667 }); await loaded; const pdf = await page.pdf({ format: format }); await page.close(); await myBrowser.close(); return pdf; };
解决方案与调试建议
1. 修复waitForNavigation的错误使用
代码中提前声明loaded = page.waitForNavigation(...),但page.setContent或page.goto本身已包含导航等待逻辑,再单独await loaded会导致逻辑冲突——导航已完成后waitForNavigation会超时,最终引发浏览器连接断开。
修改后的代码:
export const html2pdf = async (html = '', url = '', format = 'Legal') => { let myBrowser = await getBrowser(); const page = await myBrowser.newPage(); if (html) { await page.setContent(html, { waitUntil: 'networkidle0' }); } else if (url) { await page.goto(url, { waitUntil: 'networkidle0' }); } const pdf = await page.pdf({ format: format }); await page.close(); await myBrowser.close(); return pdf; };
2. 优化Chromium启动参数适配Lambda环境
在getBrowser的Chromium配置中补充关键参数,避免资源耗尽或连接异常:
return await chromium.puppeteer.launch({ args: [ ...chromium.args, '--disable-dev-shm-usage', // 禁用Lambda空间有限的/dev/shm '--disable-gpu', '--single-process', // 单进程模式减少资源占用 '--no-zygote' // 避免zygote进程兼容性问题 ], defaultViewport: chromium.defaultViewport, executablePath: await chromium.executablePath, headless: chromium.headless, ignoreHTTPSErrors: true, timeout: 0 // 取消启动超时限制,适配大资源加载场景 });
3. 处理图片加载超时与异常
图片加载慢或失败可能导致页面挂起,进而断开浏览器连接:
- 给
page.setContent/page.goto增加超时时间:await page.setContent(html, { waitUntil: 'networkidle0', timeout: 30000 }); // 30秒超时 - 监听页面错误与请求失败事件,定位具体图片问题:
page.on('error', err => console.error('页面错误:', err)); page.on('requestfailed', req => console.error('请求失败:', req.url(), req.failure()));
4. 升级依赖版本
当前使用的chrome-aws-lambda@8.0.2和puppeteer-core@8.0.0版本较旧,存在已知的Lambda适配问题。建议升级到兼容的稳定版本(注意两者大版本需一致):
npm install chrome-aws-lambda@10.1.0 puppeteer-core@10.1.0 --save-prod
5. 验证Lambda执行环境配置
- 确认Lambda运行时为Node.js 14.x及以上,旧版本可能不兼容新版Chromium
- 将Lambda执行时间限制设为最大值5分钟,避免大图片加载时超时
内容的提问来源于stack exchange,提问作者codeflinger
相关产品推荐
相关产品推荐

