Web Resources Not Cached By Browser


I recently ran into a problem where my HTML web resources and their script dependencies weren't being cached. I first noticed this because the page was loading slowly. The web resource in question was dynamically loading data from Dynamics 365, so I was expecting a delay but not to as much as the delay I was seeing.

Diagnosing the Problem

  1. The first thing I did was to load the page a few times to make sure it wasn't just running slowly the first time after a publish. In this case, it was running just as slowly every time.
  2. The next step was to break out the browser developer tools. In my case I was using Chrome so after a quick <F12>, select the Network tab and page reload, I was in business. Here is the pertinent section from the network log:Web Resources loading from network
    You can see that the 'size' is listed. If these were coming from cache then they would show as (from memory) or (from disk).
  3. I remembered that Scott Durow had a blog article about caching web resources so I checked there first. If you aren't already familiar with how Dynamics 365 caches web resources, I suggest you read that before continuing here. Everything seemed in order.
  4. Then I realised that this particular web resource is being dynamically loaded when a lookup field on the form is modified. You can see the GUID of the record being passed in the ?data parameter in my screen shot above.
  5. When I hovered over the URL of the initiator it was missing the Dynamics 'Cache Token' that normally looks something like this %7B634411504110000000%7D.

The culprit was the javascript that I was using to load the web resource into the control on the form:

var clientUrl = Xrm.Page.context.getClientUrl();  
var url = clientUrl + webResourceUrl + "?data=" + recordId;  

The getClientUrl() function in the SDK gives you the base URL for your organization, but it does NOT include the cache token.

The Fix

To fix the problem, instead of using getClientUrl() I just grabbed the 'base' URL from the URL that was already loaded in the web resource and replaced the query string with the one I needed. Like this:

var baseUrl = webResource.getSrc().split("?")[0];  
var url = baseUrl + "?data=" + recordId;  

N.B. there are ways to identify the cache token and dynamically build the URL yourself, such as this method from Nick Doriot. The down-side is that it requires a network request, and in my situation I already had the required base URL available in the web resource.
Post image (oops, wrong kind of cash...) by Nikita Andreev on Unsplash.