我应该使用 CDN 中的 Bootstrap 还是在我的服务器上制作副本?
Posted
技术标签:
【中文标题】我应该使用 CDN 中的 Bootstrap 还是在我的服务器上制作副本?【英文标题】:Should I use Bootstrap from CDN or make a copy on my server? 【发布时间】:2014-11-29 08:03:03 【问题描述】:使用 Twitter Bootstrap 的最佳做法是什么,从 CDN 引用它或在我的服务器上制作本地副本?
由于Bootstrap不断发展,如果我参考CDN,用户可能会随着时间的推移看到不同的网页,甚至有些标签可能会损坏。大多数人的选择是什么?
【问题讨论】:
【参考方案1】:Why Not Both ¯\_(ツ)_/¯ ?Scott Hanselman 有一篇关于使用 CDN 提高性能的精彩文章,但也很优雅falling back to a local copy in case the CDN is down。
具体到bootstrap,可以对load from a CDN with a local fallback做如下操作:
Working Demo in Plunker
<head>
<!-- Bootstrap CSS CDN -->
<link rel="stylesheet" href="~https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css">
<!-- Bootstrap CSS local fallback -->
<script>
var test = document.createElement("div")
test.className = "hidden d-none"
document.head.appendChild(test)
var cssLoaded = window.getComputedStyle(test).display === "none"
document.head.removeChild(test)
if (!cssLoaded)
var link = document.createElement("link");
link.type = "text/css";
link.rel = "stylesheet";
link.href = "lib/bootstrap.min.css";
document.head.appendChild(link);
</script>
</head>
<body>
<!-- APP CONTENT -->
<!-- jQuery CDN -->
<script src="~https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.0/jquery.min.js"></script>
<!-- jQuery local fallback -->
<script>window.jQuery || document.write('<script src="lib/jquery.min.js"><\/script>')</script>
<!-- Bootstrap JS CDN -->
<script src="~https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
<!-- Bootstrap JS local fallback -->
<script>if(typeof($.fn.modal) === 'undefined') document.write('<script src="lib/bootstrap.min.js"><\/script>')</script>
</body>
更新
你也可以做同样的测试using YepNope or fallback.js 根据Flash's comment 和this solution,更新了检查.visible
类而不是测试rgb(51, 51, 51)
的答案
根据deste's comment,更新为使用.hidden
和.d-none
用于Boostrap 3.x 或4
当testing if a stylesheet loaded时,你必须寻找一个会被应用的样式,创建一个元素,看看它是否被应用了。
使用 vanilla js 更新了样式表以立即加载到头部。您需要使用Document.createElement()
创建一个测试元素,应用引导类,使用Window.getComputedStyle()
测试display:none
,然后有条件地使用js 测试insert a stylesheet。
最佳实践
关于最佳实践的问题,有很多very good reasons to use a CDN in a production environment:
它增加了可用的并行度。 它增加了缓存命中的机会。 它可确保负载尽可能小。 它减少了服务器使用的带宽量。 它确保用户将获得地理位置接近的响应。
对于您的版本控制问题,任何有价值的 CDN 都可以让您定位库的特定版本,这样您就不会意外地在每个版本中引入重大更改。
使用document.write
根据document.write
上的mdn
注意:当
document.write
写入文档流时,在关闭(加载)的文档上调用document.write
会自动调用document.open
、which will clear the document。
但是,这里的使用是有意的。代码需要在 DOM 完全加载之前以正确的顺序执行。如果 jQuery 失败,我们需要在尝试加载依赖于 jQuery 的引导程序之前将其内联注入到文档中。
加载后的 html 输出:
不过,在这两种情况下,我们都会在文档仍处于打开状态时调用,因此它应该内联内容,而不是替换整个文档。如果你等到最后,你必须替换为document.body.appendChild
才能插入动态源。
旁白:在 MVC 6 中,您可以使用 link and script tag helpers 来做到这一点
【讨论】:
硬编码rgb(51, 51, 51)
似乎有风险 - 如果有人更改颜色并忘记更新它怎么办?有没有更稳定的属性可以使用?
@Flash,是的,我同意这似乎很挑剔。很难在全局 javascript 变量中或直接通过 CSS 测试 CSS 更改。我们只需要测试元素,看看它们的样式是否符合 CSS 可能描述的方式,我们将始终拥有 <body>
元素。 This answer 添加一些带有 .hidden
div 的标记,然后进行测试以查看它是否可见:$('#bootstrapCssTest').is(':visible')
。随着时间的推移,该类可能不太可能发生重大变化。
@KyleMit,我该如何为Google Material Icons 执行此操作?
很好的答案!只需要注意:如果您使用的是 Bootstrap 4,您应该使用“d-none”类而不是“hidden”类,以便让故障转移正常工作。
@JarrodW。 - 好问题。我不得不做一些挖掘工作。我们应该很好地在这里使用它 - 查看更新的答案【参考方案2】:
取决于具体的网站。
您有很多用户吗? 你关心带宽使用吗? 性能是否存在问题(CDN 的 can speed up 回复)?
您可以链接到特定版本:
//maxcdn.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css
或者
//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css
这样您就不必担心库更新,保持更新是一种更好的做法。
我不确定有关开发人员选择的确切统计数据是什么,但您可以查看 here 并看到数十亿个请求被发送到 Bootstrap CDN,这意味着它是强大且使用安全的。
【讨论】:
最后一个链接坏了。 @Nuclearman,trends.builtwith.com/cdn/StackPath-BootstrapCDN,我也在提交编辑。【参考方案3】:几乎所有公共 CDN 都非常可靠。但是,如果您担心 CDN 可能出现故障的那一小部分时间,您可以从 Bootstrap CDN 加载 Bootstrap,并在第一个 CDN 出现故障时回退到备用 CDN。
<html>
<head>
<!-- Bootstrap CSS CDN with Fallback -->
<link rel="stylesheet" href="https://pagecdn.io/lib/bootstrap/3.4.1/css/bootstrap.min.css" integrity="sha256-YLGeXaapI0/5IgZopewRJcFXomhRMlYYjugPLSyNjTY=" crossorigin="anonymous">
<script>
var test = document.createElement("div")
test.className = "hidden d-none"
document.head.appendChild(test)
var cssLoaded = window.getComputedStyle(test).display === "none"
document.head.removeChild(test)
if (!cssLoaded)
var link = document.createElement("link");
link.type = "text/css";
link.rel = "stylesheet";
link.href = "https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css";
document.head.appendChild(link);
</script>
</head>
<body>
<!-- APP CONTENT -->
<!-- jQuery CDN with Fallback -->
<script src="https://pagecdn.io/lib/jquery/3.2.1/jquery.min.js" integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo=" crossorigin="anonymous"></script>
<script>window.jQuery || document.write('<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"><\/script>');</script>
<!-- Bootstrap JS CDN with Fallback -->
<script src="https://pagecdn.io/lib/bootstrap/3.4.1/js/bootstrap.min.js" integrity="sha256-CjSoeELFOcH0/uxWu6mC/Vlrc1AARqbm/jiiImDGV3s=" crossorigin="anonymous"></script>
<script>if(typeof($.fn.modal) === 'undefined') document.write('<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"><\/script>')</script>
</body>
</html>
关于您的第二个顾虑: 这篇文章中的链接是 bootstrap 和 jquery 的硬编码版本。因此,即使 bootstrap 和 jquery 库不断开发并获得新功能,您的网站也会随着时间的推移保持不变。
【讨论】:
又名,接受的答案在说什么。遗憾的是,这甚至得到了 1 票。【参考方案4】:感谢@KyleMit。另一种后备方式是使用“窗口”对象作为下 -
<script type="text/javascript" src="https://cdn.jsdelivr.net/jquery/latest/jquery.min.js"></script>
<script>
window.jQuery || document.write("<script src='js/jquery.min.js'><\/script>");
</script>
它的工作原理是这样的 - 如果 CDN 链接有效,“window”对象将具有“jQuery”属性,否则脚本的第二部分即 document.write 将被执行,它指向本地副本。
回答原始问题 - 拥有 CDN 有很多好处,例如快速下载而不影响您的服务器和带宽。拥有本地副本有其自身的好处(作为后备安排)。在 Intranet 上,由于代理设置、安全策略的原因,CDN 链接可能无法正常工作,或者如果 CDN 链接断开,则可能无法正常工作。直接的答案是两者兼得。
【讨论】:
【参考方案5】:我尝试编辑KyleMit's answer,但论坛标记为错误的缩进代码,即使不是,所以我在下面添加我的贡献:
由于该问题被标记为 twitter-bootstrap 主题(不仅是 twitter-bootstrap-3 ),因此更新新版 Bootstrap 的响应可能会有所帮助。
由于框架在其第四版中添加了一个用于隐藏元素的新类,在这种情况下我们应该使用.d-none
而不是.hidden
。
在这种情况下,其他一切都保持不变,除了 lib 版本(当然!)
【讨论】:
以上是关于我应该使用 CDN 中的 Bootstrap 还是在我的服务器上制作副本?的主要内容,如果未能解决你的问题,请参考以下文章
React-Bootstrap 需要 npm install bootstrap 和 bootstrap CDN 还是其中之一?
Bootstrap cdn 覆盖了我在 react js 中的自定义 css 样式
我应该使用 Angular UI Bootstrap 还是普通的 Bootstrap 3? [关闭]
使用 bootstrap 5 cdn 时 Jquery 包含的菜单未显示在 html 页面上