[翻译]High Performance JavaScript(027)

第九章

Building and Deploying High-Performance JavaScript Applications

创建并部署高性能JavaScript应用程序

 

    According to a 2007 study by Yahoo!'s Exceptional Performance team, 40%–60% of Yahoo!'s users have an empty cache experience, and about 20% of all page views are done with an empty cache (http://yuiblog.com/blog/2007/01/04/performance-research-part-2/). In addition, another more recent study by the Yahoo! Search team, which was independently confirmed by Steve Souders of Google, indicates that roughly 15% of the content delivered by large websites in the United States is served uncompressed.

    根据Yahoo!卓越性能团队在2007年进行的研究,40%-60%的Yahoo!用户没有使用缓存的经验,大约20%页面视图不使用缓存(http://yuiblog.com/blog/2007/01/04/performance-research-part-2/)。另外,由Yahoo!研究小组发现,并由Google的Steve Souders所证实的一项最新研究表明,大约15%的美国大型网站所提供的内容没有压缩。

 

    These facts emphasize the need to make sure that JavaScript-based web applications are delivered as efficiently as possible. While part of that work is done during the design and development cycles, the build and deployment phase is also essential and often overlooked. If care is not taken during this crucial phase, the performance of your application will suffer, no matter how much effort you've put into making it faster.

    这些事实强调有必要确保那些基于JavaScript的网页应用尽量高效地发布。虽然部分工作在设计开发过程中已经完成,但构建和部署过程也很重要且往往被忽视。如果在这个关键过程中不够小心,你应用程序的性能将受到影响,无论你怎样努力使它更快。

 

    The purpose of this chapter is to give you the necessary knowledge to efficiently assemble and deploy a JavaScript-based web application. A number of concepts are illustrated using Apache Ant, a Java-based build tool that has quickly become an industry standard for building applications for the Web. Toward the end of the chapter, a custom agile build tool written in PHP5 is presented as an example.

    本章的目的是给你必要的知识,有效地组织并部署基于JavaScript的Web应用程序。一些概念使用Apache Ant进行说明,它是一个基于Java的创建工具,并很快成为开发网页应用程序的工业标准。在本章末尾,给出了一个用PHP5写的定制灵活的开发工具的例子。

 

Apache Ant

 

    Apache Ant (http://ant.apache.org/) is a tool for automating software build processes. It is similar to make, but is implemented in Java and uses XML to describe the build process, whereas make uses its own Makefile format. Ant is a project of the Apache Software Foundation (http://www.apache.org/licenses/).

    Apache Ant(http://ant.apache.org/)是一个自动构建软件的工具。它类似于make,但在Java中实现,并使用XML来描述生成过程,而make使用它自己的Makefile文件格式。Ant是Apache软件基金会的一个项目:(http://www.apache.org/licenses/)。

 

    The main benefit of Ant over make and other tools is its portability. Ant itself is available on many different platforms, and the format of Ant's build files is platform independent.

    Ant与make等其他工具相比,优势在于它的可移植性。Ant本身可用在许多不同平台上,Ant开发文件的格式与平台无关。

 

    An Ant build file is written in XML and named build.xml by default. Each build file contains exactly one project and at least one target. An Ant target can depend on other targets.

    默认的Ant开发文件为XMl格式的build.xml。每个开发文件只包含一个项目和至少一个目标体。一个Ant目标体可依赖于其他目标体。

 

    Targets contain task elements: actions that are executed atomically. Ant comes with a great number of built-in tasks, and optional tasks can be added if needed. Also, custom tasks can be developed in Java for use in an Ant build file.

    目标体包含任务元素是一些自动运行的动作。Ant配有大量内置任务,如果需要还可以添加可选任务。此外,Ant创建文件中用到的自定义任务可用Java开发。

 

    A project can have a set of properties, or variables. A property has a name and a value. It can be set from within the build file using the property task, or might be set outside of Ant. A property can be evaluated by placing its name between ${ and }.

    一个项目可有一个属性或变量的集合。一个属性有一个名字和一个值。它可以在开发文件中使用property任务设置,或者在Ant之外设置。引用属性的方法是:将属性名放在${和}之间。

 

    The following is an example build file. Running the default target (dist) compiles the Java code contained in the source directory and packages it as a JAR archive.

    下面是一个开发文件的例子。运行默认目标(dist)编译源码目录中的Java代码并封装为一个JAR文档。

 

<?xml version="1.0" encoding="UTF-8"?>
<project name="MyProject" default="dist" basedir=".">


  <!-- set global properties for this build -->
  <property name="src" location="src"/>
  <property name="build" location="build"/>
  <property name="dist" location="dist"/>


  <target name="init">
    <!-- Create the time stamp -->
    <tstamp/>
    <!-- Create the build directory structure used by compile -->
    <mkdir dir="${build}"/>
  </target>


  <target name="compile" depends="init" description="compile the source">
    <!-- Compile the java code from ${src} into ${build} -->
    <javac srcdir="${src}" destdir="${build}"/>
  </target>


  <target name="dist" depends="compile" description="generate the distribution">
    <!-- Create the distribution directory -->
    <mkdir dir="${dist}/lib"/>
    <!-- Put everything in ${build} into the MyProject-${DSTAMP}.jar file -->
    <jar jarfile="${dist}/lib/MyProject-${DSTAMP}.jar" basedir="${build}"/>
  </target>


  <target name="clean" description="clean up">
    <!-- Delete the ${build} and ${dist} directory trees -->
    <delete dir="${build}"/>
    <delete dir="${dist}"/>
  </target>


</project>

 

    Although Apache Ant is used to illustrate the core concepts of this chapter, many other tools are available to build web applications. Among them, it is worth noting that Rake

(http://rake.rubyforge.org/) has been gaining popularity in recent years. Rake is a Rubybased build program with capabilities similar to make. Most notably, Rakefiles (Rake's version of Makefiles) are written using standard Ruby syntax, and are therefore platform-independent.

    虽然这里使用Apache Ant来说明本章的核心概念,还是有很多其它工具可用于开发网页应用程序。其中,值得一提的是Rake(http://rake.rubyforge.org/)已在最近几年获得普及。最值得注意的是,Rakefile(Rake版的Makefile)使用标准Ruby语法书写,因此具有平台无关性。

 

Combining JavaScript Files  合并JavaScript文件

 

    According to Yahoo!'s Exceptional Performance team, the first and probably most important guideline for speeding up your website, especially for first-time visitors, is to reduce the number of HTTP requests required to render the page (http://yuiblog.com/blog/2006/11/28/performance-research-part-1/). This is where you should start looking for optimizations because combining assets usually requires a fairly small amount of work and has the greatest potential benefit for your users.

    根据Yahoo!卓越性能团队的研究,第一个也是最重要的提高网站速度的准则,特别针对那些第一次访问网站的用户,是减少渲染页面所需的HTTP请求的数量(http://yuiblog.com/blog/2006/11/28/performance-research-part-1/)。这是你优化工作的入手点,因为合并资源通常能够以相当少的工作为用户赢得最大的潜在利益。

 

    Most modern websites use several JavaScript files: usually a small library, which contains a set of utilities and controls to simplify the development of richly interactive web applications across multiple browsers, and some site-specific code, split into several logical units to keep the developers sane. CNN (http://www.cnn.com/), for example, uses the Prototype and Script.aculo.us libraries. Their front page displays a total of 12 external scripts and more than 20 inline script blocks. One simple optimization would be to group some, if not all, of this code into one external JavaScript file, thereby dramatically cutting down the number of HTTP requests necessary to render the page.

    大多数现代网站使用多个JavaScript文件:通常包括一个小型库,它是一个工具和控件集合以简化跨浏览器富交互网页应用程序开发,还有一些网站相关的代码,被分割成几个逻辑单元使开发者保持清晰。例如CNN(http://www.cnn.com/),使用Prototype和Script.aculo.us库。它的首页显示了12个外部脚本和超过20个内联脚本块。一个简单的优化是将某些脚本合并成一个外部JavaScript文件,而不是全部,从而大大降低渲染页面所需HTTP请求的数量。

 

    Apache Ant provides the ability to combine several files via the concat task. It is important, however, to remember that JavaScript files usually need to be concatenated in a specific order to respect dependencies. Once these dependencies have been established, using a filelist or a combination of fileset elements allows the order of the files to be preserved. Here is what the Ant target looks like:

    Apache Ant通过concat任务提供合并几个文件的能力。这很重要,但是要记住JavaScript文件通常需要按照依赖关系的特定顺序进行连接。一旦创建了依赖关系,使用filelist或组合使用fileset元素可将这些文件次序保存下来。Ant目标体的样子如下:

 

<target name="js.concatenate">
  <concat destfile="${build.dir}/concatenated.js">
    <filelist dir="${src.dir}"

      files="a.js, b.js"/>
    <fileset dir="${src.dir}"

      includes="*.js"

      excludes="a.js, b.js"/>
  </concat>
</target>

    This target creates the file concatenated.js under the build directory, as a result of the concatenation of a.js, followed by b.js, followed by all the other files under the source directory in alphabetical order.

    此目标体在开发目录下创建concatenated.js文件,它首先连接a.js,然后是b.js,然后是源目录下按字母顺序排列的其它文件。

 

    Note that if any of the source files (except possibly the last one) does not end with either a semicolon or a line terminator, the resulting concatenated file may not contain valid JavaScript code. This can be fixed by instructing Ant to check whether each concatenated source file is terminated by a newline, using the fixlastline attribute:

    注意所有源文件中(可能除了最后一个)如果不是以分号或行终止符结束的,那么合并文件的结果可能不成为有效的JavaScript代码。可这样修正:指示Ant检查每个源文件是否以新行结束,使用fixlastline属性:

 

<concat destfile="${build.dir}/concatenated.js" fixlastline="yes">
  ...
</concat>

 

Preprocessing JavaScript Files  预处理JavaScript文件

 

    In computer science, a preprocessor is a program that processes its input data to produce output that is used as input to another program. The output is said to be a preprocessed form of the input data, which is often used by some subsequent programs like compilers. The amount and kind of processing done depends on the nature of the preprocessor; some preprocessors are only capable of performing relatively simple textual substitutions and macro expansions, while others have the power of fully fledged programming languages.

                                                      —http://en.wikipedia.org/wiki/Preprocessor

    在计算机科学中,预处理器的任务是将输入数据处理成另一种编程语言所使用的数据。它输出的就是我们所说的经过预处理的输入数据,它通常被一些后续程序所使用,例如编译器。预处理的数量和类型与预处理器的性质有关,有些预处理器只能处理简单文本替换和宏扩展,而另一些则成为完全成熟的编程语言。(维基百科)

                                                      —http://en.wikipedia.org/wiki/Preprocessor

 

    Preprocessing your JavaScript source files will not make your application faster by itself, but it will allow you to, among other things, conditionally instrument your code in order to measure how your application is performing.

    预处理您的JavaScript源文件并不会使你的程序更快,但它允许你在代码中加入其它语言才有的一些特性,例如用条件体插入一些测试代码,来衡量你应用程序的性能。

 

    Since no preprocessor is specifically designed to work with JavaScript, it is necessary to use a lexical preprocessor that is flexible enough that its lexical analysis rules can be customized, or else use one that was designed to work with a language for which the lexical grammar is close enough to JavaScript's own lexical grammar. Since the C programming language syntax is close to JavaScript, the C preprocessor (cpp) is a good choice. Here is what the Ant target looks like:

    由于没有专门为JavaScript设计的预处理器,有必要使用一个词法预处理器,它足够灵活,可定制其词法分析规则,或者使用一个为某种语言设计的工具,其词法语法与JavaScript自己的词法语法足够接近。由于C语言语法接近JavaScript,C预处理器(cpp)就是一个很好的选择。Ant目标体如下:

 

<target name="js.preprocess" depends="js.concatenate">
  <apply executable="cpp" dest="${build.dir}">
    <fileset dir="${build.dir}"

      includes="concatenated.js"/>
    <arg line="-P -C -DDEBUG"/>
    <srcfile/>
    <targetfile/>
    <mapper type="glob"

      from="concatenated.js"

      to="preprocessed.js"/>
  </apply>
</target>

    This target, which depends on the js.concatenate target, creates the file preprocessed.js under the build directory as a result of running cpp on the previously concatenated file. Note that cpp is run using the standard -P (inhibit generation of line markers) and -C (do not discard comments) options. In this example, the DEBUG macro is also defined.

    这一目标体依赖于js.concatenate目标,它在前面的连接文件中运行cpp,其结果是在开发目录下创建preprocessed.js文件。注意cpp使用标准-P(抑制线标记生成)和-c(不删除注释)选项。在这个例子中还定义了DEBUG宏。

 

    With this target, you can now use the macro definition (#define, #undef) and the conditional compilation (#if, #ifdef, #ifndef, #else, #elif, #endif) directives directly inside your JavaScript files, allowing you, for example, to conditionally embed (or remove) profiling code:

    有了这个目标体,你现在可以直接在JavaScript文件中使用宏定义(#define, #undef)和条件编译(#if, #ifdef, #ifndef, #else, #elif, #endif)指令。例如,你可以使用条件体嵌入(或删除)测试代码:

 

#ifdef DEBUG


(new YAHOO.util.YUILoader({
  require: ['profiler'],
  onSuccess: function(o) {
    YAHOO.tool.Profiler.registerFunction('foo', window);
  }
})).insert();


#endif

 

    If you plan to use multiline macros, make sure you use the Unix end-of-line character (LF). You may use the fixcrlf Ant task to automatically fix that for you.

    如果你打算使用多行宏,请确保你使用了Unix的行结束符(LF)。你可用Ant任务fixcrlf自动修复它们。

 

    Another example, not strictly related to performance but demonstrating how powerful JavaScript preprocessing can be, is the use of "variadic macros" (macros accepting a variable number of arguments) and file inclusion to implement JavaScript assertions. Consider the following file named include.js:

    另一个例子,不太严格,但说明了JavaScript预编译可以多么强大,它使用了“传参数的宏”(宏接收可变数据的参数)和文件包含,以实现JavaScript断言。考虑下面这个include.js文件:

 

#ifndef _INCLUDE_JS_
#define _INCLUDE_JS_


#ifdef DEBUG
function assert(condition, message) {
  // Handle the assertion by displaying an alert message
  // possibly containing a stack trace for example.
}
#define ASSERT(x, ...) assert(x, ## __VA_ARGS__)
#else
#define ASSERT(x, ...)
#endif


#endif

 

    You can now write JavaScript code that looks like the following:

    现在你可以像下面这样书写JavaScript代码:

 

#include "include.js"


function myFunction(arg) {
  ASSERT(YAHOO.lang.isString(argvar), "arg should be a string");
  ...
#ifdef DEBUG
  YAHOO.log("Log this in debug mode only");
#endif
  ...
}

    The assertion and the extra logging code appear only when the DEBUG macro is set during development. These statements disappear in the final production build.

    断言和额外的日志代码只出现在开发过程设置的DEBUG宏块中。这些声明不会出现在最终产品中。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值