加快你的 Javascript 加载时间

JavaScript在网站中越来越流行,从通过 AJAX 为你的页面添加特殊效果。

不幸的是,这些功能是有代价的:你通常必须依赖庞大的JavaScript库,这些库可能为页面增加几十甚至几百KB。

用户讨厌等待,因此这里有一些你可以用来精简网站的技巧。

(查看第2部分 (用于可下载示例。)

找出臃肿部分

像任何优化技术一样,测量并找出哪些部分耗时最长是有帮助的。你可能会发现你的图片和 HTML 超过了脚本。以下是几种调查方法:

1. 该 Firefox Web开发者工具栏 让您查看页面的文件大小分解(右键单击 > 网页开发者 > 信息 > 查看文档大小)。查看分解,看看哪些文件占用了大部分带宽:

yahoo size

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

yahoo_firebug.png

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

yahoo_octagate.png

对臃肿感到厌恶?决定你的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 &middot;.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.jsmyfile.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 压缩。

全部完成?继续学习。

一旦你执行了上述技术,使用上述工具重新检查你的页面大小,以查看前后的差异。

我不是这些方法的专家——我边学边做。以下是一些深入学习参考资源:

保持你的脚本精简,并 阅读第二部分 查阅一些实际运行的示例。

本系列其他文章

  1. 如何通过 HTTP 缓存优化你的网站
  2. 如何通过 GZIP 压缩(Compression)优化你的网站
  3. 如何用 Firefox 调试 Web 应用
  4. 加快你的 Javascript 加载时间
  5. 加快你的 Javascript,第 2 部分:可下载示例!

加入 45 万月度读者

喜欢这篇文章?还有更多内容能帮你建立持久、直观的数学理解。加入通讯以获取额外内容和最新更新。