Puppeteer v19在GitHub Action中组件截图随机异常求助
Puppeteer v19在GitHub Action中批量截图随机渲染不完整问题解决
问题描述
本地环境用Puppeteer v19截图所有组件都正常,但在GitHub Action里循环截取30个组件时,会随机出现两种异常:
- 组件没完全展开,高度比实际尺寸小
- 组件元素没渲染全,比如该显示1、2、3,只截到1、2
本质是截图时机太早,组件还没彻底渲染完。
当前使用的Puppeteer启动代码:
await puppeteer.launch({ args: [ '--disable-gpu', '--disable-gpu-compositing', '--disable-gpu-rasterization', '--single-process', '--ignore-certifacate-errors', '--start-maximized', '--no-sandbox', '--enable-features=NetworkService' ], defaultviewport: null, headless: true, isMobile: true });
截图循环代码:
let components = await this.page.$$(selector); for(const [index, component] of components.entries()) { try { await component.screenshot({path: filepath, captureBeyondViewport: false}); } catch (e) { } }
解决方案
1. 等组件渲染稳定再截图
截图前加等待逻辑,确保组件尺寸、内容彻底稳定。可以等组件高度不再变化,或者等特定动态元素加载出来:
for(const [index, component] of components.entries()) { try { // 等待组件高度稳定(两次测量高度一致) await this.page.waitForFunction((el) => { const firstHeight = el.offsetHeight; return new Promise(resolve => { setTimeout(() => { resolve(el.offsetHeight === firstHeight); }, 300); }); }, {}, component); // 如果组件有动态加载的子元素,等它显示出来 await component.waitForSelector('.dynamic-child', { timeout: 5000, visible: true }); await component.screenshot({path: filepath, captureBeyondViewport: false}); } catch (e) { console.error(`第${index}个组件截图失败:`, e); } }
2. 调整Puppeteer启动参数
GitHub Action资源有限,当前参数可能限制了渲染能力,建议修改:
- 删掉
--single-process:单进程模式批量任务下容易资源不足,导致渲染滞后 - 修正拼写错误
--ignore-certifacate-errors为--ignore-certificate-errors - 把
headless: true改成headless: "chrome":v19默认的新headless模式在部分场景稳定性不如旧模式 - 添加
--disable-dev-shm-usage:解决GitHub Action里共享内存不足的问题
调整后的启动代码:
await puppeteer.launch({ args: [ '--disable-gpu', '--disable-gpu-compositing', '--disable-gpu-rasterization', '--ignore-certificate-errors', '--start-maximized', '--no-sandbox', '--enable-features=NetworkService', '--disable-dev-shm-usage' ], defaultViewport: null, headless: "chrome", isMobile: true });
3. 循环里加间隔,避免资源抢占
连续截图会让浏览器资源吃紧,每个组件截图前加短暂间隔,给浏览器留足渲染时间:
for(const [index, component] of components.entries()) { try { // 先确保组件已经渲染出高度 await component.waitForFunction(el => el.offsetHeight > 0, {}, component); // 加500ms间隔,缓解资源压力 await new Promise(resolve => setTimeout(resolve, 500)); await component.screenshot({path: filepath, captureBeyondViewport: false}); } catch (e) { console.error(`第${index}个组件截图失败:`, e); } }
4. 先等页面全局资源加载完再拿组件列表
获取组件前,先等页面所有资源加载完成,避免组件还没初始化就开始截图:
// 等网络空闲(没有请求在进行) await this.page.waitForLoadState('networkidle2'); // 或者等页面完全加载完成 // await this.page.waitForLoadState('load'); let components = await this.page.$$(selector);
内容的提问来源于stack exchange,提问作者ryan
相关产品推荐
相关产品推荐

