乐趣区

高性能网站建设指南规则78避免CSS表达式使用外部JavaScript和CSS

避免 CSS 表达式

使用 CSS 表达式将背景色设置为每小时变化一次:

backgroud-color: expression((new Date()).getHours() % 2 ? "#FFF" : "#000");

对于低版本 IE 不支持 min-width, 可以识别表达式,而其他浏览器识别静态配置:

width: expression(document.body.clientWidth < 600 ? "600px" : "auto");
min-width: 600px;

更新表达式

表达式的问题在于对其进行的求值的频率比人们期望的要高。它们不只是页面呈现和大小改变时求值,当页面滚动、甚至用户鼠标在页面上移过时都要求值。

围绕问题展开工作

用两种技术可以避免 css 表达式产生这一问题——创建一次性表达式和使用事件处理器取代 css 表达式。

一次性表达式

<style>
p {background-color: expression( altBgcolor(this) );
}
</style>
<script type="text/javascript">
function altBgcolor(elem) {elem.style.backgroundColor = (new Date()).getHours() % 2 ? "#F08A00" : "#B8D4FF";}
</script>

css 表达式调用了 altBgcolor() 函数,而该函数将样式的 backgroud-color 属性设置为一个明确的值,并移除了 CSS 表达式。

事件处理器

当浏览器的大小改变时,这个例子使用 setMinWidth() 函数来修改所有段落元素的大小

function setMinWidth() {var aElements = document.getElementsByTagName("p");
    for (var i = 0; i < aElements.length; i ++) {aElements[i].runtimeStyle.width = (document.body.clientWidth < 600 ? "600px" : "auto");
    }
}
if (1 != navigator.userAgent.indexOf("MSIE")) {window.onresize = setMinWidth;}

但这在第一次呈现时并不能恰当的设置段落的大小,所以需要使用”一次性表达式“介绍得方法设置初始宽度。

规则 8——使用外部 JavaScript 和 CSS

内联 vs 外置

纯粹而言,内联快一些,这主要是因为外部示例需要承担多个 HTTP 请求带来的开销。

但是 JavaScript 和 css 文件外置有机会被浏览器缓存起来。

如果你的网站的本质上能够为用户带来高完整缓存率,使用外部文件的收益就更大。如果不太可能产生完整缓存,则内联是更好的选择。

组件重用

如果你的网站中每个页面都使用了相同的 javascript 和 css, 使用外部文件可以提高这些组件的重用率。在这种情况下使用外部文件更加具有优势,因为当用户在页面间导航时,javascript 和 css 组件已经位于浏览器的缓存中了。

在典型情况下,页面之间 javascript 和 css 的重用既不可能 100% 重叠,也不可能 100% 无关。

最好的答案就是折中,将你的页面划分成几种页面类型,然后为每种类型创建单独的脚本和样式表。这比维护一个单独的文件要复杂,但通常比为每个页面维护不同的脚本和样式表要容易,并且对于给定的任意页面都只需要下载很少的多余的 javascript 和 css。

主页

我所见过的使用内联方式反而更好的一个例外是主页。

页面查看

主页拥有没有很高的页面查看数量,然而,通常每个会话只有一个页面查看。

空缓存 vs 完整缓存

完整缓存的百分比要比其他网站更低。出于安全的原因,很多用户选择在每次关闭浏览器时清空缓存。下一次用户打开浏览器时,产生的是一个主页的空缓存页面查看。

组件重用

重用率很低,很多主页是用户来到网站后访问的唯一一个页面,因此它们谈不上重用。

分析了这些基准,我们更加倾向于适用内联,当然,没有适用于所有主页的唯一答案。

两全其美

这里介绍得两项技术使你既可以获得内联的优势,同时也能缓存外部文件。

加载后下载

对于作为多次页面查看中的第一次的主页,我们希望为主页内联 javascript 和 css,但又能为所有后续页面查看提供外部文件。这可以通过在主页加载完成后动态下载外部组件来实现(通过 onload 事件)。这能够将外部文件放到浏览器的缓存中以便用户接下来访问其他页面。

这些页面中 javascript 和 css 被加载到页面中两次(先是内联的,然后是外部的)。要使其能够工作,必须处理双重定义。例如脚本,可以定义但不能执行函数(至少不能让用户察觉)。使用了相对单位(百分比或 em)的 css 如果指定两次可能会产生问题。将这些组件放到一个不可见的 IFrame 中是一种更好的方式。

动态内联

这可以通过使用前一个例子中的加载后下载技术来完成。当用户第一次访问页面时,服务器发现没有 cookie, 于是生成一个内联了组件的页面。然后服务器添加 javascript 来在页面加载后动态下载外部文件 (并设置 cookie)。下一次访问页面时,服务器看到了 cookie,就会生成一个使用外部文件的页面。

这种方式的美好之处在于它的宽容。即便 cookie 的状态和缓存的状态不匹配,页面也能够工作,只是没有本应该的那么优化而已。

退出移动版