Optimizing performance in the Nutrient JavaScript PDF viewer
Web application performance directly affects the time it takes for a user to complete their task. Nutrient Web SDK’s performance is influenced by three main factors:
- The way Nutrient Web SDK and the PDF are loaded in the browser
- Whether the PDF is rendered in the browser or on the server
- Whether PDFs are cached or rendered on the fly on the server
Browser rendering vs. server rendering
There are two options for running Nutrient Web SDK:
- Run locally in the browser
- Work together with Document Engine — either self-hosted or managed
Using only the Web SDK requires minimal configuration, but pairing it with Document Engine provides superior performance for the following reasons:
- Loading rendering code — In standalone mode, the browser downloads the Nutrient viewer runtime and WebAssembly worker artifacts needed for client-side rendering and editing. With Document Engine, more of that processing happens server-side, reducing the client-side computational burden.
- Loading the PDF — In standalone mode, the browser fetches document data directly and renders pages as soon as the required data is available (for example, with byte-range requests on suitable files). With Document Engine, the server handles page rendering, and the client mainly receives rendered results, which can improve perceived loading speed on large documents and slower devices.
- Rendering the PDF — Rendering a PDF takes time. In standalone mode, the client is responsible for rendering and processing. With a server setup, the work is split between server and client. The client mainly displays results produced by the server.
A server backend improves performance, especially when:
- Your PDF files are large.
- Your users access PDFs from a slow network connection — for example, on a mobile phone or in a rural area.
- Your users have low CPU performance — for example, on a mobile phone or on an old computer.
Document Engine performance
When using Nutrient Web SDK with Document Engine, too many PDF rendering requests hitting a single server can cause performance issues. To handle a high volume of requests, run an arbitrary number of Nutrient servers in parallel behind a load balancer.
For more information, refer to the horizontal scaling guide.
Web SDK performance
When using only Nutrient Web SDK in the browser, it primarily uses WebAssembly for rendering and processing on the client. In legacy environments without required WebAssembly capabilities, compatibility fallbacks can apply (for example, asm.js artifacts in older setups).
The operational modes guide offers a comparison of the benefits of each solution (with and without Document Engine).
Performance considerations
WebAssembly is intermediate code that needs to be compiled in the browser. Nutrient uses various advanced techniques to improve performance. For more information, refer to the optimizing WebAssembly startup time blog post. Additionally, use the 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.
For information on the average download time for the WebAssembly artifacts (~9 MB, ~3.7 MB gzipped) for different network conditions, refer to the international broadband scorecard(opens in a new tab) by Ofcom.
The figures mentioned in the scorecard apply only to the first time the page is loaded, as subsequent requests are much faster since the browser cache is used.
When ScrollMode.CONTINUOUS is set as ViewState#scrollMode, Nutrient Web SDK keeps a certain number of pages above and below the currently viewed one in memory. This keeps the memory footprint in check and avoids slowing down scrolling performance, as more DOM nodes need to be retained. On a document with many pages, switching back and forth between distant pages requires rerendering them, which takes additional time.
The rerendering strategy when using only Nutrient Web SDK is different from using Nutrient Web SDK with Document Engine, where the different pages are stored on the browser’s network cache so that a repeated request for a previously loaded page resolves instantly.
Preloading and prefetching
To improve load times within your application, use preload and prefetch in appropriate scenarios — for example, preloading nutrient-viewer.js on pages that are very likely to open a viewer, and prefetching it when opening a viewer is only a possible next step.
The preload attribute of the <link> tag causes the browser to start downloading the resource earlier in the page lifecycle, improving overall responsiveness. The prefetch attribute fetches resources that a user is likely to request next. Refer to the HTML specification(opens in a new tab) for more information.
The implementation depends on how you integrate the SDK. For script-tag integrations, add <link rel="prefetch" href="path/to/nutrient-viewer.js"> or <link rel="preload" href="path/to/nutrient-viewer.js"> within the <head> of relevant pages. For npm-based integrations, use your bundler’s preload/prefetch mechanisms for the chunk that contains @nutrient-sdk/viewer.
For websites and applications using modern frameworks that use webpack for bundling, use the /* webpackPrefetch: true */ or /* webpackPreload: true */ comments within your import(). Webpack uses this information to generate the appropriate <link rel="prefetch" ...> or <link rel="preload" ...> tags. Refer to the webpack documentation(opens in a new tab) for more information.
WebAssembly support
WebAssembly support is widely available in modern browsers, and it remains the core execution model for high-performance client-side document processing in Nutrient Web SDK.
If you want deeper technical background, refer to:
- How to optimize WebAssembly startup time
- How to use WebAssembly modules in a web worker
- WebAssembly for high-performance document tasks
- Dynamic linking in WebAssembly (advanced, binary-size tradeoffs)
- Render performance improvements in Nutrient Web SDK (rendering pipeline case study)
Preloading WebAssembly artifacts
Standalone mode uses the NutrientViewer.preloadWorker function to fetch WebAssembly artifacts in advance so that when the actual document is loaded, they’re already available. This minimizes the time the user has to wait for these files to load.
If you don’t open a PDF document right away after loading Nutrient Web SDK, boost subsequent document loading time by using NutrientViewer.preloadWorker:
// Call early in your app — for example, on page load or after login,// before the user navigates to a page within a PDF viewer.NutrientViewer.preloadWorker({ // When self-hosting assets, pass the same baseUrl you use in NutrientViewer.load(). // baseUrl: "https://example.com/assets/",});Caching
For optimal performance, implement a caching strategy that enables recurrent users to interact with your app without delay. Precache the resources ahead of the actual point when the user needs them by using service workers.
Refer to the caching on the web guide to learn more.