CDN Fallback

Description

The CDN is down, or my users have it filtered by a firewall, proxy, admin policy or other problem. This can cause errors or bad looking sites. How do I ensure the necessary resources will be fetched?

Solution

This article contains three examples:

In this article, the paths to the actual CDN resources are broken deliberately with a string of aaaaa, so you can examine how the fallback works. For a real app, fix the paths and consider minifying the scripts.

Stylesheet Fallback

The Telerik themes provide a test class you can easily test against to determine if they are loaded. To implement a fallback, test an element for this class (k-theme-test-class) and see if its opacity is 0. If not, then the Telerik Theme isn't loaded, so you must add a <link> element pointing to a local asset that can be downloaded instead. This approach can work in a server-side app as well, and can also be combined with a script fallback logic below.

<link rel="stylesheet" href="https://unpkg.com/@@progress/kendo-theme-aaaaadefault@@latest/dist/all.css" />
<script>
    function cdnTest() {
        var testElem = document.createElement("div");
        testElem.className = "k-theme-test-class"; // the test class the Telerik themes provide
        document.body.appendChild(testElem);
        var testOpacity = window.getComputedStyle(testElem).getPropertyValue("opacity");
        if (testOpacity !== 0) {
            // cdn failed
            var newLink = document.createElement("link");
            newLink.setAttribute("rel", "stylesheet");
            newLink.setAttribute("type", "text/css");
            newLink.setAttribute("href", "_content/Telerik.UI.for.Blazor/css/kendo-theme-default/all.css"); // URL to the static asset from the Telerik package
            document.getElementsByTagName("head")[0].appendChild(newLink);
        }
        document.body.removeChild(testElem);
    }
    cdnTest();
</script>

Script Fallback

To test for the script, just check if the TelerikBlazor object exists. If not, the Telerik JS Interop file was not loaded and you should create a <script> tag pointing to a local resources instead.

<script src="https://kendo.cdn.telerik.com/blazor/2.16.0aaaaa/telerik-blazor.min.js"></script>
<script>
    if (!window.TelerikBlazor) { // the Telerik object is not present
        var newScript = document.createElement("script");
        newScript.setAttribute("src", "_content/Telerik.UI.for.Blazor/js/telerik-blazor.js"); // path to static assets from the Telerik package
        document.getElementsByTagName("head")[0].appendChild(newScript);
    }
</script>

Stylesheet Fallback for Server-Side Blazor

A server-side Blazor app is bootstrapped in a Razor page (_Host.cshtml) and so you can benefit from framework features such as the built-in framework CDN fallback option instead of implementing your own stylesheet fallback.

<link rel="stylesheet"
      href="https://unpkg.com/@@progress/kendo-theme-aaaaadefault@@latest/dist/all.css"
      asp-fallback-href="_content/Telerik.UI.for.Blazor/css/kendo-theme-default/all.css"
      asp-fallback-test-class="k-theme-test-class"
      asp-fallback-test-property="opacity"
      asp-fallback-test-value="0" />

Notes

You may want to consider using static assets as the primary way to obtain the necessary resources. They provide the following benefits in a Blazor app:

  • For server-side Blazor - the necessity for a low-latency connection makes this flavor suitable for Intranet apps, and in such cases the user is likely to be closer to the server than to the cloud. Thus, downloading the files from the app server is likely to be faster than donwloading from the CDN.

  • For client-side Blazor - Using the static assets that come with the packages make your app independent of third party services, so it is easier to bundle together (for example, for offline support and PWAs), and those assets are available in wwwroot upon build anyway.

In this article
Not finding the help you need? Improve this article