> For the complete documentation index, see [llms.txt](https://docs.apryse.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.apryse.com/web/best-practices/best-practices.md).

# Best Practices to Improve WebViewer Performance and More

Improve WebViewer performance by preloading it for instant display. Avoid 'display: none' to hide elements. Learn about loading documents efficiently and reusing WebViewer instances for better memory

## Preload WebViewer

If your website doesn't need to display the viewer immediately you can improve performance by preloading WebViewer so that it's immediately ready when you want to display a document. To do this you can load WebViewer without a document and hide the viewer. When it's time to display WebViewer you can simply unhide the element and call loadDocument.

{% hint style="warning" %}
**Don't use "display: none" to hide the element**

This causes issues with iframes and web workers. Use "visibility: hidden" or "height: 0; width: 0;" instead.You may see an error like "memory access out of bounds", NS\_ERROR\_FAILURE or "getComputedStyle(...) is null"
{% endhint %}

The reason this is worthwhile is that when WebViewer is instantiated it needs to load a number of JavaScript and CSS files and initialize the viewer UI. Depending on the network connection this can take a non-trivial amount of time which happens in the background when preloading.

## Loading documents with loadDocument

If you want to load multiple documents in your app you'll want to reuse WebViewer. This is better than removing the old iframe and creating a new instance of WebViewer because older browsers like Internet Explorer may have trouble with this and leak memory.

To reuse WebViewer just keep a reference to your WebViewer instance and call loadDocument with the new document URL. The old document will be removed from the viewer (automatically cleaning up its resources) and the new document will be loaded in.

{% hint style="info" %}
Note that if you are using the serverUrl option for loading annotations it's important to specify the documentId for each document so your server can determine which annotations should be returned. See more information [here ](/web/annotation/import-export.md).
{% endhint %}

{% tabs %}
{% tab title="JavaScript (SDK v8.0+)" %}
{% code lineNumbers="true" %}

```js
WebViewer({
  ...
}, viewerElement)
  .then(instance => {
    loadDocumentButton.on('click', () => {
      instance.UI.loadDocument('mysite.com/myDocument.pdf', { documentId: 'id2' });
    });

    loadAnotherDocumentButton.on('click', () => {
      instance.UI.loadDocument('mysite.com/myOtherDocument.pdf', { documentId: 'id2' });
    });
  });
```

{% endcode %}

[UI.loadDocument](https://sdk.apryse.com/api/web/UI.html#loadDocument__anchor)
{% endtab %}

{% tab title="JavaScript (SDK v6.0+)" %}
{% code lineNumbers="true" %}

```js
WebViewer({
  ...
}, viewerElement)
  .then(instance => {
    loadDocumentButton.on('click', () => {
      instance.loadDocument('mysite.com/myDocument.pdf', { documentId: 'id2' });
    });

    loadAnotherDocumentButton.on('click', () => {
      instance.loadDocument('mysite.com/myOtherDocument.pdf', { documentId: 'id2' });
    });
  });
```

{% endcode %}

[WebViewerInstance.loadDocument](https://sdk.apryse.com/api/web/UI.html#loadDocument__anchor)
{% endtab %}
{% endtabs %}

If you run into any issue, see [Troubleshooting loading errors](/web/get-started/faq/loading-errors.md).

## Linearize PDF files

When viewing PDFs directly WebViewer is able to start rendering pages earlier when a PDF is linearized. Linearized PDF files are also known as "Fast Web View" which is often indicated in the document properties dialog of your favorite desktop PDF reader. You can use Apryse SDK on your server to ensure PDF files are linearized.

## Thumbnails Optimization

Use the [SaveViewerOptimized](https://sdk.apryse.com/api/PDFTronSDK/dotnet/api/pdftron.PDF.PDFDoc.html#pdftron_PDF_PDFDoc_SaveViewerOptimized_System_String_pdftron_PDF_ViewerOptimizedOptions_) option that Apryse SDK offers on the server to ensure thumbnails are optimized.

## Support range requests

Range requests allow the browser to request specific bytes from a URL. For WebViewer to efficiently download and start rendering documents quickly it's important that the server hosting the document file (for example PDF) supports these requests.

When serving files statically from a server this generally works without any configuration. However if you're serving the files in some other way you may need to use a library to handle the range requests for you.

The [range request specification](https://tools.ietf.org/html/rfc7233#section-2.1) isn't very complicated so it's also possible for you to implement the handling yourself.

## Keep original files

If you are doing file conversions of any type then you should always keep track of the original source file. For example, if you allow your customers to upload various file types (Office, images, text) and you convert them all to PDF, then you should still retain the original file, and maintain in your database links between the original and converted file. This ensures maximum flexibility and maintenance.

## Support serving with Content-Encoding

If viewing PDF or Office document directly, it's recommended that your server supports serving the larger worker files as pre-compressed brotli or gzip files. You can read more about this in our [WebViewer content-encoding warnings FAQ](/web/get-started/faq/content-encoding.md).

## Storing annotations

WebViewer provides example implementations of annotation handlers for a few different languages which store all annotations as a single XFDF file on your server. This is one way to implement annotation handling, however if you have multiple users accessing the same document then timing issues can occur with one user overwriting the annotations of another.

One way to handle this to store the XFDF data for each annotation separately, for example as rows in a database. Then when WebViewer requests the annotation data for a document you can run a query to get all the annotations with that document id, append the data together and send it back to WebViewer.

This is similar to the approach that the [realtime collaboration guide](/web/collaboration/realtime-collaboration.md) takes although that sample goes further and updates the data in real time. The important part to take away from it is the use of [`getAnnotCommand`](https://sdk.apryse.com/api/web/Core.AnnotationManager.html#getAnnotCommand__anchor) and [`importAnnotCommand`](https://sdk.apryse.com/api/web/Core.AnnotationManager.html#importAnnotCommand__anchor) to save and update the changes.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.apryse.com/web/best-practices/best-practices.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
