react-pdf
react-pdf copied to clipboard
Performance problem with creating multiple pages
Describe the bug I tried to create multiple pages pdf in web worker, and found that the speeds decreased significantly as the number increased.
Graphs of speed and data count:
Data count | Time (s) | Speeds (count / time) |
---|---|---|
10 | 0.85 | 11.76 |
30 | 0.95 | 21 |
50 | 0.89 | 56 |
100 | 1.42 | 70.42 |
200 | 2.66 | 75.18 |
300 | 4.78 | 62 |
500 | 10.42 | 50 |
800 | 23.76 | 34.7 |
1000 | 36.1 | 27 |
1500 | 84.8 | 17 |
2000 | 146.1 | 13 |
2500 | 225.36 | 11 |
3000 | 625.8 | 4.8 |
4000 | 1030 | 3.8 |
To Reproduce
Use the online demo to check the problem.
Click on different buttons to see different speeds.
Expected behavior Expect to generate at a constant rate, or faster on multiple pages.
Desktop (please complete the following information):
- OS: MacOS
- Browser: Chrome
- React-pdf version : 3.1.13
From my experience, using a dynamic component is what increases render times. For example, in your <Footer />
component https://stackblitz.com/edit/vite-react-ts-5wmsap?file=src%2Fcomponents%2FFooter.tsx%3AL54. This dynamic component with make react-pdf re-render a large document multiple times as it chunks out the pages and sets the values in each instance of the footer (this is also because of the fixed
prop).
I don't think there is a clean way around it unfortunately.
I'm constantly trying to enhance performance, but PDF generation is not cheap and layout computation either. I can leave this open but there's no obvious solution we havent done already
Curious about this. I have used useMemo
hook to only render the <Document/>
once but it still seems to make the UI laggy. Would it be possible to use a Worker somehow, not blocking the UI thread while doing PDF calculations in the worker?
Curious about this. I have used
useMemo
hook to only render the<Document/>
once but it still seems to make the UI laggy. Would it be possible to use a Worker somehow, not blocking the UI thread while doing PDF calculations in the worker?
Yes, the documentation says this. On our project we did this until we transferred the entire render to the server.
Thanks, found it
If you need to render documents with 30 pages or more in the browser, using react-pdf directly in React can occupy the browser's main thread for a long time. This can lead to unresponsive UI and browsers offering the user to abort the script. To avoid this, you should render large documents inside a web worker. Web workers are executed in separate threads, and therefore do not block the main thread of the browser. This way, the UI can stay responsive while the PDF is being rendered. For an example on how to run react-pdf in a web worker, see this blog post.