Skip to content

Instantly share code, notes, and snippets.

@demostanis
Created February 5, 2025 15:52
Show Gist options
  • Save demostanis/18fdaeb0b7ee8a53281cdf416be92f69 to your computer and use it in GitHub Desktop.
Save demostanis/18fdaeb0b7ee8a53281cdf416be92f69 to your computer and use it in GitHub Desktop.
import puppeteer from "puppeteer";
import imagemin from "imagemin";
import imageminWebp from "imagemin-webp";
import Fontmin from "fontmin";
import pino from "pino";
if (process.argv.length < 3) {
console.error("usage: node main.js url");
process.exit(1);
}
const logger = pino();
const readBody = (type, response, page) => {
return new Promise(async resolve => {
const url = response.url();
const mime = response.headers()["content-type"];
logger.debug({ url, mime }, "found " + type);
try {
resolve(await response.buffer());
} catch (err) {
logger.warn({ url, mime, err }, "failed to fetch " + type);
resolve(null);
}
});
}
const imageHandler = async (type, response, page) => {
const raw = await readBody(type, response, page);
if (!raw) return;
const compressed = await imagemin.buffer(raw, {
plugins: [
imageminWebp()
]
});
if (raw.length > compressed.length) {
const savedBytes = raw.length-compressed.length
logger.info({ url: response.url(), savedBytes }, "compressed image");
// TODO: stream to the backend
}
}
const fontHandler = async (type, response, page) => {
const raw = await readBody(type, response, page);
if (!raw) return;
const fontmin = new Fontmin()
.use(new Fontmin.ttf2woff2())
.src(raw);
const results = await fontmin.runAsync();
if (results.length > 1) {
const compressed = results.reduce((a, b) =>
a._contents.length < b._contents.length ?
a._contents : b._contents)
if (raw.length > compressed.length) {
const savedBytes = raw.length-compressed.length
logger.info({ url: response.url(), savedBytes }, "compressed font");
// TODO: stream to the backend
}
}
}
const resourceHandlers = {"image": imageHandler, "font": fontHandler};
logger.info("opening browser...");
const browser = await puppeteer.launch();
const page = await browser.newPage();
while (process.argv.length != 2) {
const url = process.argv[2];
page.on("response", response => {
const type = response.request().resourceType();
resourceHandlers[type]?.(type, response, page);
});
logger.info({ url }, "navigating");
try {
await page.goto(url);
} catch {
logger.error({ url }, "invalid url");
}
process.argv.splice(2, 1);
}
//await browser.close();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment