最近在使用lighthouse和puppeteer进行一些性能测试相关的工作,感觉puppeteer还是很好用的,下面简单介绍一下puppeteer的使用
概念
Headless Chrome
- 是一种在无界面的环境中运行 Chrome,与正常Chrome的区别
- 直接通过命令行或者程序语言操作
- 没有界面,少了加载 css/js、渲染页面的工作,比真实浏览器更快,更稳定
- 在启动 Chrome 时添加参数 --headless,便可以 headless 模式启动 Chrome
Puppeteer
- 是 Node.js 工具引擎
- 是 Chrome Developer Protocol 的上层封装
- 提供了高级API来通过DevTools协议控制Chrome或Chromium
- 默认是headless,可通过参数配置调出界面
Puppeteer可以做什么
- 生成页面的屏幕截图和PDF。(包括滚动元素的全屏截图)
- 爬取SPA(单页应用程序)并生成预渲染的内容(即“ SSR”(服务器端渲染))。
- 自动进行表单提交,UI测试,键盘输入等。
- 创建最新的自动化测试环境。使用最新的JavaScript和浏览器功能,直接在最新版本的Chrome中运行测试。
- 捕获站点的时间线跟踪,以帮助诊断性能问题。
- 测试Chrome扩展程序。
文档资源
API
结合API文档使用
Browser: 对应一个浏览器实例
BrowserContext: 对应浏览器一个上下文会话
Page:表示一个 Tab 页面
Frame: 一个框架
ExecutionContext: javascript 的执行环境
ElementHandle: 对应 DOM 的一个元素节点
JsHandle:对应 DOM 中的 javascript 对象CDPSession:可以直接与原生的 CDP 进行通信
Coverage:获取 JavaScript 和 CSS 代码覆盖率
Tracing:抓取性能数据进行分析
Response: 页面收到的响应
Request: 页面发出的请求
Puppeteer-Recoder
- 可以直接记录与浏览器进行交互,生成Puppeteer脚本。
- 可以在chrome中添加插件直接使用
- 缺点:无法记录滚动操作
点击record开始记录 | 生成代码可直接运行 |
---|---|
一些简单的例子
网页截图功能
const puppeteer = require('puppeteer');
(async () => {
// 生成browser实例
const browser = await puppeteer.launch();
// 解析一个新的页面。页面是在默认浏览器上下文创建的
const page = await browser.newPage();
// 设置网页大小
await page.setViewport({ width: 1000, height: 500 });
// 跳转到 https://example.com, 这里可以增加一些参数配置
await page.goto('https://example.com');
// 生成图片
await page.screenshot({path: 'example.png'});
// 生成pdf
await page.pdf({path: 'page.pdf'});
await browser.close();
})();
如果想调出界面
const browserConfig = {
headless: false
};
const browser = await puppeteer.launch(browserConfig);
如果想截图滚动元素
// 针对滚动元素截屏
async function scrollElementShot(page, selectorName, outputPath) {
// 选中滚动元素
const scrollableSectionEl = await page.waitForSelector(selectorName);
// 获取滚动元素参数
const bounding_box = await scrollableSectionEl.boundingBox();
await scrollableSectionEl.screenshot({
path: outputPath,
clip: bounding_box
});
}
如果设置不同网络状态
// 一些网络状态
const NETWORK_PRESETS = {
// 所有速度 / 8 是因为网络速度通常以比特/秒,而 DevTools 预计吞吐量在字节/秒! (1字节 = 8比特)
GPRS: {
offline: false, // 是否连接
downloadThroughput: (50 * 1024) / 8, // 模拟下载速度
uploadThroughput: (20 * 1024) / 8, // 模拟上传速度
latency: 500 // 模拟延迟(毫秒)
},
Regular2G: {
offline: false,
downloadThroughput: (250 * 1024) / 8,
uploadThroughput: (50 * 1024) / 8,
latency: 300
},
};
async function setNet(network, page) {
// 添加网络环境
if (network !== 'default') {
// Connect to Chrome DevTools
await page._client.send('Network.emulateNetworkConditions', NETWORK_PRESETS[network]);
}
}
const page = await browser.newPage();
// 添加网络环境
// Connect to Chrome DevTools
await page._client.send('Network.emulateNetworkConditions', NETWORK_PRESETS['GPRS']);
如果设置不同GPUThrottling
await page._client.send('Emulation.setCPUThrottlingRate', { rate: 4 });
一些时间节点判断API
// 等待3s
await page.waitForTimeout(3000);
// 等待某个元素出现
await page.waitForSelector('div > .m-tabwrap');
// 等待某个条件项
await page.waitForFunction('window.innerWidth < 100');
性能分析相关API
- tracing,生成的json文件可直接拖入ChromeDevTools的performance面板中查看
await page.tracing.start({path: 'trace.json', screenshots: true});
await page.click('div > .m-tabwrap > .m-tab > li:nth-child(3) > a');
await page.waitForTimeout(3000);
await page.screenshot({
path: 'demo1.png'
});
await page.tracing.stop();
- 通过 page.getMetrics() 可以得到一些页面性能数据
const metrics = await page.metrics();
<!--Timestamp The timestamp when the metrics sample was taken.-->
<!--Documents 页面文档数-->
<!--Frames 页面 frame 数-->
<!--JSEventListeners 页面内事件监听器数-->
<!--Nodes 页面 DOM 节点数-->
<!--LayoutCount 页面 layout 数-->
<!--RecalcStyleCount 样式重算数-->
<!--LayoutDuration 页面 layout 时间-->
<!--RecalcStyleDuration 样式重算时长-->
<!--ScriptDuration script 时间-->
<!--TaskDuration 所有浏览器任务时长-->
<!--JSHeapUsedSize JavaScript 占用堆大小-->
<!--JSHeapTotalSize JavaScript 堆总量-->
更多
更多示例可参考官方示例库