Web Caching for Our JavaScript PDF Viewer

To let your users experience a fast PDF viewer, the loading performance of assets — especially your PDF files — is critical. In this guide, you’ll learn how to make your assets load fast and how to cache them for a long time.

gzip and Brotli

All modern browsers support gzipped content. This allows your server to deliver a compressed version of your assets with a reduced file size. The browser will take care of uncompressing the assets as soon as it has received them.

Many web servers, like Apache or Nginx, can gzip responses automatically right before they get sent to the client. However, unless your assets are created dynamically for every request, an even smarter solution is to create gzipped versions of your assets when you deploy them.

Tools like webpack offer plugins to gzip your assets at build time. Once you deploy them, make sure your server sends the gzipped version of the file if the user’s browser supports it. In this case, the user’s browser will send the following header with the request:

Accept-encoding: gzip, deflate

An even better compression method for your assets is Brotli. With Brotli, you can achieve a 20-percent decrease in file size in comparison to gzip. However, Brotli is not as well supported by browsers as gzip is. If a browser supports Brotli, it will include it in its Accept-encoding header:

Accept-encoding: gzip, br

There’s also a webpack plugin that compresses your assets with Brotli at build time.

Long Caching

Ideally, everything required to load PSPDFKit should be loaded in the browser before a user even enters a page that displays a PDF.

When using PSPDFKit in Standalone mode, this applies especially to the pspdfkit.js and pspdfkit.wasm files, which are large.

Once your users have downloaded your assets, you should make sure they don’t have to download them again every time they need them. The easiest and most efficient way to do this is to tell the browser to cache your assets for a long time and to give them a unique path that changes whenever the asset’s content changes.

In this way, the browser only needs to download an asset once and can serve further requests for the same assets from the browser cache. When an asset changes, tell the browser about the new path, for example by passing the new path in PSPDFKit’s document option. Once the browser has downloaded the changed file, it will serve it from the cache again for a long time.

To tell the browser to keep your assets for a certain time without fetching them again, pass the following HTTP header along with the asset response:

Cache-Control: max-age=8640000

This tells the browser to keep your asset in its cache for up to 100 days (100 _ 24 _ 60 * 60 = 8640000 seconds).

Inspecting Asset Loading

In Your Browser’s Dev Tools

To check if your assets are delivered with the correct encoding and headers, you can use your browser’s dev tools. In this example, we’ll use Chrome’s dev tools, but you’ll find similar tools in every modern browser.

Bookmark bar

You can see above that the PDF was served with a Cache-Control header, which prevents refetching when you access the same file again within one day.

The browser also states that it supports gzip compression, but apparently the server can’t deliver a gzipped version; otherwise, there would be the response header Content-Encoding: gzip. To improve loading performance of the PDF, you should configure the server to deliver a gzipped version.

Using cURL

You can also use cURL to send an HTTP request and check the response headers. For instance, if you want to check that the pspdfkit.wasm file is being served with proper caching and compression response headers, you can try the following:

curl 'https://example.com/pspdfkit-lib/pspdfkit-9709cb17eadf2572.wasm' \
-I \
-X GET \
-H "accept-encoding: gzip, deflate, br"

A response might then look like this:

HTTP/1.1 200 OK
Content-Type: application/wasm
Content-Length: 3035090
Connection: keep-alive
vary: Accept-Encoding
cache-control: public, max-age=31536000
accept-ranges: bytes
content-encoding: br
Access-Control-Allow-Origin: *

Notice the presence of both the cache-control and content-encoding HTTP response headers — just like what can be seen in the example in the previous section.

Precaching on the Browser

Using service workers, you can intercept fetch requests from the browser and return cached versions of the requested assets instead of going through the network.

Service workers have many nice features — among them, the ability to add files to the browser cache when the service worker is installing. This feature is called precaching.

An easy solution to implement precaching is using the Workbox library. Workbox not only precaches assets, but it also takes care of both loading a newer version when something has changed and removing old versions from the cache. This way, your browser cache is used more efficiently than it is with HTTP caching.

You’ll find all the details relevant to this in the Workbox precaching guide.

If you’re using webpack, there’s a Workbox webpack plugin. This will precache all files of your webpack build by default. If you only want to precache the PSPDFKit assets, you can set a limit in the plugin configuration:

new Workbox.GenerateSW({
  include: ["pspdfkit.js", "pspdfkit.wasm"]
});

Caching is a comprehensive topic and we’ve barely scratched the surface here. If you want to learn more, check out the Google and Mozilla guides on HTTP caching.

Content Delivery Network

If you serve customers all around the world, you should consider using a Content Delivery Network (CDN). CDNs store your assets on several servers in different parts of the world. Your CDN will make sure your users always receive content from the closest available server. This reduces latency and download speed, and it takes the load away from your production server, which will no longer have to serve the assets.

An additional benefit of CDNs is the high availability of your content: Should one server become unreachable, your content can still be delivered from another available server.

Typically, CDNs let you configure the caching headers your assets are delivered with, and you can also provide a gzipped version of your files, which gets served automatically if the user’s browser supports it.

For more information on how to set up caching with your CDN of choice, check out the following links:

Caching on Server-Backed

PSPDFKit for Web Server-Backed caches rendered pages in memory to speed up future rendering. When you run into server performance issues, increasing the server’s memory will keep more pages in the cache, leading to faster page loads on average.

For a multi-server setup, you can use Redis to cache pages that have been rendered by an arbitrary server, and a server can even access a cached page created by another server.

For more details on this, see the server caching guide.