Skip to content

Instantly share code, notes, and snippets.

@addyosmani
Last active March 26, 2024 00:09
Show Gist options
  • Save addyosmani/c053f68aead473d7585b45c9e8dce31e to your computer and use it in GitHub Desktop.
Save addyosmani/c053f68aead473d7585b45c9e8dce31e to your computer and use it in GitHub Desktop.
Largest Contentful Paint - Puppeteer
const puppeteer = require('puppeteer');
const Good3G = {
'offline': false,
'downloadThroughput': 1.5 * 1024 * 1024 / 8,
'uploadThroughput': 750 * 1024 / 8,
'latency': 40
};
const phone = puppeteer.KnownDevices['Nexus 5X'];
function calcLCP() {
window.largestContentfulPaint = 0;
const observer = new PerformanceObserver((entryList) => {
const entries = entryList.getEntries();
const lastEntry = entries[entries.length - 1];
window.largestContentfulPaint = lastEntry.renderTime || lastEntry.loadTime;
});
observer.observe({ type: 'largest-contentful-paint', buffered: true });
document.addEventListener('visibilitychange', () => {
if (document.visibilityState === 'hidden') {
observer.takeRecords();
observer.disconnect();
console.log('LCP:', window.largestContentfulPaint);
}
});
}
async function getLCP(url) {
const browser = await puppeteer.launch({
args: ['--no-sandbox'],
timeout: 10000
});
try {
const page = await browser.newPage();
const client = await page.createCDPSession();
await client.send('Network.enable');
await client.send('ServiceWorker.enable');
await client.send('Network.emulateNetworkConditions', Good3G);
await client.send('Emulation.setCPUThrottlingRate', { rate: 4 });
await page.emulate(phone);
await page.evaluateOnNewDocument(calcLCP);
await page.goto(url, { waitUntil: 'load', timeout: 60000 });
let lcp = await page.evaluate(() => {
return window.largestContentfulPaint;
});
browser.close();
return lcp;
} catch (error) {
console.log(error);
browser.close();
}
}
getLCP("https://remix-clone-hacker-news.flameddd1.workers.dev/")
.then(lcp => console.log("LCP is: " + lcp));
@warpech
Copy link

warpech commented Aug 5, 2020

Hi Addy! This is very useful. Could you please add license information?

@flameddd
Copy link

Thanks for Addy.

Some API changed, updated code in below:

const puppeteer = require('puppeteer');

const Good3G = {
  'offline': false,
  'downloadThroughput': 1.5 * 1024 * 1024 / 8,
  'uploadThroughput': 750 * 1024 / 8,
  'latency': 40
};

const phone = puppeteer.KnownDevices['Nexus 5X'];

function calcLCP() {
  window.largestContentfulPaint = 0;

  const observer = new PerformanceObserver((entryList) => {
    const entries = entryList.getEntries();
    const lastEntry = entries[entries.length - 1];
    window.largestContentfulPaint = lastEntry.renderTime || lastEntry.loadTime;
  });

  observer.observe({ type: 'largest-contentful-paint', buffered: true });

  document.addEventListener('visibilitychange', () => {
    if (document.visibilityState === 'hidden') {
      observer.takeRecords();
      observer.disconnect();
      console.log('LCP:', window.largestContentfulPaint);
    }
  });
}

async function getLCP(url) {
  const browser = await puppeteer.launch({
    args: ['--no-sandbox'],
    timeout: 10000
  });

  try {
    const page = await browser.newPage();
    const client = await page.createCDPSession();

    await client.send('Network.enable');
    await client.send('ServiceWorker.enable');
    await client.send('Network.emulateNetworkConditions', Good3G);
    await client.send('Emulation.setCPUThrottlingRate', { rate: 4 });
    await page.emulate(phone);

    await page.evaluateOnNewDocument(calcLCP);
    await page.goto(url, { waitUntil: 'load', timeout: 60000 });

    let lcp = await page.evaluate(() => {
      return window.largestContentfulPaint;
    });

    browser.close();
    return lcp;

  } catch (error) {
    console.log(error);
    browser.close();
  }
}

getLCP("https://remix-clone-hacker-news.flameddd1.workers.dev/")
  .then(lcp => console.log("LCP is: " + lcp));

@addyosmani
Copy link
Author

Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment