概要
- パフォーマンスメトリクスのAPIを有効化する
- setTimeout ループで FMP取得まで待つ
コード
npm install -S puppeteer
fmp.js
const puppeteer = require('puppeteer')
async function getPerformanceMetrics(page) {
const { metrics } = await page._client.send('Performance.getMetrics')
return metrics.reduce((acc, i) => ({ ...acc, [i.name]: i.value }), {})
}
async function waitForFMP(page) {
let doneMet = null
while (true) {
const data = await getPerformanceMetrics(page)
if (data.FirstMeaningfulPaint !== 0) {
doneMet = data
break
}
await new Promise(resolve => setTimeout(resolve, 300))
}
return doneMet
}
async function run(url) {
const browser = await puppeteer.launch()
const page = await browser.newPage()
await page._client.send('Performance.enable')
await page.goto(url)
const m = await waitForFMP(page)
console.log(
`${url}: ${~~((m.FirstMeaningfulPaint - m.NavigationStart) * 1000)}ms`
)
browser.close()
}
;(async () => {
await run('https://google.com')
await run('https://qiita.com')
await run('https://github.com')
await run('https://twitter.com/mizchi')
await run('https://r.nikkei.com')
await run('https://yahoo.co.jp')
await run('https://www.rakuten.co.jp/')
})()
ターゲットはそれっぽいサイトを適当に選びました。
$ node fmp.js
https://google.com: 669ms
https://qiita.com: 723ms
https://github.com: 1089ms
https://twitter.com/mizchi: 992ms
https://r.nikkei.com: 849ms
https://yahoo.co.jp: 618ms
https://www.rakuten.co.jp/: 452ms
async/await と object-rest-spread 使ってるのでたぶん node 8.x じゃないと動かないです。
これたぶんUnixtime で返ってて Timestamp からの差分だと思うけど自信はない。
おまけ: 取得できる内部パラメータ
今回は getPerformanceMetrics の FirstMeaningfullPaint だけ使いましたが、内部的にはこんなパラメータが取れています。
export type Metrics = {
Timestamp: number,
AudioHandlers: number,
Documents: number,
Frames: number,
JSEventListeners: number,
LayoutObjects: number,
MediaKeySessions: number,
MediaKeys: number,
Nodes: number,
Resources: number,
ScriptPromises: number,
SuspendableObjects: number,
V8PerContextDatas: number,
WorkerGlobalScopes: number,
UACSSResources: number,
LayoutCount: number,
RecalcStyleCount: number,
LayoutDuration: number,
RecalcStyleDuration: number,
ScriptDuration: number,
TaskDuration: number,
JSHeapUsedSize: number,
JSHeapTotalSize: number,
FirstMeaningfulPaint: number,
DomContentLoaded: number,
NavigationStart: number
}
TaskDuration がJSの実行やCSSのLayoutにかかった時間の合計で、ここらへんも参考になります。