第20章 最佳實踐 (四)

 

20.4 部署

20.4.1 構建過程

你寫的代碼不應該原封不動地放入瀏覽器中,理由如下所示。

  • 知識產權問題 -- 如果把帶有完整註釋的代碼放到線上,那別人就更容易知道你的意圖,對它再利用,並且可能找到安全漏洞。
  • 文件大小 -- 書寫代碼要保證容易閱讀,才能更好地維護,但是對於性能是不利的。瀏覽器並不能從額外的空白字符或者是冗長的函數名和變量名中獲得什麼好處。
  • 代碼組織 -- 組織代碼要考慮到可維護性並不一定是傳送給瀏覽器的最好方式。
基於這些原因,最好給 JavaScript 文件定義一個構建過程。
構建過程始於在源控制中定義用於存儲文件的邏輯結構。最好避免使用一個文件存放所有的 JavaScript ,遵循以下面向對象語音中的典型模式:將每個對象或自定義類型分別放入其單獨的文件中。這樣可以確保每個文件包含最少量的代碼,使其在不引入錯誤的情況下更容易修改。另外,在使用像 CVS 或 Subversion 這類併發源控制系統的時候,這樣做也減少了在合併操作中產生衝突的風險。
記住將代碼分離成多個文件只是爲了提高可維護性,並非爲了部署。要進行部署的時候,需要將這些源代碼合併爲一個或幾個歸併文件。推薦 Web 應用中儘可能使用最少的 JavaScript 文件,是因爲 HTTP 請求是 Web 中的主要性能瓶頸之一。記住通過 <script> 標記引用 JavaScript 文件是一個阻塞操作,當代碼下載並運行的時候會停止其他所有的下載。因此,儘量從邏輯上將 JavaScript 代碼分組成部署文件。 
一旦組織好文件和目錄結構,並確定哪些要出現在部署文件中,就可以創建構建系統了。Ant 構建工具 (http://ant.apache.org) 是爲了自動化 Java 構建過程而誕生的,不過因爲其應用性和應用廣泛,而在 Web 應用開發人員中也頗流行,諸如 Julien Lecomte 的軟件工程師,已經寫了教程指導如何使用 Ant 進行 JavaScript 和 CSS 的構建自動化。
Ant 由於其簡便的文件處理能力而非常適合 JavaScript 編譯系統。例如,可以很方便地獲得目錄中的所有文件的列表,然後將其合併爲一個文件,如下所示:
該 build.xml 文件定義了兩個屬性:輸出最終文件的構建目錄,以及 JavaScript 源文件所在的源目錄。目標 js.concatenate 使用了 <concat> 元素來指定需要進行合併的文件的列表以及結果文件所要輸出的位置。<filelist> 元素用於指定 a.js 和 b.js 要首先出現在合併的文件中,<fileset> 元素指定了之後要添加到目錄中的其他所有文件,a.js 和 b.js 除外。結果文件最後輸出到 /js/output.js 。
如果安裝了 Ant ,就可以進入 build.xml 文件所在的目錄,並運行以下命令:
ant 
然後構建過程就開始了,最後生成合並了的文件。如果在文件中還有其他目標,可以使用以下代碼僅執行 js.concatenate 目標:
ant js.concatenate
可以根據需求,修改構建過程以包含其他步驟。在開發週期中引入構建這一步能讓你在部署之前對 JavaScript 文件進行更多的處理。

20.4.2 驗證

儘管現在出現了一些可以理解並支持 JavaScript 的 IDE,大多數開發人員還是要在瀏覽器中運行代碼以檢查其語法。這種方法有一些問題。首先,驗證過程難以自動化或者在不同系統間直接移植。第二,除了語法錯誤外,很多問題只有在執行代碼的時候纔會遇到,這給錯誤留下了空間;有些工具可以幫助確定 JavaScript 代碼中潛在的問題,其中最著名的就是 Douglas Crockford 的 JSLint (www.jslint.com)。
JSLint 可以查找 JavaScript 代碼中的語法錯誤以及常見的編碼錯誤。它可以發掘的一些潛在問題如下所示:
  • eval() 的使用;
  • 未聲明變量的使用;
  • 遺漏的分號;
  • 不恰當的換行;
  • 錯誤的逗號使用;
  • 語句周圍遺漏的括號;
  • switch 分支語句中遺漏的 break;
  • 重複聲明的變量;
  • with 的使用;
  • 錯誤使用的等號 (替代了雙等號或三等號);
  • 無法到達的代碼。
爲了方便訪問,它有一個在線版本,不過它也可以使用基於 Java 的 Rhino JavaScript 引擎 (www.mozilla.org/rhino/) 運行於命令行模式下。要在命令行中運行 JSLint ,首先要下載 Rhino,並從 www.jslint.com/ 下載 Rhino 版本的 JSLint 。一旦安裝完成,便可以使用下面的語法從命令行運行 JSLint 了:
java -jar rhino-1.6R7.jar jslint.js [輸入文件]
如這個例子:
java -jar rhino-1.6R7.jar jslint.js a.js b.js c.js
如果給定文件中有任何語法問題或者是潛在的錯誤,則會輸出有關錯誤和警告的報告。如果沒有問題,代碼會直接結束而不顯示任何信息。
可以使用 Ant 將 JSLint 作爲構建過程的一部分運行,添加如下一個目標:
這個目標假設 Rhino.jar 文件的位置已經由叫做 rhino.jar 的屬性指定了,同時 JSLint Rhino 文件的位置由叫做 jslint.js 的屬性指定了。Output.js 文件被傳遞給 JSLint 進行校驗,然後顯示找到的任何問題。
給開發週期添加代碼驗證這個環節有助於避免將來可能出現的一些錯誤。建議開發人員給構建過程加入某種類型的代碼驗證作爲確定潛在問題的一個方法,防患於未然。

20.4.3 壓縮

當談及 JavaScript 文件壓縮,其實在討論兩個東西:代碼長度和配重 (Wire weight) 。代碼長度指的是瀏覽器所需解析的字節數,配重指的是實際從服務器傳送到瀏覽器的字節數。在 Web 開發的早期,這兩個數字幾乎是一樣的,因爲從服務器端到客戶端原封不動地傳遞了源文件。而在今天的 Web 上,這兩者很少相等,實際上也不應相等。
1.文件壓縮
因爲 JavaScript 並非編譯爲字節碼,而是按照源代碼傳送的,代碼文件通常包含瀏覽器執行所不需要的額外的信息和格式。註釋,額外的空白,以及長長的變量名和函數名雖然提高了可讀性,但卻是傳送給瀏覽器時不必要的字節。不過,我們可以使用壓縮工具減少文件的大小。
壓縮器一般進行如下一些步驟:
  • 刪除額外的空白 (包括換行);
  • 刪除所有註釋;
  • 縮短變量名。
JavaScript 有不少壓縮工具可用,其中最優秀的是 YUI 壓縮器,http://devloper.yahoo.com/yui/compressor/ 。YUI 壓縮器使用了 Rhino JavaScript 解析器將JavaScript 代碼令牌化。然後使用這個令牌流創建代碼不包含空白和註釋的優化版本。與一般的基於表達式的壓縮器不同的地方在於,YUI 壓縮可以確保不引入任何語法錯誤,並可以安全地縮短局部變量名。
YUI 壓縮器是作爲 Java 的一個 jar 文件發佈的,名字叫 yuicompressor-x.y.z.jar ,其中 x.y.z 是版本號。可以使用以下命令行格式來使用 YUI 壓縮器:
java -jar yuicompressor-x.y.z.jar [選項] [輸入文件]
YUI 壓縮器的選項列在了下面的表格內。
例如,以下命令可以用來將 CookieUtil.js 壓縮成一個叫做 cookie.js 的文件:
java -jar yuicompressor-2.3.5.jar -o cookie.js CookieUtil.js
YUI 壓縮器也可以通過直接調用 java 可執行文件在 Ant 中使用,如下面的例子所示:
該目標包含了一個文件 output.js ,由構建過程生成的,並傳遞給 YUI 壓縮器。輸出文件指定爲同一目錄下的 output-min.js 。這裏假設 yuicompressor.jar 屬性包含了 YUI 壓縮器的 jar 文件的位置。然後可以使用以下命令運行這個目標:
ant js.compress
所有的 JavaScript 文件在部署到生成環境之前,都應該使用 YUI 壓縮器或者類似的工具進行壓縮。給構建過程添加一個壓縮 JavaScript 文件的環節以確保每次都進行這個操作。
2.HTTP 壓縮
配重指的是實際從服務器傳送到瀏覽器的字節數。因爲現在的服務器和瀏覽器都有壓縮功能,這個字節數不一定和代碼長度一樣。所有的五大 web 瀏覽器 (IE、Firefox、Safari、Chrome 和 Opera) 都支持對所接收的資源進行客戶端解壓縮。這樣服務器端就可以使用服務器端相關功能來壓縮 JavaScript 文件。一個指定了文件使用了給定格式進行了壓縮的 HTTP 頭包含在了服務器響應中。接着瀏覽器會查看該 HTTP 頭確定文件是否已被壓縮,然後使用合適的格式進行解壓縮。結果是和原來的代碼量相比在網絡中傳遞的字節數量大大減少了。
對於 Apache web 服務器,有兩個模塊可以進行 HTTP 壓縮:mod_gzip (Apache1.3.x) 和 mod_deflate (Apache 2.0.x) 。對於 mod_gzip ,可以給 httpd.conf 文件或者是 .htaccess 文件添加以下代碼啓用對 JavaScript 的自動壓縮:
#告訴 mod_gzip 要包含任何以 .js 結尾的文件
mod_gzip_item_include file \.js$
該行代碼告訴 mod_gzip 要包含來自瀏覽器請求的任何以 .js 結尾的文件。假設你所有的 JavaScript 文件都以 .js 結尾,就可以壓縮所有請求並應用何時的 HTTP 頭以表示內容已被壓縮。關於 mod_zip 的更多信息,請訪問項目網站 http://www.sourceforge.net/projects/mod-gzip/ 。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章