Skip to content

Instantly share code, notes, and snippets.

@charisTheo
Last active February 15, 2024 15:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save charisTheo/ac1cb68a1502e4116000c292b3da7f06 to your computer and use it in GitHub Desktop.
Save charisTheo/ac1cb68a1502e4116000c292b3da7f06 to your computer and use it in GitHub Desktop.
npm init -y && npm i puppeteer && node index.js
import puppeteer from 'puppeteer';
const browser = await puppeteer.launch({
headless: false,
args: [
'--window-size=1818,1328',
"--no-sandbox",
"--disable-setuid-sandbox",
"--disable-dev-shm-usage",
"--disable-accelerated-2d-canvas",
"--no-first-run",
"--no-zygote",
"--disable-gpu",
'--deterministic-fetch',
'--disable-features=IsolateOrigins',
'--disable-site-isolation-trials',
],
defaultViewport: {
width: 1818,
height: 1328,
deviceScaleFactor: 1,
isMobile: false,
hasTouch: false,
isLandscape: false
}
})
const page = await browser.newPage()
const TEST_PRERENDER = true
async function delay(milliseconds) {
return await new Promise(res => setTimeout(() => res(true), milliseconds))
}
await Promise.all([
page.goto(`https://www.farfetch.com/${TEST_PRERENDER ? 'fr' : 'uk'}/sets/most-wanted-pieces.aspx`),
page.waitForNavigation()
])
async function getProductCardCoordinates(page) {
return await page.evaluate(() => {
const productCardClientRects = document
.querySelector('li[data-testid="productCard"]:nth-child(1) a[data-component="ProductCardLink"]')
.getClientRects()[0]
return {
left: productCardClientRects.left,
top: productCardClientRects.top
}
})
}
async function hoverOverProductLinks(page) {
const productCardClientRects = await getProductCardCoordinates(page)
var x = Number(productCardClientRects.left + 10, 10)
var y = Number(productCardClientRects.top + 750, 10)
for (var i = 0; i <= 4; i++) {
await page.mouse.move(x, y, {steps: 200})
x += 300
await delay(1000)
}
}
async function getPrerenderedPathFromPage(page) {
if (!TEST_PRERENDER) {
return '/uk/shopping/men/amiri-stars-court-low-sneakers-item-22775645.aspx?storeid=9446'
}
const speculationRule = await page.evaluate(() => {
const speculationRules = document.querySelectorAll('script[type=speculationrules]')
if (!speculationRules?.length) return null
return JSON.parse(speculationRules?.[3]?.innerText || '')
})
return speculationRule ? speculationRule.prerender?.[0]?.urls?.[0] : null
}
await hoverOverProductLinks(page)
await delay(4000)
await hoverOverProductLinks(page)
await delay(4000)
const prerenderedPath = await getPrerenderedPathFromPage(page)
if (!prerenderedPath) {
console.log('❌ No prerendered page was found')
await browser.close()
process.exit(0)
}
await delay(4000)
await Promise.all([
page.click(`a[href='${prerenderedPath}']`),
page.waitForNavigation(),
])
const LCP = await page.evaluate(() => {
return new Promise(resolve => {
const getActivationStart = () => {
const navEntry = window.performance &&
performance.getEntriesByType &&
performance.getEntriesByType('navigation')[0]
return (navEntry && navEntry.activationStart) || 0;
};
new PerformanceObserver((entryList) => {
const entries = entryList.getEntries()
const lastEntry = entries[entries.length - 1]
resolve(
lastEntry
? Math.max(lastEntry.startTime - getActivationStart(), 0)
: null
)
}).observe({ type: 'largest-contentful-paint', buffered: true })
})
})
// https://developer.chrome.com/docs/web-platform/prerender-pages#detecting_prerender_in_javascript
const prerendered = await page.evaluate(() => {
return (
document.prerendering ||
self.performance?.getEntriesByType?.('navigation')[0]?.activationStart > 0
)
})
console.log('Prerendered:', prerendered)
console.log('LCP:', LCP)
await delay(2000)
await browser.close()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment