Closure 編譯器服務已遭淘汰,日後將予以移除。請考慮在本機執行編譯器。
總覽
與 API 通訊說明瞭與 Closure Compiler 服務通訊的基本概念,但這個 API 只透過服務從一行 JavaScript 中去除註解。本教學課程說明如何在合理的情境中,使用 Closure Comppiler 服務:處理整個 JavaScript 檔案以大幅縮減大小。
本教學課程假設您對 JavaScript 和 HTTP 有基本的瞭解。雖然它使用 Python 指令碼將 JavaScript 提交到 Closure Compiler 服務,但您不必知道 Python 就能按照範例操作。
壓縮檔案
與 API 通訊中的範例會將 JavaScript 字串做為指令列參數傳遞給我們的編譯指令碼。不過,對實際大小的 JavaScript 程式而言,這個方法並不太有效,因為當程式碼長度超過幾行時,JavaScript 字串可能會很快就變得不理想。如果是大型程式,您可以使用 code_url
要求參數指定要處理的 JavaScript 檔案名稱。除了 js_code
以外,您也可以使用 code_url
,或替換 js_code
。
以下列 JavaScript 程式為例:
/** * A simple script for adding a list of notes to a page. The list diplays * the text of each note under its title. */ /** * Creates the DOM structure for a note and adds it to the document. */ function makeNoteDom(noteTitle, noteContent, noteContainer) { // Create DOM structure to represent the note. var headerElement = document.createElement('div'); var headerText = document.createTextNode(noteTitle); headerElement.appendChild(headerText); var contentElement = document.createElement('div'); var contentText = document.createTextNode(noteContent); contentElement.appendChild(contentText); var newNote = document.createElement('div'); newNote.appendChild(headerElement); newNote.appendChild(contentElement); // Add the note's DOM structure to the document. noteContainer.appendChild(newNote); } /** * Iterates over a list of note data objects and creates a DOM */ function makeNotes(data, noteContainer) { for (var i = 0; i < data.length; i++) { makeNoteDom(data[i].title, data[i].content, noteContainer); } } function main() { var noteData = [ {title: 'Note 1', content: 'Content of Note 1'}, {title: 'Note 2', content: 'Content of Note 2'}]; var noteListElement = document.getElementById('notes'); makeNotes(noteData, noteListElement); } main();
您可以將這個程式做為檔案,直接作為 Closure Compiler 服務傳送,作為一個大型字串。請按照下列步驟使用服務處理檔案:
- 將 JavaScript 儲存成檔案。
- 在網路上存取檔案 (例如將檔案上傳至您的網路伺服器)。
- 向 Closure Compiler 服務發出 POST 要求,如與 API 通訊中所述,但
js_code
參數會取代code_url
參數。code_url
的值必須是您在步驟 1 建立的 JavaScript 檔案網址。
例如,您可以在 tutorial2.js
檔案中找到這個範例的 JavaScript。如要使用 Closure Compiler 服務 API 處理這個檔案,請將 Python 程式從與 API 通訊改為使用 code_url
,如下所示:
#!/usr/bin/python2.4 import httplib, urllib, sys # Define the parameters for the POST request and encode them in # a URL-safe format. params = urllib.urlencode([ ('code_url', sys.argv[1]), # <--- This parameter has a new name! ('compilation_level', 'WHITESPACE_ONLY'), ('output_format', 'text'), ('output_info', 'compiled_code'), ]) # Always use the following value for the Content-type header. headers = { "Content-type": "application/x-www-form-urlencoded" } conn = httplib.HTTPSConnection('closure-compiler.appspot.com') conn.request('POST', '/compile', params, headers) response = conn.getresponse() data = response.read() print data conn.close()
注意:如要重現這個範例,Windows 使用者可能需要安裝 Python。請參閱 Python Windows 常見問題,瞭解如何在 Windows 中安裝及使用 Python。
使用下列指令將程式碼傳送至 Closure Compiler 服務:
$ python compile.py https://closure-compiler.appspot.com/closure/compiler/samples/tutorial2.js
Closure Compiler 服務會從 https://closure-compiler.appspot.com/closure/compiler/samples/tutorial2.js
擷取檔案,並在回應中傳回壓縮的 JavaScript。
如要將多個輸出檔案編譯成一個輸出檔案,請加入多個 code_url
參數,如以下範例所示:
params = urllib.urlencode([ # Multiple code_url parameters: ('code_url', 'http://yourserver.com/yourJsPart1.js'), ('code_url', 'http://yourserver.com/yourJsPart2.js'), ('compilation_level', 'WHITESPACE_ONLY'), ('output_format', 'text'), ('output_info', 'compiled_code'), ])
改善壓縮
到目前為止,範例都使用了 WHITESPACE_ONLY
的 compilation_level
,而這僅會移除註解和空白字元。使用 SIMPLE_OPTIMIZATIONS
壓縮等級時,您可以提高壓縮率。如要使用 SIMPLE_OPTIMIZATIONS
壓縮,請將 compilation_level
參數變更為 SIMPLE_OPTIMIZATIONS
:
params = urllib.urlencode([ ('code_url', sys.argv[1]), ('compilation_level', 'SIMPLE_OPTIMIZATIONS'), # <--- This parameter has a new value! ('output_format', 'text'), ('output_info', 'compiled_code'), ])
然後依以下方式執行指令碼:
$ python compile.py https://closure-compiler.appspot.com/closure/compiler/samples/tutorial2.js
輸出內容應如下所示:
var GLOBAL_document=document,$$PROP_appendChild="appendChild";function makeNoteDom(a,b,c){var d=GLOBAL_document.createElement("div");a=GLOBAL_document.createTextNode(a);d[$$PROP_appendChild](a);a=GLOBAL_document.createElement("div");b=GLOBAL_document.createTextNode(b);a[$$PROP_appendChild](b);b=GLOBAL_document.createElement("div");b[$$PROP_appendChild](d);b[$$PROP_appendChild](a);c[$$PROP_appendChild](b)}function makeNotes(a,b){for(var c=0;c<a.length;c++)makeNoteDom(a[c].title,a[c].content,b)} function main(){var a=[{title:"Note 1",content:"Content of Note 1"},{title:"Note 2",content:"Content of Note 2"}],b=GLOBAL_document.getElementById("notes");makeNotes(a,b)}main();
這個程式碼比來源程式更難以讀取,但比較小。
程式碼有多小?
如果我們將要求參數中的 output_info
從 compiled_code
變更為 statistics
,就可以看到確切的儲存空間:
Original Size: 1372 Compressed Size: 677 Compilation Time: 0
新版 JavaScript 只有原始圖片的一半。
封閉式編譯器服務如何讓這個程式更小?
在此情況下,Closure Compiler 可以藉由重新命名本機變數而縮減大小。例如,原始檔案包含以下這行程式碼:
var headerElement = document.createElement('div');
Closure Compiler 將此陳述式更改為:
var d=document.createElement("div");
Closure Compiler 會將 headerElement
符號改成 d
函式 makeNoteDom
內的任何位置,因此可以保留功能。但 headerElement
的 13 個字元已縮短為顯示三個位置的每一個字元。因此總共可省下 36 個字元。
使用 SIMPLE_OPTIMIZATIONS
進行編譯一律會保留語法有效 JavaScript 的功能,前提是程式碼不會使用字串名稱存取本機變數 (例如,eval()
陳述式)。
後續步驟
現在,您已熟悉 SIMPLE_OPTIMIZATIONS
和使用服務的基本機制,下一步就是瞭解 ADVANCED_OPTIMIZATIONS
編譯層級。這個層級需要額外步驟,才能確保您的 JavaScript 在編譯前後能夠以相同方式運作,但是會讓 JavaScript 縮小。如要瞭解 ADVANCED_OPTIMIZATIONS
,請參閱進階編譯與外部。