Single frame loading

Overview

You can achieve single-frame page initialization (a.k.a. Instaload) if you can ensure that Cohtml receives all needed resources (html/css/img/fonts/etc.) for the page either before or during the first Advance call. This has several important benefits:

  • It achieves the best possible page initialization performance
  • Best possible page initialization performance on all subsequent loads of that HTML page. This is especially useful for UIs which switch and revisit HTML pages frequently.
  • Deterministic View loading. Cohtml will generate a full render of the finished HTML page on the first Advance call.

How to use

The overall workflow goes as follows:

  1. When creating the Cohtml system, turn off AsynchronousResourceRequestCalls in the cohtml::SystemSettings
  2. At some point in time before a given HTML page is loaded, preload all resources needed for its initialization.
  • For HTML/CSS/JS/Font resources, use the corresponding APIs to force Cohtml to fetch, parse and cache them.
  • For image resources, fetch and decode them as per the preloaded images guide)
  • For all other resources, just preload them in memory. This step is optional, but skipping it carries a performance hit as caching them in memory saves expensive disk operations later on.
  1. Load the HTML page, for example via LoadURL
  2. Call Advance on the View that holds the page
  3. Satisfy all following OnResourceRequest calls immediately (as in, in the same call stack). This is where preloading resources in memory comes in handy for performance reasons, but you can still read them from the hard drive here, as long as you pass the file contents to Cohtml before the OnResourceRequest call is finished.

If all resources that the HTML page needs were successfully loaded before or during their OnResourceRequest callbacks, the HTML page is guaranteed to load fully on the first Advance. You can ensure that by checking if the ViewListener::OnFinishLoad callback was called.

Implementation example

You can find an example implementation of the steps listed below in the Prysm Instaload sample.

Turning off Asynchronous Resource requests

Configure the Cohtml system to use synchronous resource requests, via

systemSettings.AsynchronousResourceRequestCalls = false;

This makes sure that whenever Cohtml encounters a resource dependency, it will immediately ask you for it, instead of just scheduling a task and moving on with execution. All resource requests will now happen on the UI thread and any work you do during them will block it. Therefore, it is advised to have the resources loaded in memory. Note that you are still allowed to not provide the resource during the call to OnResourceRequest in synchronous mode - it just means that you will not achieve a single frame load.

Loading all resources in advance

Pick a convenient time for every type of resource that your page will use and preload them using the APIs outlined in our resource preloading guide. For this example, let’s assume that we’ve picked a point in time after the Cohtml System is created, but before any HTML page is loaded in the View. All resource types are preloadable during this time.

void MyApp::Initialize()
{
    PreloadFonts("fonts");
    PreloadCSS("css");
    PreloadJS("js");
    PreloadHTML();
    PreloadImages("images");
}

Loading the page in one Advance

Page loading can trigger in several ways, for example by following hyperlinks, but for now, let’s consider just manually loading the page in C++

// Load through C++
View->LoadURL("my_page.html");

If all resources for the page my_page.html are preloaded, your next call to cohtml::System::Advance after executing the code above will mark all resources as “ready for use” by the Views. After that, when your code reaches cohtml::View::Advance, the Cohtml library will:

  1. Build your entire HTML page
  2. Fire the cohtml::IViewListener::OnFinishLoad event (which you can use to check if the page loaded in one frame successfully).
  3. Schedule a paint frame on the render thread with your finished page