Choosing a CDN for SharePoint client-side solutions

Client-side solutions have been de rigueur for a few years now: they're cloud friendly, and are generally much easier to deploy than server-side code. SharePoint is an enterprise class content management tool, so it's only natural to store the client code in SharePoint. That was all well and good until Office 365's large farm sizes rendered SharePoint's BLOB cache useless, which makes loading static files much slower online than on premises.

So lately Microsoft has been encouraging - and helping - us all to use a proper Content Delivery Network (CDN) for static content. CDN's are designed for speed and volume; they even address the speed of light problem by fetching files from a data center that's near the client. This will help your client-side solutions to load noticeably faster, as seen in this chart.

CDN Comparison in ms

The chart shows the time to download one file, an SPFx bundle from my Quotes web part. For all tests, I warmed up my local DNS cache and forced a refresh in Chrome; I also measured the timing with Chrome's developer tools. TTFB is the Time to First Byte - that is the amount of time between the browser requesting a page and receiving the first byte of a response. This can include things like DNS lookups and router caches, but I warmed up each scenario, so it's mainly time spent in the server. You can see that with SharePoint only it's about half a second slower, since without a BLOB cache, SharePoint needs to go all the way back to SQL for the file. It also may be due to SharePoint only supporting HTTP 1.1 (still?) - so it needs to establish the SSL connection each time. TTLB is, of course, Time to Last Byte; there the transfer time doesn't vary as much, but still SharePoint manages to be slower.

Using a CDN can be the difference between seeing your web part spin while loading vs. a tiny flicker on the screen.

There are many CDN options out there; I tested two of them for this article. SharePoint Online comes with a free CDN; this is the obvious choice. Azure also offers a CDN, however; I picked the Verizon free plan but there were other options. (Wow that TTFB was fast!)


I started by testing with no CDN. Since I was using the SharePoint Framework, I set the "cdnBasePath" in write-manifests.json to the location of a document library in SharePoint.

"cdnBasePath": ""

Whether I'm using the SharePoint Framework or just a Content Editor Web Part, I like to put shared files in a special site collection that's secured appropriately. (NOTE: The content editor web part can't reference files outside of its site collection, but it's useful to put very simple files in each site collection that pull in the application logic from a shared location; see this article for details.) As you can see in the example, my site collection is called /sites/scripts; within that I have a document library called public (the name will be clear later in this article). Within public, I have a folder for each solution. Nice and tidy.

To deploy to the CDN, I ran a couple gulp commands

gulp bundle --ship

gulp package-solution --ship

Then I copied the files from the /temp/deploy folder into the quotes folder in the document library, and I deployed the SharePoint Package (.sppkg) file in the app catalog.

All that directs SharePoint to fetch the web part bundle from the folder in SharePoint. The result works fine, and if the powers that be won't let you set up a CDN, it's good enough.

SP Only

But look - it took over a second to load including the 171.5 ms it spent waiting for the browser to free up a thread to make the request on. A second is an eternity on a web page!

SharePoint CDN

First of all, let me clarify that I used a SharePoint public CDN. That means that anyone with the URL can read the file; it's not very secure! But the thinking is that's OK for JavaScript and CSS files... you're not hard-coding passwords are you? Are you!

SharePoint also supports a private CDN, but it's not especially useful for web part code and the like. It provides a token-based authorization scheme, where the token is encoded on the URL. SharePoint checks the file's permissions, and if the user has access, it generates the token and sticks it on the URL. This URL rewriting is cool, but it only applies to image files and the like which are referenced by page content. SharePoint won't rewrite the URL's of, say, an SPFx web part's code bundle, so it's useless in this context.

To set up the public CDN, you need a few PowerShell commands. First, ensure you have the latest SPO PowerShell commands. Then you can add one or more origins for the CDN. An origin is just a SharePoint document library; put files in the library, and they are automatically deployed to the CDN. How easy is that? Just be sure you don't put any confidential documents in there!

For example, here's how I published the origin for my example:

Set-SPOTenantCdnEnabled -CdnType Public -Enable $true
Add-SPOTenantCdnOrigin -CdnType Public -OriginUrl sites/scripts/public

Now you know the reason I called the document library "public" - because I planned all along to associate it with the public CDN.

When referencing files, simply prepend the SharePoint library URL with "".

  "cdnBasePath": ""

You can get more details here:

As you can see, the results are significantly better!


Azure CDN

Azure has a CDN too, and the tooling to use it is built into the SharePoint Framework tools, making it easy to use. To start, set up your Azure CDN using these instructions. This article will guide you through the whole process, so I won't repeat it all here, just the high level concepts. I used the standard Verizon CDN due to the price and features; other CDN options in Azure may perform differently.

There is a file called deploy-azure-storage.json in every SharePoint Framework project; during the setup, you copy your Azure account and access key into the file so the gulp task can deploy the web part directly to the CDN.

  "workingDir": "./temp/deploy/",
  "account": "<!-- STORAGE ACCOUNT NAME -->",
  "container": "quotes",
  "accessKey": "<!-- ACCESS KEY -->"

Of course you also have to put the Azure CDN location into the cdnBasePath as before. A few gulp tasks later, and you're in action.

gulp bundle --ship

gulp deploy-azure-storage

gulp package-solution --ship

Azure CDN

As you can see, this was the fastest of all, but only negligibly different than the SharePoint CDN

Delivering your Static Content

Either CDN option works well; the SharePoint CDN is free, and easy to set up if you're an administrator. The key is to use a CDN wherever possible rather than a document library to deliver static content in SharePoint Online!

Comments (2)

  1. Nigel Price says:

    Hi Bob

    Very Interesting article. One assumes this is for a single user. Do we know what happens when there are a large number of users ? Do CDNs scale linearly or exponentially.

    1. I have to confess I don’t know if they scale linearly or exponentially but I know they scale very well. Visit any modern SharePoint page and do a network trace, and you’ll see that Microsoft puts its static content in similar CDN’s. Many of these files are used on every modern page in every tenant in O365, so you’ve got some real scale there, and they’re still extremely fast!

Skip to main content