65.9K
CodeProject 正在变化。 阅读更多。
Home

HTTP Handler 结合多个文件、缓存并提供压缩输出以加快页面加载速度

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.89/5 (51投票s)

2008年8月28日

CPOL

5分钟阅读

viewsIcon

273468

一个 HTTP Handler,它将多个 CSS、JavaScript 或 URL 组合成一个响应,以加快页面加载速度。它可以组合、压缩和缓存响应,从而加快页面加载速度并提高 Web 应用程序的可伸缩性。

引言

为了更好的代码可维护性,使用多个小的 JavaScript 和 CSS 文件而不是一个大的 JavaScript/CSS 文件是一个好习惯,但从网站性能的角度来看却很糟糕。虽然你应该将 JavaScript 代码写成小文件,并将大的 CSS 文件分解成小块,但当浏览器请求这些 JavaScript 和 CSS 文件时,它会为每个文件发送一个 HTTP 请求。每次 HTTP 请求都会导致浏览器与服务器之间的网络往返,而到达服务器和返回浏览器的延迟称为延迟。因此,如果你有四个 JavaScript 文件和三个 CSS 文件由页面加载,那么你就会浪费七次网络往返的时间。在美国境内,平均延迟为 70 毫秒。所以,你浪费了 7x70 = 490 毫秒,大约半秒的延迟。在美国境外,平均延迟约为 200 毫秒。这意味着 1400 毫秒的等待时间。在 CSS 和 JavaScript 完全加载之前,浏览器无法正确显示页面。因此,延迟越大,页面加载速度越慢。

延迟有多糟糕

这张图表显示了每次请求延迟如何累加并引入显著的页面加载延迟。

image_16.png

你可以通过使用 CDN 来减少等待时间。阅读我关于使用 CDN 的上一篇博文。然而,一个更好的解决方案是使用一个 HttpHandler,它将多个文件组合起来并将它们作为单个输出提供。所以,你不需要放置许多 <script> 或 <link> 标签,你只需要放置一个 <script> 和一个 <link> 标签,并将它们指向 HttpHandler。你告诉 Handler 要组合哪些文件,它就会在一个响应中提供这些文件。这可以避免浏览器发出许多请求,并消除延迟。

image_18.png

在这里你可以看到,如果你能将多个 JavaScript 和 CSS 文件合并到一个文件中,你会获得多少改进。

在典型的网页中,你会看到很多引用的 JavaScript。

<script type="text/javascript" src="http://www.msmvps.com/Content/JScript/jquery.js">
</script>
<script type="text/javascript" src="http://www.msmvps.com/Content/JScript/jDate.js">
</script>
<script type="text/javascript"
    src="http://www.msmvps.com/Content/JScript/jQuery.Core.js">
</script>
<script type="text/javascript"
    src="http://www.msmvps.com/Content/JScript/jQuery.Delegate.js">
</script>
<script type="text/javascript"
    src="http://www.msmvps.com/Content/JScript/jQuery.Validation.js">
</script>

与其使用这些单独的 <script> 标签,你只需使用一个 <script> 标签,通过 Http Handler 来提供所有脚本。

<script type="text/javascript" 
    src="HttpCombiner.ashx?s=jQueryScripts&t=text/javascript&v=1" >
</script>

HTTP Handler 读取配置文件中定义的文件名,并将所有这些文件组合起来,作为单个响应提供。它以 gzip 压缩格式提供响应,以节省带宽。此外,它还会生成一个正确的缓存头,以便在浏览器缓存中缓存响应,这样,浏览器在未来的访问中就不会再次请求它。

在查询字符串中,你可以在 "s" 参数中指定文件集名称,在 "t" 参数中指定内容类型,在 "v" 参数中指定版本号。由于响应已被缓存,如果你更改了该集中的任何文件,则必须增加 "v" 参数值,以使浏览器重新下载响应。

使用这个 HttpHandler,你也可以提供 CSS。

<link type="text/css" rel="stylesheet"
 href="HttpCombiner.ashx?s=CommonCss&t=text/css&v=1" ></link>

以下是如何在 web.config 中定义文件集。

<appSettings>
    <add key="jQueryScripts" 
        value="~/Content/JScript/jquery.js,
            ~/Content/JScript/jDate.js,
            ~/Content/JScript/jQuery.Core.js,
            ~/Content/JScript/jQuery.Delegate.js,
            ~/Content/JScript/jQuery.Validation.js"    
    />
    <add key="CommonCss"
        value="~/App_Themes/Default/Theme.css,
            ~/Css/Common.css,
            ~/Controls/Grid/grid.css"
    />
</appSettings>

使用 HttpCombiner 的示例网站

我创建了一个简单的测试网站来向你展示 HttpCombiner 的用法。该测试网站有两个 CSS 和两个 JS 文件。default.aspx 文件通过 HttpCombiner.ashx 只使用一个 <link><script> 标签来请求它们。

image_4.png

这是 Default.aspx 的内容。

image_12.png

在这里你看到,有一个 <link> 标签向 HttpCombiner.ashx 发送请求以提供名为 Set_Css 的文件集,还有一个 <script> 标签请求名为 Set_Javascript 的文件集。

属于这两个文件集的文件的定义在 web.config 文件中。

image_30.png

Handler 的工作原理如下:

  • 首先,它读取在 "s" 参数中传递的文件集名称。
  • 然后,它获取 web.config 中为该文件集定义的文件。
  • 它读取单个文件并将其存储在缓冲区中。
  • 然后对缓冲区进行 gzip 压缩。
  • 将压缩后的缓冲区发送到浏览器。
  • 压缩后的缓冲区存储在 ASP.NET 缓存中,以便后续对同一文件集的请求可以直接从缓存中提供,而无需从文件系统或外部 URL 读取单个文件。

Handler 的优势:

  • 它节省了网络往返。一个文件集中的文件越多,节省的网络延迟就越多。这提高了性能。
  • 它将整个组合后的响应以压缩形式进行缓存,从而避免了反复从文件系统读取文件和进行压缩。这提高了可伸缩性。

HttpHandler 的工作原理

首先,Handler 从查询字符串中读取要使用的文件集、类型和版本。

image_20.png

如果文件集已缓存,则直接从缓存中写入。否则,将文件逐个加载并存储在 MemoryStream 中。如果浏览器支持压缩输出,则使用 GZipStream 对 MemoryStream 进行压缩。

image_22.png

在组合所有文件并进行压缩后,将组合后的字节缓存起来,以便后续请求可以直接从缓存中提供。

image_24.png

GetFileBytes 函数读取文件或 URL 并返回字节。因此,你可以使用网站内的文件的虚拟路径,也可以使用托管在其他域上的外部 Javascript/CSS 文件的 URL。

image_26.png

WriteBytes 函数包含了很多智慧。它会根据字节是否为压缩形式来生成一个合适的头。然后它会生成一个合适的浏览器缓存头,以便浏览器缓存响应。

image_28.png

如何使用此 Handler:

  • HttpCombiner.ashx 包含在你的项目中。
  • web.config<appSettings> 部分定义文件集。
  • 将网站中的 <link><script> 标签更改为指向 HttpCombiner.ashx,格式如下:
    HttpCombiner.ashx?s=<setName>&t=<contentType>&v=<versionNo>

结论

就是这样!让你的网站加载更快,获得更多用户,并赚取更多收入。

你还应该阅读我之前的关于延迟和组合脚本加载以提高感知速度以及如何充分利用浏览器缓存的文章。

© . All rights reserved.