加快你的 Javascript,第 2 部分:可下载示例!

我很高兴人们发现 关于JavaScript优化的文章 有用的。但我犯了一个巨大而可怕的错误。一个降临在许多教程上的错误。

我没有提供实际可操作的示例供你尝试。 你可以随意谈论,但直到你有了代码,那只是理论和无力的叹息。如果没有看到代码走查(或运行!明白了吗?),很难相信它真的有效。所以这里有一些实际运行的例子来展示这些技术的实际应用:

这些例子是免费的,属于公共领域。但是,如果你觉得有用,我希望你能与朋友分享,或者 给我留言. 我喜欢了解哪些解释方式有效,以便将来能更多地采用。

现在,我们来导览一下你会在压缩包里看到的内容。

消除繁琐:使用脚本

自动化,自动化,再自动化!我创建了一组批处理文件(以及为你们 Linux/UNIX 高手准备的 .sh 文件)来帮助你入门:

  • makeall.bat:运行以下命令
  • make_libraries.bat:将 *.js 合并为 “allfiles.lib.js”,并将以 “example” 为前缀的文件合并为 “example.lib.js”。
  • pack_js.bat:压缩 *.js 并创建 *.js.packed
  • add_cache_header.bat:插入 PHP 缓存头部信息到 .js.packed 文件中,创建 js.packed.php
  • cleanup.bat:删除生成的文件,只保留原始的 .js 文件。

这些是模板——你可以修改它们以适应自己的需求。如果你发现自己反复输入某个命令,就把它写进脚本里。

压缩JavaScript

我包含了 custom_rhino.jar 用于执行压缩(更多信息).

有几个用于演示的 JavaScript 文件。第一个是 example_compressed.js,它在不同作用域(局部和全局)内含有极长的变量名。看看这个家伙,它正适合被 Rhino 压缩:

/* these names are global, so will not get compressed (could be used elsewhere) */
var LongName = 1;
var OtherLongName = 2;
var ReallyReallyLongName = 3;
var AbsurdlyLongNameImNotQuiteSureWhyAnyoneWouldUseThisButItIsGoodForExamples = 3;

/* these names are local to foo(), and will get compressed. Isn't Rhino awesome? */
function foo(){

var LongName = 1;
var OtherLongName = 2;
var ReallyReallyLongName = 3;
var AbsurdlyLongNameImNotQuiteSureWhyAnyoneWouldUseThisButItIsGoodForExamples = 3;
var LongName = 1;
var OtherLongName = 2;
var ReallyReallyLongName = 3;
var AbsurdlyLongNameImNotQuiteSureWhyAnyoneWouldUseThisButItIsGoodForExamples = 3;
(repeated...)
return 0; // of course :)
}

log("Compressed Example Loaded!");

典型的“JavaScript 压缩器”只会移除多余的空格和注释,这帮助不大。Rhino 实际上会分析你的代码:当它看到全局变量时,知道不应该改变其名称,因为其他脚本可能会引用它们。

但局部变量就是另一回事了。由于局部变量只在 在它们的函数内部内被引用,它们很适合被压缩。这就是 Rhino 处理后的 JavaScript:

var LongName=1;
var OtherLongName=2;
var ReallyReallyLongName=3;
var AbsurdlyLongNameImNotQuiteSureWhyAnyoneWouldUseThisButItIsGoodForExamples = 3;

function foo(){
var _1=1;
var _2=2;
var _3=3;
var _4=3;
var _1=1;
var _2=2;
var _3=3;
var _4=3;
var _1=1;
var _2=2;
...
return 0;
}
log("Compressed Example Loaded!");

有问题吗?

Rhino 践踏了变量名,并用它能找到的最短标识符替换它们:_1、_2 等等。这节省了大量空间,并且具有部分混淆代码的副作用(如果你想要这种效果的话)。

动态导入与延迟加载

现在是有趣的部分: example_imported.jsexample_delayed.js 不做任何特殊处理,除了调用一个记录函数来显示它们何时被加载。

检出 sample.html

<html>
<head>
<!-- only put scripts here if you really need to -->
</head>
<body>

<!-- Scripts that need to run first -->
<script src="import.js"></script>
<script>
/* Simple logger -- looks for div with id "log".
   We want this available from the get-go. */

function log(str){
  var logger = document.getElementById("log");
  if (logger){
    logger.innerHTML += new Date().toString() + ": ";
    logger.innerHTML += str;
    logger.innerHTML += "<br/>";
  }
}
</script>

<!-- content, images, tables, etc. -->
Put content here...

<div id="log">
</div>

<!-- include packed version -->
<script src="example_compressed.js.packed"></script>

<!-- dynamic import -->
<script>
    $import('example_imported.js');
</script>

<!-- delayed loading -->
<script>
    function loadDelayedScripts(){
        $import('example_delayed.js');
    }

    var delay = 5; // wait and then load the file
    setTimeout("loadDelayedScripts()", delay * 1000);
</script>

<!-- other heavy scripts, tracking code, etc. -->
</body>
</html>

看看 结果:

sample_html.png

注意 $import 会立即执行,而延迟加载则在5秒后发生。所有脚本都调用 log 函数,但它可以是任何回调,比如 registerLoadEvent() 或者 displayHiddenFeature()。剩下的就靠你想象了。

创建库文件

将较小的文件合并成一个较大的文件也会很有帮助,尤其是当它们不经常变化时。这会减少浏览器发出的请求数量,并且你无需为每个文件承担开销。

下载一个10k的脚本比下载十个1k的脚本更快——浏览器一次只能打开一定数量的连接。既然连接已经建立,你不如塞入一个更大的文件。

这个 UNIX “cat”(或Windows的“type”)命令非常适合这个操作。如果你设置一个过滤器(例如 *.js),可以将具有相同前缀的文件合并成一个库:

cat *.js > allfiles.lib.js
cat example*.js > example.lib.js

而且,由于这个库以 .js 结尾,它会在我们的打包脚本中与其他 .js 文件一起被压缩。

添加 PHP 缓存头部

最后一步是给文件添加缓存头。有一个通用的“set_cache_header.php”文件,它与打包后的 JavaScript(.js.packed)结合,生成 .js.packed.php 文件。假设你的服务器已配置为提供 PHP, 这将设置缓存头为3天(将其改为 任意你喜欢的数字).

永远保持学习

学习永无止境——我很想知道你还使用了哪些技巧来加速 JavaScript 或自动化“构建”过程。

请记住,你可以实现各种有趣的回调。脚本加载后,可以调用函数来显示页面中先前隐藏的功能:随着脚本的加载,菜单项/图片/文本可以出现。或者,你只需有一个主脚本, $imports 其他的,这样你就不需要修改你的 HTML 文件如果你添加一个新的 JavaScript 文件(一些 JavaScript 库就是这样做的)。可能性还有很多:使用其中一些、全部或都不使用。尝试并学习哪些对你有效。

祝你编程愉快。

本系列其他文章

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

加入 45 万月度读者

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