Задать вопрос

Как сделать «снимок в pdf» страницы react-spa-приложения корректно?

На клиенте используется react-приложение с клиентским рендерингом.
На сервере реализован обработки маршрута на nodejs express с логикой генерации страницы в pdf-файл при помощи puppeteer.

Проблема в том, что в pdf попадет только 1-я страница документа и выглядит она так, как будто в pdf сохраняется только видимая область.
Пробовал таким образом страницу кинопоиска сфоткать - всё ок, в pdf попадает документ целиком, в pdf-е это всё разбито страниц на 15. Но в pdf моего приложения попадает только один лист страницы. Вся остальная часть после скролла обрезается.
Есть предположение, что проблема связана с реализацией react-компонентов (виртуальные скроллы, бесконечные списки, графики на canvas и т.д.).

Помогите, пож-та, с корректной реализацией.
const express = require("express");
const morgan = require("morgan");
const cors = require("cors");
const puppeteer = require("puppeteer");

const app = express();
const PORT = process.env.PORT || 3005;

const printPdf = async (projectId, reportName) => {
  const browser = await puppeteer.launch({
    headless: true
  });

  const page = await browser.newPage();

  page.setViewport({
    width: 1920,
    height: 1080
  });

  page.goto(
    `http://localhost:3000/project/${projectId}/report/${reportName}`,
    { waitUntil: "networkidle2" }
  );

  await page.waitForNavigation();
  await page.type("#username", process.env.USERNAME);
  await page.type("#password", process.env.PASSWORD);
  await page.click("#submit");
  await page.waitForSelector(".content", { visible: true });

  const pdfFile = await page.pdf({
    format: "A4",
    printBackground: true
  });

  await browser.close();

  return pdfFile;
};

app.use(cors());
app.use(morgan("combined"));

app.get("/export", function(req, res) {
  const { projectId, reportName } = req.query;

  printPdf(projectId, reportName)
    .then(pdf => {
      res.set({
        "Content-Type": "application/pdf",
        "Content-Length": pdf.length
      });

      res.send(pdf);
    })
    .catch(error => {
      console.log("!!ERROR", error);
    });
});

app.listen(PORT, () => {
  console.log("Server running on port %d", PORT);
});
  • Вопрос задан
  • 146 просмотров
Подписаться 1 Сложный Комментировать
Пригласить эксперта
Ответы на вопрос 1
Aetae
@Aetae
Тлен
Не глядя можно сказать, что ваше приложение работает в режиме окна 100% на 100%, а все скроллы что есть - они где-то там внутри.
Полагаю height в setViewport нужно задать по-больше, чтобы всё влезло.)
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы