2

I am building a personal scraper using the chromedp package. I would like to get my FCP(First Contentful Paint) and other stats. Unfortunately I am unable to find a way to do this, then I got the idea of extracting it from the developer console.

Unfortunately I am unable to find any tutorials on the internet after two days of fiddling around with it.

Can anyone tell me please how I can measure the FCP and other metrics with chromedp?

I tried this but it returns an error: encountered an undefined value. But when I type it into my browser's console it actually does work.

chromedp.EvaluateAsDevTools("const paintTimings = performance.getEntriesByType('paint');", nil),
chromedp.EvaluateAsDevTools("const fmp = paintTimings.find(({ name }) => name === \"first-contentful-paint\");", nil),
chromedp.EvaluateAsDevTools("console.log('First contentful paint at foo');", &jscript))

I figured out that the problem I have is, that when a console.log is executed devtools also returns a undefined which collides with what Go expects. Does anyone know how to fix this?

Zeke Lu
  • 6,349
  • 1
  • 17
  • 23

1 Answers1

1

I don't understand how FCP is measured. I will provide a demo that works from the perspective of chromedp below.

It would be better to use the cdp Performance domain and/or the cdp PerformanceTimeline domain, but as what I said before, I don't know FCP and I don't know how to use them.

package main

import (
    "context"
    "encoding/json"
    "log"

    "github.com/chromedp/chromedp"
)

type performancePaintTiming struct {
    EntryType string  `json:"entryType"`
    Name      string  `json:"name"`
    Duration  int     `json:"duration"`
    StartTime float64 `json:"startTime"`
}

func main() {
    ctx, cancel := chromedp.NewContext(context.Background(),
        // Enable the debug mode to see the CDP messages.
        // It's helpful to understand how CDP works.
        // But please don't enable it in Production Environment.
        chromedp.WithDebugf(log.Printf))
    defer cancel()

    // I don't know why but it seems that Runtime.evaluate does not return
    // JSON object any more, so I have to stringified it into a string.
    js := `
const paintTimings = performance.getEntriesByType('paint');
const fcp = paintTimings.find(({ name }) => name === "first-contentful-paint");
JSON.stringify(fcp);`

    var res string
    if err := chromedp.Run(ctx,
        chromedp.Navigate("https://www.bing.com/"),
        chromedp.EvaluateAsDevTools(js, &res),
    ); err != nil {
        panic(err)
    }

    var fcp performancePaintTiming
    if err := json.Unmarshal([]byte(res), &fcp); err != nil {
        panic(err)
    }

    log.Printf("%#v", fcp)
}

References:

Zeke Lu
  • 6,349
  • 1
  • 17
  • 23