Note
Usage
使用 command line 執行 Java jar file:
java -jar compiler.jar --指令
Main
-
--compilation_level:設定 compile 的等級,預設為 SIMPLE - SIMPLE: 修改 locale variable - ADVANCED - EX:--compilation_level SIMPLE_COMPILATIONS -
--js:要進行 compile 的 JavaScript file 路徑;可以使用*一次添加複數檔案,或是!*排除複數檔案 - EX:--js 'JS1.js' 'JS2.js'、--js 'JS1.js' --js 'JS2.js' -
--js_output_file:匯出的檔案名稱及路徑 - EX:--js_output_file 'compiledJS.js' -
--externs:引用的 library。設定此參數會排除 JavaScrip file 中外部檔案的 variables。 * jQuery 必須使用 Google Closure Library 中提供的檔案 - EX:--externs './path/jquery-3.1.js' --externs './path/semantic-ui.js'
Other
-
--formatting:設定匯出檔案的格式- PRETTY_PRINT:匯出的檔案斷行
- EX:
--formatting PRETTY_PRINT
-
--generate_exports:設定是否識別/** @export */並將註記的 variable 作為 symbol 處理- EX:
--generate_exports true
- EX:
-
--export_local_property_definitions:能夠設定/** @export */於 locale scope- EX:
--export_local_property_definitions true
- EX:
-
--force_inject_library:強制於匯出的 js 檔中加入指定名稱的 library- EX:
--force_inject_library es6_runtime:匯出的 js 檔中加入相容於 es6 的 polyfill library
- EX:
-
--isolation_mode:將匯出的程式包裹在 function 中- EX:
//Command 參數:
//--compilation_level ADVANCED
//--generate_exports true
//--isolation_mode IIFE
//Import
/** @export */
class Citizen {
constructor(name) {
this.name = name;
}
/** @export */
sayHello(to) {
let output = this.name + 'say: "Hello! "'+ to.name +'!';
console.log(output);
}
}
//Export
//NOTE: 為方便理解, 部分屬性名稱與實際輸出不同
function() {
var global = this;
function a (name) {
this.name = name || "";
}
a.prototype.a = function (a) {
let output = this.name + 'say: "Hello! "'+ a.name +'!';
console.log(output);
}
a.prototype.sayHello = a.prototype.a;
global["Citizen"] = a;
}.call(this);
Feature
- ES6會被 compile 為 ES5
ADVANCED_OPTIMIZATIONS
- 修改 local variable
- 修改 global variable
- 移除未被使用的 code
- 將部分 functions/variables 修改為 inline 呼叫的方式:
// Before
function hello () {console.log("hello")};
hello();
// After
console.log("hello");
- 若要避免 code 被修改,則需做 export 處理
Note
- 以
name作為 key 的話,key 不會被修改。
//Before
var customer = {name: "John"}
window["customer"] = customer;
//After
var a= {name: "John"}
window["customer"] = a;
Export Symbols
避免 API 被修改的方法
Solution 1:
- Closure Compiler 進行編譯時不會修改 String。於作為 Symbol 的變數後在 global scope 以 String 重新宣告 variables:
var customer = {
name: "Peter",
gender: "male",
hello: function () {console.log("hello " + this.name);}
}
window["customer"] = customer;
customer["name"] = customer.name;
customer["gender"] = customer.gender;
customer["hello"] = customer.hello;
customer.hello();
- 將變數中屬性的 key 以 String 表示:
var customer = {
name": "Peter",
"gender": "male",
"hello": function () {console.log("hello " + this["name"]);}
}
window["customer"] = customer;
customer["hello"]();
Solution 2
- 使用指令
—-generate_exports true及--export_local_property_definitions true; 並將 Google Closure Library 中的 base.js 設為--js的第一個檔案 - 需要保留的屬性/變數添加註記
@export
/** @export */
var customer = {
name: "Peter",
gender: "male",
/** @export */
hello: function () {console.log("hello " + this.name);}
}
Compile 前後比較
-
Solution 1 - 以 String 重新宣告 variables:Before 276 字 | After 164 字 - 優點:現有 code 需要修改的範圍較小 - 缺點:每個元件 API 處皆須增加數行 variables 宣告,後續維護麻煩
-
Solution 1 - 屬性的 key 以 String 表示:Before 180 字 | After 129 字 - 優點:編譯後的字數最少 - 缺點:現有 API 的使用皆須改為
componentName["PROPERTY_NAME"]的方式,修改幅度較大 -
Solution 2 -
/** @export */:Before 198 字 | After 141 + 285 字 - 285 字為重複使用的部分 - 優點:後續維護方便,僅需在註記的部分增加@export關鍵字 - 缺點:若 library 為各部分獨立 compile,則每個檔案都會多出 285 字;且現有 literal 寫法必須修改