最近在使用lighthouse和puppeteer進行一些性能測試相關的工作,感覺puppeteer還是很好用的翔怎,下面簡單介紹一下puppeteer的使用
概念
Headless Chrome
- 是一種在無界面的環(huán)境中運行 Chrome,與正常Chrome的區(qū)別
- 直接通過命令行或者程序語言操作
- 沒有界面,少了加載 css/js讳癌、渲染頁面的工作,比真實瀏覽器更快存皂,更穩(wěn)定
- 在啟動 Chrome 時添加參數(shù) --headless晌坤,便可以 headless 模式啟動 Chrome
Puppeteer
- 是 Node.js 工具引擎
- 是 Chrome Developer Protocol 的上層封裝
- 提供了高級API來通過DevTools協(xié)議控制Chrome或Chromium
- 默認是headless,可通過參數(shù)配置調出界面
Puppeteer可以做什么
- 生成頁面的屏幕截圖和PDF。(包括滾動元素的全屏截圖)
- 爬取SPA(單頁應用程序)并生成預渲染的內容(即“ SSR”(服務器端渲染))泡仗。
- 自動進行表單提交,UI測試猜憎,鍵盤輸入等娩怎。
- 創(chuàng)建最新的自動化測試環(huán)境。使用最新的JavaScript和瀏覽器功能胰柑,直接在最新版本的Chrome中運行測試截亦。
- 捕獲站點的時間線跟蹤,以幫助診斷性能問題柬讨。
- 測試Chrome擴展程序崩瓤。
文檔資源
API
結合API文檔使用
image.png
Browser: 對應一個瀏覽器實例
BrowserContext: 對應瀏覽器一個上下文會話
Page:表示一個 Tab 頁面
Frame: 一個框架
ExecutionContext: javascript 的執(zhí)行環(huán)境
ElementHandle: 對應 DOM 的一個元素節(jié)點
JsHandle:對應 DOM 中的 javascript 對象CDPSession:可以直接與原生的 CDP 進行通信
Coverage:獲取 JavaScript 和 CSS 代碼覆蓋率
Tracing:抓取性能數(shù)據(jù)進行分析
Response: 頁面收到的響應
Request: 頁面發(fā)出的請求
Puppeteer-Recoder
- 可以直接記錄與瀏覽器進行交互,生成Puppeteer腳本踩官。
- 可以在chrome中添加插件直接使用
- 缺點:無法記錄滾動操作
點擊record開始記錄 | 生成代碼可直接運行 |
---|---|
image.png
|
image.png
|
一些簡單的例子
網頁截圖功能
const puppeteer = require('puppeteer');
(async () => {
// 生成browser實例
const browser = await puppeteer.launch();
// 解析一個新的頁面却桶。頁面是在默認瀏覽器上下文創(chuàng)建的
const page = await browser.newPage();
// 設置網頁大小
await page.setViewport({ width: 1000, height: 500 });
// 跳轉到 https://example.com, 這里可以增加一些參數(shù)配置
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);
// 獲取滾動元素參數(shù)
const bounding_box = await scrollableSectionEl.boundingBox();
await scrollableSectionEl.screenshot({
path: outputPath,
clip: bounding_box
});
}
如果設置不同網絡狀態(tài)
// 一些網絡狀態(tài)
const NETWORK_PRESETS = {
// 所有速度 / 8 是因為網絡速度通常以比特/秒,而 DevTools 預計吞吐量在字節(jié)/秒! (1字節(jié) = 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) {
// 添加網絡環(huán)境
if (network !== 'default') {
// Connect to Chrome DevTools
await page._client.send('Network.emulateNetworkConditions', NETWORK_PRESETS[network]);
}
}
const page = await browser.newPage();
// 添加網絡環(huán)境
// Connect to Chrome DevTools
await page._client.send('Network.emulateNetworkConditions', NETWORK_PRESETS['GPRS']);
如果設置不同GPUThrottling
await page._client.send('Emulation.setCPUThrottlingRate', { rate: 4 });
一些時間節(jié)點判斷API
// 等待3s
await page.waitForTimeout(3000);
// 等待某個元素出現(xiàn)
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() 可以得到一些頁面性能數(shù)據(jù)
const metrics = await page.metrics();
<!--Timestamp The timestamp when the metrics sample was taken.-->
<!--Documents 頁面文檔數(shù)-->
<!--Frames 頁面 frame 數(shù)-->
<!--JSEventListeners 頁面內事件監(jiān)聽器數(shù)-->
<!--Nodes 頁面 DOM 節(jié)點數(shù)-->
<!--LayoutCount 頁面 layout 數(shù)-->
<!--RecalcStyleCount 樣式重算數(shù)-->
<!--LayoutDuration 頁面 layout 時間-->
<!--RecalcStyleDuration 樣式重算時長-->
<!--ScriptDuration script 時間-->
<!--TaskDuration 所有瀏覽器任務時長-->
<!--JSHeapUsedSize JavaScript 占用堆大小-->
<!--JSHeapTotalSize JavaScript 堆總量-->
更多
更多示例可參考官方示例庫