为什么不将样式/脚本嵌入HTML而不是链接?


41

我们将CSS和JavaScript文件连接起来以减少HTTP请求的数量,从而提高了性能。结果是这样的HTML:

<link rel="stylesheet" href="all-my-css-0fn392nf.min.css">
<!-- later... -->
<script src="all-my-js-0fn392nf.min.js"></script>

如果我们拥有服务器端/构建逻辑来为我们完成所有这些工作,为什么不更进一步,并将这些串联的样式和脚本嵌入HTML?

<style>.all{width:100%;}.my{display:none;}.css{color:white;}</style>
<!-- later... -->
<script>var all, my, js;</script>

减少了两个HTTP请求,但实际上我还没有看到这种技术。为什么不?


12
我怪缓存。

Answers:


98

因为在通过中断缓存实现HTTP请求时,保存HTTP请求几乎没有用。如果将样式表和脚本分别提供,则可以很好地缓存它们,并分摊到对非常不同的页面的许多请求中。如果在同一个HTML页面中删除它们,则必须与每个HTML页面重新传输它们。单。请求。

例如,此页面的HTML现在为13 KB。180 KB的CSS命中了缓存,360 KB的JS也命中了。两次高速缓存命中都花费了很少的时间,并且几乎不占用带宽。鞭打浏览器的网络分析器,然后在其他一些站点上尝试使用。


1
如果您正在做一个单页面应用程序风格的网站,那么其中绝大多数代码是特定于一个页面的,那么这仍然有意义吗?
JohnB 2013年

3
约翰:如果页面只被访问过一次,是的。如果多次访问,则所有嵌入的内容将多次传输而不是一次传输并进行缓存。
Konerak 2013年

另一个值得注意的要点是,通过分别提供这些资源,可以减少资源,从而减小资源的大小。
maple_shaft

2
@maple_shaft请详细说明一下,为什么不能像往常一样缩小资源,然后再包含它们?

1
@JohnB不要忘记CDN或isp本地缓存的影响。即使我在本地缓存未命中,我对google javascript的请求也可能永远不会到达google,因为另一个使用相同isp的人已经导致isp缓存了数据。

19

仅仅是因为Web性能真的很重要! 99%的时间将为您提供更快的最终用户响应时间。

这是Velocity Conf的一些例子。

  • 必应 –慢2秒的网页导致每位用户的收入下降4.3%。
  • Google – 400毫秒的延迟导致搜索量/用户减少0.59%。
  • 雅虎!– 400毫秒的减速导致整页流量下降了5-9%。
  • Shopzilla –将网站加速5秒钟,转换率提高了7-12%,搜索引擎营销的会话次数增加了一倍,所需服务器数量减少了一半。
  • Mozilla –将登陆页面缩短2.2秒,可将下载转换率提高15.4%,他们估计,每年的Firefox下载量将增加6000万。
  • Netflix –采用单一优化,gzip压缩,可将速度提高13-25%,并将其出站网络流量减少50%。

来自Web性能优化的先驱Steve Souders,

最终用户响应时间的80-90%用于前端-首先从这里开始。

使用外部文件产生更快的页面,因为JavaScript和CSS文件是由浏览器/网络/代理缓存的(如HTTP协议中定义的带有缓存头的缓存)。每次请求HTML文档时,都会下载HTML文档中内联的JavaScript和CSS。这减少了所需的HTTP请求的数量,但增加了HTML文档的大小。如果您使用的是类似Jquery的脚本,则很容易引用300 KB的脚本,并且不相信每个人都可以通过运行在您的网站上打开的单个应用程序(浏览器)来获得低延迟的100 MBits / s带宽。99%的时间将为您提供更快的最终用户响应时间。

相对于请求的HTML文档数量而言,缓存外部JavaScript和CSS组件的频率也很重要。如果您站点上的用户每个会话具有多个页面视图,并且您的许多页面都重复使用相同的脚本和样式表(捆绑包),则从缓存的外部文件中可以获得更大的潜在利益。

但是内联有时对于单页应用程序或每个会话具有单个页面视图的网站更可取。没有黄金法则,通常会忘记它,因为它主要涉及最终用户性能真正涉及的非常特定的网站。

您可以在此处阅读为什么性能如此重要(免责声明:我是作者)


3

HTTP的最新版本创建于1999年。1999年,每个人都通过拨号连接到Internet。互联网非常慢。16年后,事情发生了很大变化,但我们使用的协议却没有。

我们不应该内联的答案“因为它会干扰缓存”有些误导,特别是在超高速Internet时代。实际进行计算时,如果已内联,则对热缓存和热缓存用户的加载时间之间的差异通常可以忽略不计。有事实小的差异是不是固有因为你内联,但由于HTTP / 1.1的不灵活设计。

SPDY协议实现了称为服务器推送的功能。从本质上讲,这需要将HTML文档本身内联到协议中。智能服务器将知道客户端已经拥有的资源。愚蠢的服务器只会发送所有内容,尽管这仍然会带来性能上的好处,但可能会占用带宽。如果浏览器的缓存中包含内容,则可以简单地丢弃传入的副本。服务器会等到HTML加载完毕后再发送其他资源-从理论上讲,浏览器可以发送信号来取消服务器推送。

HTTP / 2.0基于SPDY,最有可能实现服务器推送,但是理论上您可以从今天开始使用SPDY。因此,我们不进行内联的真正原因是一个遗留问题-当前存在的协议较旧且不够灵活,无法实现“协议级内联”。


2
有趣的答案,而不是“遗留”,是您目前不内联的原因,是因为它最适合当前的Web协议基础结构。如果在完全部署HTTP / 2.0 / SPDY之后的n年内每个人都仍在做同样的事情,这将是很重要的事情;-)
andybuckley 2013年

2
您能否给出引用,简化计算或至少给出“超快”的标准数字?在文明的第一世界国家中,有很多钱可以用来上网的人们(阅读:客户),有时还是什至经常以比每秒数百兆字节更少的带宽浏览。我很少会超过3 MB / s,经常不到700 KB / s。作为单独的一点,您没有给出以OP建议的方式进行内联的理由(实际上,您没有给出理由),而是为优化协议提供了理由。

1
我的3G连接并非完全“超快”,我的手机话费也无法欣赏到不必要的数据。别忘了-并非所有的移动数据使用都通过网络共享和启用3G的平板电脑/笔记本电脑在手机上进行。Esp。对于笔记本电脑,假设是家庭宽带连接上的wifi /以太网。远程网络共享时不胜感激
AnonJr 2014

3

除了缓存和检索其他答案引起的问题外,我还要强调另一个更晦涩的问题:解析

HTML中出现的JavaScript可能会遇到解析问题,例如以下示例:

<html>
<head>
<script>
function myfunc() {
    if ("</style> isn't a problem")
        return "but </script> is"
}
</script>
<style>
body::after {
  content: '</script> is okay, but not </style>'
}
</style>
</head>
<body>
<script>document.write(myfunc())</script>
</body>
</html>

...这意味着您必须转换脚本以转义一些在HTML中触发的字符。当您将CSS和JavaScript作为外部资源提供时,此问题就消失了,因为它们不再需要考虑“父”解析上下文。

如果您以XML形式提供内容,则可以使用CDATA部分来解决此问题。但是,CDATA也存在类似的问题:

<?xml version="1.0" encoding="utf-8"?>
<html>
<head>
<script>
// <![CDATA[
function myfunc() {
    if ("</script> is no longer a problem")
        return "but ]]> is"
}
// ]]>
</script>
<style>
<![CDATA[
body::after {
  content: 'same ]]> issue here'
}
]]>
</style>
</head>
<body>
<script>document.write(myfunc())</script>
</body>
</html>

班轮要当心。


1

与较少的http请求相比,将内容从其表示的样式中分离出来通常具有更大的优势。

分隔所有样式可以启用并鼓励重用和共享文件。

文件的内容也将更加静态,并且可用于该页面和其他访问页面的服务器和客户端上的缓存。

但是,对于您的特定问题...如果让服务器自己进行缩小,则会使资产更难以维护和调试问题。但是,现在许多框架都在文件级别执行此操作,例如,所有cs和所有js。例如,ruby on rails框架现在将其资产最小化用于生产。额外的5-10个HTTP请求通常不是瓶颈,如果有100个以上的HTTP请求(您通常会在图片中看到),则瓶颈更多。

实际上将代码包含在页面本身中的额外步骤将具有较大的页面的缺点,您必须仔细管理下载页面,并且如果没有其余(现在很大)的页面,该页面通常无法显示内容正在下载。


澄清一下,您是说样式和内容的分离对开发人员有利,还是对最终用户浏览器的性能有利?

我的意思是,与减少业务需求相比,给公司带来的总体收益通常是更大的获胜。
迈克尔·杜兰特

3
您是否意识到OP主张使用单独的文件进行开发,并且仅在部署期间进行合并,同时进行压缩,混淆和“常规”合并?您将拥有可维护的代码库,并且也将获得性能上的好处。这是其他代码处理优化的常见做法,例如,最小化源代码并将多个JS / CSS文件合并为一个。

我没意识到 单词“在HTML中嵌入了那些串联的样式和脚本吗?” 使我困惑。
Michael Durrant 2013年

明确地说,我确实是在暗示@delnan在我的评论中提出的建议。抱歉,如果我的问题措辞不明确。
GladstoneKeep

1
  1. 尽量减少重复编码。以节省时间(您可以重复使用一页编码的样式和JS函数)。
  2. 最大限度地减少变更工作。(如果客户要求您更改网站的按钮颜色,则需要一页一页地进行操作)。
  3. 减少加载时间(如果CSS和JS重复,则意味着单个页面的大小增加并且下载耗时。但是普通的CSS JS无需一次又一次地下载)。
  4. 远程使用。(您可以将常见的CSS js JS放置在远程位置。不是同一台托管服务器)
  5. 减少错误修复时间。如果一个功能中有错误,则需要逐页修复嵌入式JS和CSS中的错误。
  6. 增加SEO(只需将内容与元数据分开)
  7. 代码更清晰,更易于理解(如果将所有代码都嵌入一个文件中,则调试和代码清晰度将消失。每一页将是一个很长的页面)。
  8. 此外,这将帮助您减小产品尺寸。
  9. 但是您仍然可以考虑在同一页面中嵌入最独特的内容。

0

我们不应该在HTML中嵌入样式/脚本,因为

嵌入式样式/脚本必须随每个页面请求一起下载:

这些样式不能被浏览器缓存并重新用于其他页面。因此,建议嵌入尽可能少的CSS / JS。

相反,当我们使用链接绑定CSS /脚本时,我们使用链接COZ

多个页面请求的网站速度提高:

当一个人第一次访问您的网站时,他们的浏览器会下载当前页面的HTML以及链接的CSS和JS文件。当他们导航到另一个页面时,他们的浏览器只需要下载新页面的HTML,就缓存了CSS / JS文件,因此不需要再次下载。这可能会有很大的不同,特别是如果您具有较大的样式和脚本文件。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.