13
Vote

CdnFallbackExpression for StyleBundles creates a <script> instead of a <link>

description

This is my attempt at providing CSS fallback for a Bootstrap3 bundle.
BundleTable.Bundles.Add(new StyleBundle("~/bundles/bootstrap", "http://netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css") 
{
    CdnFallbackExpression = @"
function (url) {
    var length = document.styleSheets.length;
    for (var i = 0; i < length; i++) {
        var sheet = document.styleSheets[i];
        if (sheet.href = url) {
            var rules = sheet.rules ? sheet.rules : sheet.cssRules;
            if (rules == null || rules.length == 0) {
                return false;
            }
        }
    }
}('http://netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css')"
}.Include("~/Content/bootstrap/bootstrap.css"));
BundleTable.Bundles.UseCdn = true;
The rendered output is
<link href="http://netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css" rel="stylesheet">
<script>(function (url) {
    var length = document.styleSheets.length;
    for (var i = 0; i < length; i++) {
        var sheet = document.styleSheets[i];
        if (sheet.href = url) {
            var rules = sheet.rules ? sheet.rules : sheet.cssRules;
            if (rules == null || rules.length == 0) {
                return false;
            }
        }
    }
}('http://netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css'))||document.write('<script src="/bundles/bootstrap"><\/script>');</script>
Note the fallback creates a <script> element instead of <link> even though it's a StyleBundle


https://github.com/qntmfred/CssCdnFallback

comments

shayneva wrote Nov 4, 2013 at 12:13 PM

By the way, I've created some workaround code to fix this in the meantime, but if I use a CDN for accessing the style bundle, then the javascript above to detect if any of the rules have been downloaded fails in Firefox due to a security warning about cross-domain scripting (specifically at the point where the stylesheet rules are being accessed):
var rules = sheet.rules ? sheet.rules : sheet.cssRules;
I can't think of an elegant way of soving this problem. I came up with a nasty solution involving adding a dummy style rule in the css and adding a dummy invisible element which is targeted by said style. But since the javascript has to run in the <head>, the element can't be added to the <body> as it doesn't yet exist, so the whole lot is wrapped in timeout, hoping that by the time it executes the <body> exists in order to add the dummy element to it. Very very ugly.

afsherman wrote Nov 24, 2013 at 1:56 PM

Why you do not resolve this in latest releases?!

JeffEmery wrote Feb 16, 2014 at 9:49 PM

I've provided a solution for this problem at GitHub Style Bundle Fallback

Marva00 wrote May 3, 2016 at 1:29 PM

I'm still hoping for a supported solution for this issue.