Skip to content

JsPdf is saving a pdf but takes too long time to show it in google chrome #3137

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
stounej opened this issue Apr 19, 2021 · 20 comments
Open

Comments

@stounej
Copy link

stounej commented Apr 19, 2021

I'm using JsPDF to download an html styled element, but when it is downloaded, it takes too long to be showed in google chrome as pdf (shows just an empty pdf document at first and charge it after long time),

the size of the file is only 300KB, I don't know why I have this problem however it's showed correctly in mozilla firefox browser

Please do you know how could I solve this problem.

this is my code

generatePDF = () => {
var doc = new jsPDF('p','pt',"a4");
const inp = document.getElementById("cv");
doc.html( inp , {
html2canvas: {
scale: 0.75,
},
callback: function (doc) {
var pageCount = doc.internal.getNumberOfPages();
doc.deletePage(pageCount)
doc.save("download.pdf");
}
});
}

this is the pdf file:
downloaded.pdf

@HackbrettXXX
Copy link
Collaborator

Please attach the PDF document.

@stounej
Copy link
Author

stounej commented Apr 20, 2021

I have edited my post and included the pdf document, this is the code rendered in the pdf document:

import` '../App.css;
import personalInfo from '../Contexts/personalInfo';
import Grid from '@material-ui/core/Grid';
import {Typography} from '@material-ui/core';
import clsx from 'clsx';
import {makeStyles} from '@material-ui/core/styles';

const useStyles = makeStyles({
  paragraphes: {
    fontSize: "12px",
    overflow: "hidden",
    whiteSpace: "pre-wrap"
  },
  Typography: {
    textAlign: "center"
  },
  title: {
    fontSize: "20px",
    marginTop: "45px",
    textAlign: "center",
    fontFamily: "bold",
    backgroundColor: "#96b0bc",
    color: "white"
  },
  dates: {
    marginTop: "40px",
    fontSize: "12px",
    marginLeft: "13px"
  },
  h4: {
    fontSize: "15px",
    fontWeight: "bold",
    marginBottom: "8px",
    marginTop: "10px"
  }
});

//width: "21cm",height:"29.7cm"{width: "248.0px",height:"350.8px"
function PaperA4() {
  const classes = useStyles();
  return (
    <div class="page" data-size="A4" id="cv">
      <personalInfo.Consumer>
        {({
          fullname,
          email,
          phone,
          address,
          zip,
          city,
          country,
          driving,
          status,
          nationality
        }) => (
          <Grid container xs={12} direction="column" justify="center">
            <Grid
              item
              xs={12}
              justify="center"
              alignItems="center"
              style={{
              lineHeight: "5px",
              marginTop: "20px"
            }}>
              <Typography align="center" variant="h5">{fullname}</Typography>
            </Grid>
            <Grid item xs={12}>
              <Typography className={clsx(classes.Typography, classes.paragraphes)}>
                {email}&nbsp; {phone}&nbsp; {address}
                &nbsp; &nbsp; {city}
                &nbsp; {country}
                &nbsp; {nationality}
                &nbsp; {status}
                &nbsp; {zip}
                &nbsp;{driving}
              </Typography>
            </Grid>

          </Grid>
        )}
      </personalInfo.Consumer>
      <Grid container xs={12} direction="column" justify="center">
        <Typography className={classes.title} variant="h5">Professional Experience
        </Typography>
        <personalInfo.Consumer>
          {({experience}) => (experience.map((exp, i) => {
            return (
              <div key={i}>
                <Grid container xs={12} spacing={false}>
                  <Grid xs={3}>
                    <Typography className={classes.dates}>
                      {exp.startdate}-{exp.enddate}<br/> {exp.city},{exp.country}
                    </Typography>
                  </Grid>
                  <Grid xs={8}>
                    <Typography className={classes.paragraphes}>
                      <Typography className={classes.h4}>
                        {exp.job}
                        <br/> {exp.employer}
                      </Typography>
                      {exp.description}
                    </Typography>
                  </Grid>
                </Grid>
              </div>

            )
          }))}
        </personalInfo.Consumer>
      </Grid>
      <Typography className={classes.title} variant="h5">Education
      </Typography>
      <personalInfo.Consumer>
        {({education}) => (education.map((edu, i) => {
          return (
            <div key={i}>
              <Grid container xs={12} spacing={false}>
                <Grid xs={3}>
                  <Typography className={classes.dates}>
                    {edu.startdate}-{edu.enddate}<br/> {edu.city},{edu.country}
                  </Typography>
                </Grid>
                <Grid xs={8}>
                  <Typography className={classes.h4}>
                    {edu.degree}
                    <br/> {edu.school}
                  </Typography>
                  <Typography className={classes.paragraphes}>
                    {edu.description}
                  </Typography>
                </Grid>
              </Grid>
            </div>

          )
        }))}
      </personalInfo.Consumer>

    </div>

  );
}

export default PaperA4;`

@HackbrettXXX
Copy link
Collaborator

The performance issue seems to be that each letter is written as a single chunk of text. Why that is, I don't know, yet.

@stounej
Copy link
Author

stounej commented Apr 22, 2021

I tried to transform the document to an Image before saving it and it worked but the text inside the pdf can't be copied,
I need the text to be copyable.

@KurtGokhan
Copy link
Contributor

KurtGokhan commented Jul 26, 2021

Seems like if there is letter-spacing in CSS, this will happen. Here is the workaround I am using to remove letter-spacing for PDF:

        onclone: async (d: HTMLDocument) => {
          const styleSheet = `
            * {
              letter-spacing: initial !important;
            }
          `;
          const style = document.createElement('style');
          style.innerText = styleSheet;
          d.head.appendChild(style);
        }

@kevinmelo
Copy link

Any return? have the same issue

@KurtGokhan
Copy link
Contributor

In addition to letter-spacing, too many words can also cause this issue. When letter-spacing is not 0, each letter is rendered separately. But when it is 0, html2canvas renders each word separately and that still makes the PDF size grow too much and cause performance problems.

I created this PR in html2canvas which significantly improves the performance by rendering multiple words in a line together.

@CollenZhou
Copy link

I have the same problem. The pdf generated from html is loaded very slow by chrome and edge and scrolling is choppy.

@DanLopess
Copy link

Hi, @KurtGokhan I've tried the mentioned solution of removing the letter-spacing but it made no difference. The PDF is still extremely choppy on chromium browsers (e.g. Edge is a chromium browser).

@KurtGokhan
Copy link
Contributor

@DanLopess

In addition to letter-spacing, too many words can also cause this issue.

One workaround I found is to render the text to an image, and print that into PDF. But text will not be selectable in the PDF if you do that.

@DanLopess
Copy link

@KurtGokhan Yeah unfortunately that wouldn't be ideal. However if I did that, since my HTML converts into multiple pages the image would have to be split (still haven't figured out how to do that) and I would have to calculate how many pages would be needed.

@CollenZhou
Copy link

Hi dear authors any update?

@CollenZhou
Copy link

Hi, just FYI. I noticed if a single table cell contains too much text will cause the performance issue. Hope it helps.

@github-actions
Copy link

github-actions bot commented Apr 8, 2022

This issue is stale because it has been open 90 days with no activity. It will be closed soon. Please comment/reopen if this issue is still relevant.

@prasheel888
Copy link

Also having the same issue, Any Suggestions guys??

@kevinmelo
Copy link

Also having the same issue, Any Suggestions guys??

At the end the best solution was using Puppeeter with my nodejs backend

@prasheel888
Copy link

Also having the same issue, Any Suggestions guys??

At the end the best solution was using Puppeeter with my nodejs backend

Thanks For Suggestion!!

@haaah
Copy link

haaah commented Jan 3, 2024

trying @KurtGokhan css hack does improve the rendering speed a little but when there's Word Starting With Upper Case it will sometimes join 2 word together --> WordWord.

Is there any other workaround ?

@adamturski
Copy link

adamturski commented Feb 28, 2024

In my case generated PDF was loading fine in Ubuntu Document Viewer, but not in Chrome PDF viewer. Rendering was slow for some pages, visible especially on scrolling (but also on load if I put problematic element on first page). I could narrow down the issue to border-radius style on my table element. If text was short then there was no issue, but for long texts it was loading very long (forever). I set border-radius to 0 on my table container class and problem disappeared. I do not know why is that.
I also played with letter-spacing style and set 0 globally, but it helped just a little I would say - finally border-radius solved the issue.

Html:

<div id="exported-content">
        <div class="table-container">
        <table>
            <tr>
                <td>Test</td>
                <td>
                    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla nec purus feugiat, molestie ipsum et, consequat nibh. Etiam non elit dui. Nullam vel eros sit amet arcu vestibulum accumsan in in leo. Fusce malesuada vulputate faucibus. Integer in hendrerit nisi. Praesent a hendrerit urna. In non imperdiet elit, sed molestie odio. Etiam auctor sit amet odio et luctus. Quisque in massa a libero luctus suscipit. Cras metus purus, iaculis ut aliquam non, varius quis nibh. Quisque a interdum augue. Nam ut nibh mauris.
                    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla nec purus feugiat, molestie ipsum et, consequat nibh. Etiam non elit dui. Nullam vel eros sit amet arcu vestibulum accumsan in in leo. Fusce malesuada vulputate faucibus. Integer in hendrerit nisi. Praesent a hendrerit urna. In non imperdiet elit, sed molestie odio. Etiam auctor sit amet odio et luctus. Quisque in massa a libero luctus suscipit. Cras metus purus, iaculis ut aliquam non, varius quis nibh. Quisque a interdum augue. Nam ut nibh mauris.
                    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla nec purus feugiat, molestie ipsum et, consequat nibh. Etiam non elit dui. Nullam vel eros sit amet arcu vestibulum accumsan in in leo. Fusce malesuada vulputate faucibus. Integer in hendrerit nisi. Praesent a hendrerit urna. In non imperdiet elit, sed molestie odio. Etiam auctor sit amet odio et luctus. Quisque in massa a libero luctus suscipit. Cras metus purus, iaculis ut aliquam non, varius quis nibh. Quisque a interdum augue. Nam ut nibh mauris.
                    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla nec purus feugiat, molestie ipsum et, consequat nibh. Etiam non elit dui. Nullam vel eros sit amet arcu vestibulum accumsan in in leo. Fusce malesuada vulputate faucibus. Integer in hendrerit nisi. Praesent a hendrerit urna. In non imperdiet elit, sed molestie odio. Etiam auctor sit amet odio et luctus. Quisque in massa a libero luctus suscipit. Cras metus purus, iaculis ut aliquam non, varius quis nibh. Quisque a interdum augue. Nam ut nibh mauris.
                    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla nec purus feugiat, molestie ipsum et, consequat nibh. Etiam non elit dui. Nullam vel eros sit amet arcu vestibulum accumsan in in leo. Fusce malesuada vulputate faucibus. Integer in hendrerit nisi. Praesent a hendrerit urna. In non imperdiet elit, sed molestie odio. Etiam auctor sit amet odio et luctus. Quisque in massa a libero luctus suscipit. Cras metus purus, iaculis ut aliquam non, varius quis nibh. Quisque a interdum augue. Nam ut nibh mauris.
                    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla nec purus feugiat, molestie ipsum et, consequat nibh. Etiam non elit dui. Nullam vel eros sit amet arcu vestibulum accumsan in in leo. Fusce malesuada vulputate faucibus. Integer in hendrerit nisi. Praesent a hendrerit urna. In non imperdiet elit, sed molestie odio. Etiam auctor sit amet odio et luctus. Quisque in massa a libero luctus suscipit. Cras metus purus, iaculis ut aliquam non, varius quis nibh. Quisque a interdum augue. Nam ut nibh mauris.
                </td>
            </tr>
        </table>
        </div>
 </div>

Css:

.table-container {
    border-radius: 8px !important; // !!! This line was causing an issue with rendering PDF in Chrome.
    overflow: hidden;
    background-color: white;
}

JS:

new jsPDF({
            orientation: 'p',
            unit: 'mm',
            format: this.paperFormat,
            putOnlyUsedFonts: true,
            compress: true,
        }).html(document.getElementById('exported-content'), {
            html2canvas: {
                async: true,
                letterRendering: false,
                logging: true,
                removeContainer: true,
            },
            callback: (doc) => {
                doc.save("test.pdf");
            },
            margin: [15, 15, 15, 15],
            autoPaging: true,
            width: 180,
            windowWidth: 1080,
        });

@Amatewasu
Copy link

@adamturski Thank you for the update. I just tested and I reproduce that removing the border radius in my generated pdf make them way faster in chrome.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

10 participants