|
const fs = require("fs"); // https://github.com/nodejs/node/blob/master/doc/api/fs.md |
|
const puppeteer = require("puppeteer"); // https://github.com/puppeteer/puppeteer |
|
const chalkAnimation = require("chalk-animation"); // https://github.com/bokub/chalk-animation |
|
const { argv } = require("yargs"); // https://github.com/yargs/yargs |
|
|
|
// Function for parsing data from our list of urls to visit. |
|
function readURLFile(path) { |
|
return fs |
|
.readFileSync(path, "utf-8") |
|
.split("\n") |
|
.map((elt) => { |
|
const url = elt.replace("\r", ""); |
|
return `${url.toLowerCase()}`; |
|
}); |
|
} |
|
|
|
// Instantiate our browser and start hitting urls. |
|
(async () => { |
|
const startDate = new Date().getTime(); |
|
const USER_AGENT = |
|
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3239.108 Safari/537.36"; |
|
const urls = readURLFile("./cache-data.twig"); // <- List of urls, warm.sh fetches this using wget from the file you set up. |
|
const browser = await puppeteer.launch(); |
|
|
|
for (let url of urls) { |
|
const warmingAnimation = chalkAnimation.karaoke(`๐ Warming: ${url}`); |
|
|
|
let page = await browser.newPage(); |
|
await page.setUserAgent(USER_AGENT); |
|
|
|
try { |
|
// If user and pass arguments passed, submit authentication credentials |
|
if (argv.user && argv.pass) { |
|
// We need to authenticate |
|
await page.authenticate({ username: argv.user, password: argv.pass }); |
|
} |
|
|
|
await page.goto(url, { waitUntil: "networkidle2" }); // Wait for network traffic to stop. |
|
|
|
// Optional step if you have a modal or some GDPR consent that needs to be dismissed on the first or every page. |
|
try { |
|
await page.click("#elc-accept-all-link"); // <- Change this to the ID of the button or element that needs to be clicked to accept/dismiss cookie consent. etc |
|
// console.log("๐ช Accepting Cookies\n"); |
|
} catch (error) { |
|
// console.log("๐คญ Cookies Already Accepted\n") |
|
} |
|
|
|
await autoScroll(page); // Get to the bottom of it. |
|
await page.waitFor(2000, { waitUntil: "networkidle2" }); // Be like, super sure everything is loaded and css transitions have run their course. |
|
|
|
warmingAnimation.stop(); // Stop the warming animation |
|
warmingAnimation.f = `๐ Warming: ${url}`.length + 10; // Set the frame manually to [string length + 10] (this is a hack, thank you @bokub) |
|
warmingAnimation.render(); // Render one last frame |
|
chalkAnimation.rainbow(`๐ Success\n`); |
|
|
|
// Set the filename of our screenshot |
|
let fileName = url.replace(/(\.|\/|:|%|#)/g, "_"); |
|
if (fileName.length > 100) { |
|
fileName = fileName.substring(0, 100); |
|
} |
|
|
|
await page.screenshot({ |
|
path: `./cache/${fileName}.jpeg`, |
|
fullPage: true, |
|
}); |
|
} catch (err) { |
|
console.log(`๐ An error occured fetching ${url}`); |
|
} finally { |
|
await page.close(); |
|
} |
|
} |
|
|
|
await browser.close(); |
|
console.log( |
|
`Time elapsed: ${Math.round( |
|
(new Date().getTime() - startDate) / 1000 |
|
)} seconds.` |
|
); |
|
})(); |
|
|
|
// Function to make sure we trigger rendering of async loaded elements at the bottom of the page. |
|
async function autoScroll(page) { |
|
await page.evaluate(async () => { |
|
await new Promise((resolve, reject) => { |
|
var totalHeight = 0; |
|
var distance = 100; |
|
var timer = setInterval(() => { |
|
var scrollHeight = document.body.scrollHeight; |
|
window.scrollBy(0, distance); |
|
totalHeight += distance; |
|
|
|
if (totalHeight >= scrollHeight) { |
|
clearInterval(timer); |
|
resolve(); |
|
} |
|
}, 100); |
|
}); |
|
}); |
|
} |