browserless 对于延迟加载图片的处理

日常中大家为了提高web的性能基于可见区的图片加载基本常见,但是对于基于puppeteer的快照以及pdf生成就不太方便了,以下是一个解决方法,核心是过去内容的高度,基于代码进行滚动,模拟人的操作实现资源的加载

参考实现

const express = require("express");
const puppeteer = require("puppeteer-core");
 
const app = express();
 
const browserWSEndpoint = process.env.ENDPOINT || "ws://localhost:3000";
 
const getBrowser = async () => puppeteer.connect({ browserWSEndpoint });
 
app.get("/image", async (req, res) => {
  let browser = null;
  const website = req.query.website;
  await getBrowser()
    .then(async (browser) => {
      const page = await browser.newPage();
      await page.setViewport({ width: 1280, height: 1024 });
      await page.goto(website, {
        waitUntil: ["load", "networkidle0"],
      });
      const bodyHandle = await page.$("body");
      const { height } = await bodyHandle.boundingBox();
      console.log("height", height);
      await bodyHandle.dispose();
 
      // Scroll one viewport at a time, pausing to let content load
      const viewportHeight = page.viewport().height;
      console.log("viewportHeight", viewportHeight);
      let viewportIncr = 0;
      while (viewportIncr + viewportHeight < height) {
        await page.evaluate((_viewportHeight) => {
          console.log("scrolling", _viewportHeight);
          window.scrollBy(0, _viewportHeight);
        }, viewportHeight);
        await wait(20);
        viewportIncr = viewportIncr + viewportHeight;
      }
 
      // Scroll back to top
      await page.evaluate((_) => {
        window.scrollTo(0, 0);
      });
      await wait(100)
      const screenshot = await page.screenshot({
        fullPage: true,
        captureBeyondViewport: true,
      });
      res.end(screenshot, "binary");
    })
    .catch((error) => {
      if (!res.headersSent) {
        res.status(400).send(error.message);
      }
    })
    .finally(() => browser && browser.close());
});
 
function wait (ms) {
  return new Promise(resolve => setTimeout(() => resolve(), ms));
}
 
app.get("/pdf", async (req, res) => {
  let browser = null;
  const website = req.query.website;
  await getBrowser()
    .then(async (browser) => {
      const page = await browser.newPage();
      await page.setViewport({ width: 1280, height: 1024 });
      await page.goto(website, {
        waitUntil: ["load", "networkidle0"],
      });
      const bodyHandle = await page.$("body");
      const { height } = await bodyHandle.boundingBox();
      console.log("height", height);
      await bodyHandle.dispose();
 
      // Scroll one viewport at a time, pausing to let content load
      const viewportHeight = page.viewport().height;
      console.log("viewportHeight", viewportHeight);
      let viewportIncr = 0;
      while (viewportIncr + viewportHeight < height) {
        await page.evaluate((_viewportHeight) => {
          console.log("scrolling", _viewportHeight);
          window.scrollBy(0, _viewportHeight);
        }, viewportHeight);
        await wait(20);
        viewportIncr = viewportIncr + viewportHeight;
      }
 
      // Scroll back to top
      await page.evaluate((_) => {
        window.scrollTo(0, 0);
      });
      await wait(100);
      const screenshot = await page.pdf({
        displayHeaderFooter: true,
        format: "A4",
        printBackground: true,
      });
      res.end(screenshot, "binary");
    })
    .catch((error) => {
      if (!res.headersSent) {
        res.status(400).send(error.message);
      }
    })
    .finally(() => browser && browser.close());
});
 
app.listen(8080, () => console.log("Listening on PORT: 8080"));

说明

以上是基于滚动,以及延迟处理的,实际可能还需要结合实际调整,不能确保没问题

参考资料

https://wiki.zegnat.net/cache/?md5=f7ce4fd73de0ac41f15ea708b4c8f20f

posted on 2024-04-18 11:48  荣锋亮  阅读(6)  评论(0编辑  收藏  举报

导航