博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

1.如何让网站的每个页面只加载一个CSS文件满足所有要求?

    CSS压缩、CSS Sprites已经是广泛应用的网站提速的手段,减少外部文件的Request,是Best Practices for Speeding Up Your Web Site中的第一条,让所有页面只需要加载一个CSS文件的作用不言而喻。实际应用的参考如Yahoo首页加载了2个CSS文件,Yahoo首页的CSS文件总大小为36.2kb,淘宝首页的只加载了一个CSS文件大小为10.2kb。而sohu的首页加载了4个CSS文件,总大小9.1kb却需要4次请求,还不如直接合并到html里。在实际操作中,可以通过合并CSS文件来实现,但是对CSS的维护有极大的不便。如何在不影响网站当前的CSS文件组织、维护的情况下做到让每个页面只加载一个CSS文件哪?

    (1).指定一个通用的Web服务器端处理CSS请求的程序,以ASP.NET 为例,我们可以在根目录下创建一个HttpHandler用来接收所有页面的CSS请求。

public class Handler : IHttpHandler {
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType
= "text/css";
}

public bool IsReusable {
get {
return false;
}
}
}

    (2).根据现有页面加载的所有CSS,把单独的CSS路径信息作为HttpHandler处理程序的参数传入。即多个<link>标签转化为一个<link>标签,而原有的请求信息转化为参数形式。

<link type="text/css" rel="Stylesheet" href="styles/common.css"/>
<link type="text/css" rel="Stylesheet" href="styles/skin1/skin1.css"/>

   转化后:

<link type="text/css" rel="Stylesheet" href="Handler.ashx?common=/styles/common.css&skin1=/styles/skin1/skin1.css" />

    (3).在HttpHandler处理程序中根据参数信息,读取不同的CSS文件内容并发送到输出流。上述代码为了阐述问题只包含必要的部分,如果在上一步中对参数的形式进行了格式化,在当前代码中提取参数时要做相应的处理。

public class Handler : IHttpHandler {
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType
= "text/css";
for (int i = 0; i < context.Request.QueryString.Count; i++)
{
string path =context.Request.MapPath(context.Request.ApplicationPath+context.Request.QueryString[i]);
using (TextReader tr = new StreamReader(path))
{
context.Response.Write(tr.ReadToEnd()
+"\n");
}
}
}
public bool IsReusable {
get {
return false;
}
}
}

2.如何让网站根据不同的浏览器(如IE6)的加载不同的CSS文件?

  开发或改版网站时,IE浏览器由于个别版本不遵循标准,并且有数量众多臭名昭著的BUG,给我们带来了很多困难。为了兼容IE,我们不得不经常用条件注释和CSS hack处理它。我们理想的方式是先针对标准的浏览器开发,如FireFox。然后在IE下测试并达到兼容的目标。通过在后台控制加载的方式,我们不需要条件注释,不需要对CSS添加无意义的属性或hack来兼容IE。个人认为,为IE提供另一套CSS或部分独立的CSS所需要的时间是少于通过CSS hack或牺牲IE不支持的CSS特性进行兼容的时间的。

public class Handler : IHttpHandler {

public void ProcessRequest(HttpContext context)
{
context.Response.ContentType
= "text/css";
for (int i = 0; i < context.Request.QueryString.Count; i++)
{
string path =context.Request.MapPath(context.Request.ApplicationPath+context.Request.QueryString[i]);
if (context.Request.Browser.Browser == "IE" && context.Request.Browser.Version == "6.0")
{
path
= path.Replace(".css", "-ie6.css");
}
using (TextReader tr = new StreamReader(path))
{
context.Response.Write(tr.ReadToEnd()
+"\n");
}
}
}

public bool IsReusable {
get {
return false;
}
}
}

3.如何在网站改版时,对正式站的测试不影响用户体验?

    有的时候我们在测试站上进行了改版的测试,可是在部署到正式站时因为测试不足或测试站与正式站的细微差别,导致测试期间对用户体验造成了不良的影响。通过后台控制,完全可以针对不同浏览器、同一浏览器的不同版本分别测试,可以降低对用户体验的影响。要达到不影响用户体验的程度又可以使用正式站作为测试环境,我们只需要在上述代码中加入对客户端IP的限制即可达到这一目的。

public class Handler : IHttpHandler {

public void ProcessRequest(HttpContext context)
{
context.Response.ContentType
= "text/css";
for (int i = 0; i < context.Request.QueryString.Count; i++)
{
string path =context.Request.MapPath(context.Request.ApplicationPath+context.Request.QueryString[i]);
if (context.Request.UserHostAddress == "127.0.0.1")
{
path
= path.Replace(".css", "-test.css");
}
using (TextReader tr = new StreamReader(path))
{
context.Response.Write(tr.ReadToEnd()
+"\n");
}
}
}

public bool IsReusable {
get {
return false;
}
}
}

    同样的原理,其他的动态网站,如PHP网站等完全可以使用相同的逻辑进行类似的处理。既可以保留原有文件结构和维护方式,又可以减少请求数,把多个<link>标签合并为一个对于前台工组人员只要了解了规定好的原则完全可以胜任。对开发人员来说,实现更负责的自定义逻辑也不是问题,比如针对所有浏览器加载的css、针对不同浏览器加载的css、同一浏览器加载的不同的css、不同年份、节日、月份加载的CSS等。

补充:

上面的方式同样可以只加载一个JS文件。这篇文章Combine CSS with JS and make it into a single download提到了可以把CSS和JavaScript写到同一个文件,或者在请求时输出一个文件。我个人认为还是应该区分开CSS和JavaScript请求,因为该文章中提到的方法需要针对代码加<!---->和//注释用于浏览器正确的解析和忽略,这样对原有代码需要进行改造,编写和维护也变得小心翼翼才可以。还有就是我在FireBug和Fiddle2中查看同一文件分别写在<link><script>标签中发现请求还是2次

作者:Tjerry
出处:http://easygame.cnblogs.com/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。