Last active
February 15, 2024 15:53
-
-
Save charisTheo/ac1cb68a1502e4116000c292b3da7f06 to your computer and use it in GitHub Desktop.
npm init -y && npm i puppeteer && node index.js
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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