Skip to main content

Übertragung gerenderter Kacheln

Architektur

Beim Blättern innerhalb eines Dokuments müssen im Browser die Dokument-Seiten zur Anzeige gebracht werden. Der Browser setzt dabei mehrere rechteckige Kacheln zu einer Seite zusammen und stellt diese dar. Jede Kachel wurde zuvor vom Server gerendert und entspricht einem Bild im PNG/WebP-Format.

Der jadice web toolkit Server stellt die Kacheln über ein Servlet zum Download bereit. Jede Kachel wird vom Browser via HTTP-Download entgegengenommen. Da der Browser die Kacheln wie alle Bilddateien behandelt, werden die Kacheln vom Browser gemäß Browser-Einstellung gecacht. Einstiegspunkte für ein etwaiges Feintuning der Browser-Caches werden in einem gesonderten Abschnitt weiter unten behandelt.

Feintuning der Browser-Caches

ETag-Header

Die Tile-Requests werden server-seitig mit einem ETag versehen. Dieser wird anhand der URL generiert. Alle modernen Browser unterstützen diesen Mechanismus. Der ETag führt dazu, dass der Browser sich bereits gerenderte Kacheln im Cache hält. Wird dieselbe Kachel vom Browser erneut angefragt (z.B. durch runter- und erneutes hochblättern) wird diese nicht gerendert sondern aus dem Cache geladen.

View-ID

Bei Tile-Requests wird der Parameter v als View-ID verwendet. Dieser Parameter wird vom Client bei jedem neuen Dokument verändert. Damit ist sichergestellt, dass beim erneuten (expliziten) Laden desselben Dokuments ein erneutes Rendering stattfindet (da sich die URL verändert, ändert sich auch der ETag). Dies soll sicherstellen, dass eventuelle Änderungen am Dokument auch korrekt angezeigt werden und der Anwender nicht eine gecachte Version angezeigt bekommt.

Es kann jedoch auch erwünscht sein, dass die View-ID sich nicht ändert. Dies ermöglicht beispielsweise das schnelle Hin- und Herspringen bei mehreren Dokumenten, z.B. beim Betrachten einer Dokumentensammlung wie einer "Akte". Um die Änderungen der View-ID abzuschalten, muss folgendermaßen vorgegangen werden:

GWT

ClientConfigurationManager.getClientConfiguration().setPersistentViewId(true);

TypeScript & Angular

ClientConfiguration.get().setPersistentViewId(true);

Standard-Caching-Header

Um das Verhalten des Browser-Caches zu steuern, werden entsprechende Instruktionen serverseitig im Header der HTTP Response platziert. Die Klasse TileCacheFilter wird dafür in den Demos verwendet und kann als Vorlage für eine kundenspezifische Browser-Cache-Konfiguration dienen.

Im Allgemeinen sind die Voreinstellungen des Browser-Caches sinnvoll und müssen kundenseitig nicht angepasst werden.

Preloading von Seiten

Um eine flüssige Seitenanzeige auch für unbesuchte Seiten gewährleisten zu können, bietet das jadice web toolkit die Möglichkeit, Seiten schon vor deren Darstellung zu laden. Navigiert der Benutzer im Anschluss auf eine solche Seite, kann diese direkt aus dem Browser-Cache entnommen und zur Anzeige gebracht werden. Damit entfällt die Latenz durch Netzwerk und Rendering.

Um den Einsatz in möglichst allen Kundenszenarien zu ermöglichen, kann das Preloading-Verhalten flexibel und einfach an der PageView über die Klasse PreloadingPageRange konfiguriert werden. Ausgehend von den aktuell sichtbaren Seiten innerhalb des Viewers wird jeweils ein Seiten-Intervall für den vorangehenden und den nachfolgenden Bereich definiert (Notation: [-n;+m]). Beispielsweise können mit der Konfiguration [-3;+5] die drei vorangehenden und die 5 nachfolgenden Seiten ausgehend von den jeweils sichtbaren Seiten vorgeladen werden. Da zusätzlich auch die erste und die letzte Seite des Dokuments als Intervallgrenze konfigurierbar ist, kann das Preloading-Verhalten an beliebige Einsatzszenarien angepasst werden.

Eine passende Konfiguration des Preloadings hängt in starkem Maße von der Konfiguration des clientseitigen Caches ab. Ist der clientseitige Cache beispielsweise auf 20 Kacheln begrenzt, führt ein Seiten-Intervall von [-50;+50] zum überflüssigen Spülen. Außerdem beeinflusst die Konfiguration auch die anfallende Rechenlast auf Serverseite, da jede vorgeladene Seite dort zunächst gerendert werden muss. Bei einer großen Anzahl parallel arbeitender Benutzer kann der zusätzliche Renderingaufwand signifikant werden. Aus diesem Grund kann es sinnvoll sein, das Feature zunächst eher defensiv zu konfigurieren und die Intervalle iterativ zu vergrößern.

Beispiel: Konfiguration des Preloadings von Seiten (GWT)

final Viewer viewer = new ViewerBuilder().build();
final PageView pageView = viewer.getPageView();

// preload the previous 2 pages and all pages till the end of the document relative to the currently visible pages
// pageView.setPreloadingPageRange(new PreloadingPageRange(2, true));

// preload the previous 2 pages and the next 3 pages relative to the currently visible pages
pageView.setPreloadingPageRange(new PreloadingPageRange(2, 3));

Beispiel: Konfiguration des Preloadings von Seiten (TypeScript)

  const viewer: JadiceViewer = ...
pageRange: PreloadingPageRange = {previousPages: 1, followingPages: 10};
viewer.setPreloadingPageRange(pageRange);

Beispiel: Konfiguration des Preloadings von Seiten (Angular, Template)

    <jwt-multi-mode-viewer #viewerComponent
[preloadingPageRange]="pageRange"/>

Beispiel: Konfiguration des Preloadings von Seiten (Angular, Component)

  pageRange: PreloadingPageRange = {previousPages: 1, followingPages: 10};

Clientseitiges Caching von Text

Der Text von Dokumenten wird unter anderem für die Markierungsfunktion clientseitig gespeichert. Das zugehörige Cachingverhalten kann über die PageView konfiguriert werden. Dabei wird festgelegt, ob die Textbestandteile nur für die aktuell sichtbaren bzw. vorgeladenen Seiten gespeichert werden, oder für das gesamte Dokument.

Beispiel: Konfiguration des clientseitigen Cachings für Text

...

final Viewer viewer = new ViewerBuilder().build();
final PageView pageView = viewer.getPageView();

// default - cache text whenever the mouse is hovered over a page and purge cache only when the document is closed
// pageView.setTextPurgeStrategy(PageView.TextPurgeStrategy.PURGE_ON_DOC_CLOSE);

// cache text only for visible and preloaded pages, remove obsolete text on each page change
pageView.setTextPurgeStrategy(PageView.TextPurgeStrategy.PURGE_ON_PAGE_CHANGE);

...