如果我使用以下脚本:
Bootstrap和jQuery Validation需要jQuery和jQuery Validation Unobtrusive需要jQuery验证,所以我们有相互依赖的脚本。我看到的后备脚本看起来都是这样的:
(window.jQuery || document.write('<script src="/bundles/jquery"><\/script>'));
($.validator || document.write('<script src="/bundles/jqueryval"><\/script>'));
($.validator.unobtrusive || document.write('<script src="/bundles/jqueryvalunobtrusive"><\/script>'));
($.fn.modal || document.write('<script src="/bundles/bootstrap"><\/script>'));
问题是,如果我使用的是ajax.aspnetcdn.com CDN并且它失败了,那么第一行将导致jQuery在本地加载,但接下来的三行代码将在此之前执行并出错,因为$是未定义的
是否有标准方法来处理这些类型的相互依赖的后备脚本?我环顾四周,无法找到处理此类情景的资源。
更新
我尽我所能地回答了这个问题,但我仍在寻找人们如何处理这个问题的答案。
答案 0 :(得分:1)
依赖于另一个第三方脚本似乎有点过分,但我发现Fallback.js和YepNope.js可能能够处理这种情况。我不确定CDN正常工作的日常场景的性能影响。更多信息here。
我还编写了自己的实现:
JavaScript回退
(function (document, fallbacks) {
var check = function (fallbacks, i) {
if (i < fallbacks.length) {
var fallback = fallbacks[i];
if (fallback.test()) {
check(fallbacks, i + 1);
}
else {
var script = document.createElement("script");
script.onload = function () {
check(fallbacks, i + 1);
};
script.src = fallback.src;
document.getElementsByTagName("body")[0].appendChild(script);
}
}
}
check(fallbacks, 0);
})(document, [
{ test: function () { return window.Modernizr; }, src: "/js/modernizr.js" },
{ test: function () { return window.jQuery; }, src: "/js/jquery.js" },
{ test: function () { return $.validator; }, src: "/js/jquery-validate.js" },
{ test: function () { return $.validator.unobtrusive; }, src: "/js/jquery-validate-unobtrusive.js" },
{ test: function () { return $.fn.modal; }, src: "/js/bootstrap.js" },
{ test: function () { return window.Hammer && window.Hammer.VERSION; }, src: "/js/hammer.js" },
{ test: function () { return window.Zepto; }, src: "/js/bootstrap-touch-carousel.js" }
]);
CSS后备
使用元标记的想法是从新的ASP.NET 5 MVC 6框架中“借用”的。
(function (document, fallbacks) {
var metas = document.getElementsByTagName("meta");
for (var i = 0; i < fallbacks.length; ++i) {
var fallback = fallbacks[i];
for (j = 0; j < metas.length; ++j) {
var meta = metas[j];
if (meta.getAttribute("name") == fallback.metaName) {
if (!fallback.test(meta)) {
var link = document.createElement("link");
link.href = fallback.href;
link.rel = "stylesheet";
document.getElementsByTagName("head")[0].appendChild(link);
}
break;
}
}
}
})(document, [
{
// metaName - The name of the meta tag that the test is performed on. The meta tag must have a class from the
// relevant stylesheet on it so it is styled and a test can be performed against it. E.g. for
// font awesome the <meta name="x-font-awesome-stylesheet-fallback-test" class="fa"> meta tag is
// added. The 'fa' class causes the font awesome style to be applied to it.
metaName: "x-font-awesome-stylesheet-fallback-test",
// test - The test to perform against the meta tag. Checks to see if the Font awesome styles loaded
// successfully by checking that the font-family of the meta tag is 'FontAwesome'.
test: function (meta) { return meta.style.fontFamily === "FontAwesome"; },
// href - The URL to the fallback stylesheet.
href: "/css/font-awesome.css"
}
]);