Content Delivery Networks (CDN) are useful to increase website performance, such as a great way to help speed up your site download times, even if by a fraction of a second. In branding, we often use public CDN’s offered by Google or Microsoft that host common files such as jQuery libraries. If we plan to use Design Manager for our Master Pages and Page Layouts, an issue arises with how SharePoint 2013 and Design Manager parse our HTML using XML.
In SharePoint 2010 or SharePoint 2013 (not using Design Manager), we might link to Google’s or Microsoft’s CDN for our jQuery library reference using the following code in our .master Master Page.
Or
Notice how I did not include http: before the //? That is because if we do not include http: or https: then the browser will request the library using the same protocol (i.e. http or https) as the main page. Handy trick.
Anyhow, it would be nice to include a fallback in case the CDN is unavailable. If we store a local copy of the library as well, we could supplement one of the above lines and use the following code.
1 2 |
As long as this code goes into a .master or .aspx you are set. But try this in a normal HTML file that you convert to a HTML Master Page in Design Manager and you are out of luck.
Why? What is wrong?
To show you what happens, I created a standard HTML prototype that I intent to convert into a HTML Master Page. My original prototype contained the following <head> section.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | <!DOCTYPE html> <html class="no-js" lang="en"> <head> <meta charset="utf-8" /> <title>CDN Example</title> <meta name="description" content="" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <link rel="stylesheet" href="css/bootstrap.css" /> <link rel="stylesheet" href="css/style.css" /> <!-- Modernizr enables HTML5 elements & feature detects for optimal performance. Include html5shiv 3.6. Our version is a custom build. Create your own custom Modernizr build: www.modernizr.com/download/ --> <script src="js/modernizr-2.6.2.custom.js"></script> <!--Grab Microsofts CDN's jQuery, with a protocol relative URL; fall back to local if offline --> <!--place in head in case need to access jquery inline in SP page layout--> <script src="//ajax.aspnetcdn.com/ajax/jQuery/jquery-1.9.1.min.js"></script> <script>window.jQuery || document.write('<script src="js/jquery-1.9.1.min.js"><\/script>')</script> <!--used to help make old scripts work with jquery 1.9--> <script src="js/jquery-migrate-1.1.0.min.js"></script> <!--js libraries--> <script src="js/jquery-ui-1.8.9.custom.min.js"></script> <!--custom scripts--> <script src="js/jquery-custom.js"></script> </head> |
Using SPD, I import this HTML file into the Master Page Gallery. When I open this HTML file (has not been associated with the HTML Master Page content type yet, so it also does not yet have a .master either), SharePoint decided to change my first script tag linking to the library. Notice that
became
This is not good as the src linking to our CDN is now incorrect. Why Design Manager removes the first part I am not sure, but if you open your HTML Master Page again and re-enter the correct src to your CDN, you should be set. I went ahead and reset the src to the CDN and now converted my HTML file to a HTML Master Page. (I followed the steps from Trick 2).
After my HTML file is converted to a HTML Master Page, I then opened my new HTML Master Page in SPD and looked at my link to the CDN as well as the additional fallback code that links to a local jQuery library if the CDN is unavailable.
In the above screenshot, we can see that our link to the CDN is still valid (if you forgot to update your link to the CDN, correct that now), but the link to our backup, local copy is now invalid.
Design Manager is not a fan of inline code within a <script> tag, in fact it is getting confused with the additional script within the document.write function. Notice how two //<![CDATA[ tags have been added.
My suggestion is that we use a trick similar to my first SharePoint 2013 Branding trick and use a snippet like block. See the following code block for the replacement code to link to a local jQuery library if the CDN is unavailable.
1 2 3 4 5 |
Note: I had to provide an absolute path to the local library now as SharePoint will not manage this link to the file for me as it would in a script or link tag.
By leveraging Markup Start (MS) and Markup End (ME) tags, we can get Design Manager to translate our script block to the .master Master Page in an unadulterated way. Let’s now look at how this block is translated in our associated .master Master Page.
1 2 3 4 5 6 7 |
This is exactly what we are looking for. In our .master Master Page we are now properly linking to a CDN for our jQuery Library. If this is unavailable for any reason, we can fall back to our own local copy.
This same technique could be used in HTML Page Layouts as well if your project requires you to link to a CDN in an HTML Page Layout ContentPlaceholder.
See of all of my SharePoint 2013 Branding Tricks and Discoveries.
This bug has just been fixed in SharePoint 2016 and O365. As of August 2015 CU, the bug was still there.
I did not know it was fixed in SP 2016. Makes sense but I never checked. Thank you for sharing!
We’re having this exact issue although it is not limited to HTML masterpages.
Sharepoint 2013 munges CDN links on every masterpage we create or import when we remove the protocol.
This looks like a bug, and I wish we could fix or disable this behavior.
We’re using a highly customized master page from a SP2010 site while transitioning to SP2013. CDN links in the master page get munged in the way you’re describing no matter how many times we add them back. Is there a way to stop this?
Unfortunately not that I have found. My only suggestion is to recode the links to CDN’s in the manner I suggested. Or do not use HTML Master Pages, just use a .master that is not associated with a HTML Master Page, or is in fact managed by design manager.