JavaScript在网站中越来越流行,从通过 AJAX 为你的页面添加特殊效果。
不幸的是,这些功能是有代价的:你通常必须依赖庞大的JavaScript库,这些库可能为页面增加几十甚至几百KB。
用户讨厌等待,因此这里有一些你可以用来精简网站的技巧。
(查看第2部分 (用于可下载示例。)
找出臃肿部分
像任何优化技术一样,测量并找出哪些部分耗时最长是有帮助的。你可能会发现你的图片和 HTML 超过了脚本。以下是几种调查方法:
1. 该 Firefox Web开发者工具栏 让您查看页面的文件大小分解(右键单击 > 网页开发者 > 信息 > 查看文档大小)。查看分解,看看哪些文件占用了大部分带宽:

2. Firebug插件 也显示文件分解——只需转到“网络”选项卡。您还可以按文件类型过滤:

3. OctaGate站点计时器 提供一个清晰的在线的图表,显示每个文件下载所需的时间:

对臃肿感到厌恶?决定你的JavaScript需要优化?让我们开始吧。
压缩你的JavaScript
首先,您可以尝试让JavaScript文件本身更小。有许多工具可以通过移除空白和注释来“压缩”您的文件。
您可以这样做,但这些工具可能会很挑剔,如果您的代码格式不正确,可能会进行不必要的更改。以下是可以做的:
1. 运行JSLint (在线 或者 可下载版本) 来分析您的代码并确保其格式良好。
2. 使用 YUI 压缩器 从命令行压缩您的JavaScript。有一些 在线打包工具,但 YUI 压缩器(基于Rhino)实际上会分析您的源代码,因此在压缩时更改它的可能性很小,并且它是可脚本化的。
安装 YUI 压缩器(需要Java),然后从命令行运行它(x.y.z 是您下载的版本):
java -jar yuicompressor-x.y.z.jar myfile.js -o myfile-min.js
这会压缩 myfile.js 并输出到 myfile-min.js。Rhino 会移除空格、注释,并在适当的地方缩短变量名。
使用 Rhino,我打包原始的 JavaScript 并将打包后的版本部署到我的网站。
调试压缩后的JavaScript
调试 压缩后的 JavaScript 可能非常难以调试,因为变量被重命名了。我建议为您的页面创建一个引用原始文件的“调试”版本。一旦测试并让页面正常工作,打包它,测试打包后的版本,然后部署。
如果您有一个像 jsunit这样的单元测试框架,测试打包后的版本应该不难。
消除乏味工作
因为反复输入这些命令可能很繁琐,您可能想要 创建一个脚本来执行打包命令这个 .bat 文件会压缩每个 .js 文件并创建 .js.packed 文件:
compress_js.bat:
for /F <span class="tex-inline-html" alt="F in ('dir /b *.js') do java -jar custom_rhino.jar -c ">F in ('dir /b ·.js') do java -jar custom_rhino.jar -c </span>F > %%F.packed 2>&1
当然,你可以使用更好的语言如 perl 或 bash 来满足你的需求。
优化JavaScript放置位置
将你的JavaScript放在文档末尾 HTML 如果可能的话,注意 Google Analytics 和其他统计跟踪软件希望放在关闭 </body> 标签之前。
这样可以让大部分页面内容(如图片、表格、文本)优先加载和渲染。用户看到内容在加载,页面看起来响应迅速。此时,重量级的 JavaScript 可以到最后再开始加载。
我以前把所有 JavaScript 都塞进 <head> 部分,但这是不必要的。只有页面加载初期绝对需要的核心文件才应放在那里。其余的文件,比如炫酷的菜单效果、过渡动画等,可以稍后加载。你应该让页面一开始就显得响应(即,有内容在加载)。
按需加载JavaScript
一个 AJAX 模式 是 动态加载JavaScript,或者当用户运行需要你脚本的功能时。你可以使用以下方法从任何域名加载任意 JavaScript 文件: 导入函数:
function $import(src){
var scriptElem = document.createElement('script');
scriptElem.setAttribute('src',src);
scriptElem.setAttribute('type','text/javascript');
document.getElementsByTagName('head')[0].appendChild(scriptElem);
}
// import with a random query parameter to avoid caching
function $importNoCache(src){
var ms = new Date().getTime().toString();
var seed = "?" + ms;
$import(src + seed);
}
函数 $import('http://example.com/myfile.js') 会向文档的 head 添加一个元素,就像直接包含文件一样。 $importNoCache 版本会向请求添加时间戳,强制浏览器获取新副本。
要测试文件是否完全加载,你可以这样做:
if (myfunction){
// loaded
}
else{ // not loaded yet
$import('http://www.example.com/myfile.js');
}
还有一个 AJAX 版本也 但我更喜欢这个,因为它更简单并且适用于任何域的文件。
延迟加载JavaScript
与其按需加载 JavaScript(这可能导致明显的延迟), 在后台延迟加载你的脚本。使用类似这样的方法:
var delay = 5;
setTimeout("loadExtraFiles();", delay * 1000);
这会 loadExtraFiles() 在5秒后调用,从而加载你需要的文件(使用 $import)。你甚至可以在这些导入文件的末尾添加一个函数,用于执行任何所需的初始化(或调用现有函数进行初始化)。
这样做的优点是,你仍然可以获得快速的初始页面加载,并且用户在需要使用高级功能时不会遇到停顿。
对于 InstaCalc,有一些不常用的重型图表库。我正在测试一种方法,将图表加载延迟几秒钟,同时核心功能从一开始就可用。
你可能需要重构代码以处理组件的延迟加载。一些想法:
- 使用SetTimeout定期轮询加载状态(检查包含脚本中定义的函数/变量是否存在)
- 在包含的脚本末尾调用一个函数,以通知主程序它已加载完成
缓存你的文件
另一种方法是显式设置浏览器的缓存过期时间。为此,你需要访问 PHP 或 Apache 的 .htaccess 文件,以便回传特定的缓存头(阅读更多关于缓存的内容).
重命名 myfile.js 到 myfile.js.php 并添加 以下行 到顶部:
<?php
header("Content-type: text/javascript; charset: UTF-8");
header("Cache-Control: must-revalidate");
$offset = 60 * 60 * 24 * 3;
$ExpStr = "Expires: " .
gmdate("D, d M Y H:i:s",
time() + $offset) . " GMT";
header($ExpStr);
?>
在这种情况下,缓存将在 (60 * 60 * 24 * 3) 秒或 3天。对于你自己的文件要小心使用,特别是当它们还在开发中时。我建议缓存那些不经常更改的库文件。
如果你意外地缓存了某些东西太久,可以使用 $importNoCache 技巧,在请求中添加类似“myfile.js?123456”的时间戳(该时间戳会被忽略)。由于文件名不同,浏览器会请求新版本。
设置浏览器缓存不会加快初始下载速度,但如果你的网站在多个页面中引用相同的文件,或者对于重复访问者,它会有帮助。
合并你的文件
我最初忘记的一个好方法是将多个 JavaScript 文件合并为一个。你的浏览器一次只能打开与一个网站的多个连接——考虑到建立每个连接的开销,将多个小脚本合并成一个较大的脚本是有意义的。
但你不必手动合并文件!使用脚本合并文件——查看第2部分了解示例脚本。巨大的文件难以编辑——将你的库拆分成较小的组件,以便以后合并,就像将 C 程序拆分成更小的模块一样,是很好的做法。
我应该Gzip它吗?
你可能应该这样做。我最初说不行,因为一些旧版浏览器在处理压缩内容时有问题。
但网络正在向前发展。像 Google 和 Yahoo 这样的大网站都在使用它,而且旧版浏览器中的问题并不普遍。
压缩的好处——通常文件大小减少 75% 或更多——太好了,不容忽视: 使用以下工具优化您的网站 HTTP 压缩。
全部完成?继续学习。
一旦你执行了上述技术,使用上述工具重新检查你的页面大小,以查看前后的差异。
我不是这些方法的专家——我边学边做。以下是一些深入学习参考资源:
保持你的脚本精简,并 阅读第二部分 查阅一些实际运行的示例。