Optimizing Performance in Our JavaScript PDF Viewer

The performance of a web application is extremely important for usability, as it directly affects the time it takes for a user to complete their task. PSPDFKit for Web’s performance can be influenced by three main factors:

  • The way PSPDFKit and the PDF are loaded in the browser

  • If the PDF is rendered in the browser or on the server

  • If PDFs are cached or rendered on the fly on the server

Browser Rendering vs. Server Rendering

There are two options for running PSPDFKit for Web:

While Standalone mode is easier to set up, its performance is inferior to a Server-Backed mode for the following reasons:

  1. Loading rendering code — In Standalone mode, PSPDFKit has to load the PDF rendering engine in the browser. More specifically, this rendering engine is the pspdfkit.wasm file, which is larger than 8 MB. When using a server, the rendering code stays on the server, and as a result, the browser doesn’t have to load it, meaning the overall loading time decreases.

  2. Loading the PDF — In Standalone mode, in order to display the PDF, PSPDFKit has to download the entire PDF file first before it can start to render it. With a server backend, the server takes care of the rendering, and PSPDFKit only loads the pages it needs intelligently. Therefore, pages can be displayed faster, which is especially helpful when it comes to large PDFs.

  3. Rendering the PDF — Rendering a PDF takes time. While in Standalone mode, the client is responsible for all jobs, including rendering. Meanwhile, with a server setup, the work is split between server and client. The client only needs to display the result of the potentially expensive rendering process that the server has already taken care of.

Using a server backend can improve performance, especially when:

  • Your PDF files are large.

  • You expect your users to access PDFs from a slow network connection, like on a mobile phone or in a rural area.

  • You expect your users to have low CPU performance, like on a mobile phone or on an old computer.

Server-Backed Performance

When using the PSPDFKit for Web Server-Backed operational mode, you might run into problems when too many PDF rendering requests hit a single server. To handle a multitude of requests, you can run an arbitrary number of PSPDFKit servers in parallel behind a load balancer.

Find out how to achieve this in our Horizontal Scaling guide.

Standalone Performance

The PSPDFKit for Web Standalone operational mode runs completely in the browser. It uses WebAssembly and falls back to plain JavaScript (asm.js) to render PDF files directly on the client. Our operational modes guide offers a comparison of the benefits of each solution.

Performance Considerations

WebAssembly is intermediate code that needs to be compiled in the browser. We use various advanced techniques to improve performance. See the Optimizing WebAssembly Startup Time blog post for more on this. Additionally, you can use our Real-World WebAssembly Benchmark to test the performance of your browser and OS.

Initial loading performance on modern machines is in the range of 3–9 seconds. Once the component is loaded, switching documents is nearly instant.

This table shows the average download time for the WebAssembly artifacts (~9 MB, ~3.7 MB gzipped) for different network conditions:

Network Speed (Mbit/s) Download Time (s) Download Time (s, gzipped)
Broadband 50 1.5 0.59
LTE 15 4.8 1.97
Fast 3G 6 12 4.93

Source for average speeds (Ofcom): Broadband (2018), Mobile (2014)

These figures apply only to the first time the page is loaded, as subsequent requests will be much faster since the browser cache will be used.

When ScrollMode.CONTINUOUS is set as ViewState#scrollMode, there are a certain number of pages of the document above and below the currently viewed one that PSPDFKit for Web keeps in memory at each moment. This is done to keep our memory footprint in check and to avoid slowing down scrolling performance, as more DOM nodes need to be retained. For this reason, on a document with many pages, switching back and forth between pages that are distant from each other requires rerendering them, and that could require some time.

The rerendering strategy on Standalone mode is different from a PSPDFKit for Web Server-Backed mode, where the different pages are stored on the browser’s network cache so that a repeated request for a page that was previously loaded can be resolved instantly.

Preloading and Prefetching

To improve load times within your application, we recommend using preload and prefetch in adequate scenarios: preloading pspdfkit.js for sites on which you wish to display PDF content using PSPDFKit, and prefetching on sites on which no PDF content is visible.

The preload attribute of the <link> tag causes your browser to start downloading the resource of the <link> tag earlier in the lifecycle of your page, which will improve the overall feel of your site, while the prefetch attribute is used to fetch the resources you predict a user is likely to request. See the HTML specification for more information.

The implementation of these will depend on how you’re importing pspdfkit.js on your site/application. If your service is a regular website using vanilla JavaScript, you can add <link rel="prefetch" href="path/to/pspdfkit.js"> or <link rel="preload" href="path/to/pspdfkit.js"> within the <head> of the pages in question.

For websites and applications using modern frameworks that use webpack for bundling, this can be done using the /* webpackPrefetch: true */ or /* webpackPreload: true */ comments within your import(). Webpack will use this information to generate the appropriate <link rel="prefetch" ...> or <link rel="preload" ...> tags for you. See the webpack documentation for more information.

WebAssembly Support

In 2017, all browsers started supporting WebAssembly (see WebAssembly: A New Hope), and since 2018 it’s been getting really fast.

Firefox’s new streaming and tiering compiler helps decrease even the initial loading time to around half of what other browsers require.

Update 20 August 2018: Google released Liftoff, a new baseline compiler for WebAssembly in V8. The blog post includes specific benchmarks for PSPDFKit, showing a 56%+ faster initialization time.

Preloading WebAssembly Artifacts

Standalone mode can make use of the PSPDFKit.preloadWorker function to fetch WebAssembly artifacts in advance so that when the actual document is loaded, they’re already available. This can greatly enhance the user experience by minimizing the time the user has to wait for these files to load.

If you don’t open a PDF document right away after loading PSPDFKit, consider boosting subsequent document loading time by using PSPDFKit.preloadWorker.

PSPDFKit is committed to being at the forefront of this innovative technology, and our goal is to make Standalone mode as fast as Server-Backed mode.

Caching

For optimal performance, it’s critical to implement a caching strategy that allows recurrent users to quickly interact with your app. You can even precache the resources way ahead of the actual point when the user needs them by using service workers.

Please check our Caching on the Web guide to learn more.