閉合編譯器是使JavaScript下載和運行速度更快的工具。它是JavaScript的真正編譯器。它沒有從源語言到機器代碼編譯,而是從JavaScript編譯到更好的JavaScript。它可以解析您的JavaScript,分析,刪除死亡代碼並重寫並最小化剩下的內容。它還檢查語法,變量引用和類型,並警告有關常見的JavaScript陷阱。
除ADVANCED
以外的彙編模式總是事後的想法,我們已經棄用了這些模式。我們認為,其他工具針對非ADVANCED
模式的性能相當,並且可以更好地集成到更廣泛的JS生態系統中。
閉合編譯器不適合任意JavaScript。為了使ADVANCED
模式生成工作JavaScript,必須考慮閉合編譯器的輸入JS代碼。
CLOSURE編譯器是一個“全世界”優化器。它希望直接查看或至少接收有關每個全局或導出變量以及每個屬性名稱的每種可能使用的信息。
它將積極刪除和重命名變量和屬性,以使輸出代碼盡可能小。如果使用全局變量或屬性隱藏的使用,這將導致損壞的輸出JS。
儘管可以編寫自定義外部文件以告訴編譯器將一些名稱保持不變,以便可以通過不屬於編譯的代碼安全地訪問它們,但這通常很乏味。
CLOSURE編譯器屬性重命名要求您始終使用obj[p]
或obj.propName
的屬性,但並非兩者兼而有之。
當您訪問帶有方括號(例如obj[p]
)或使用其他間接方法的屬性時,例如let {p} = obj;
這隱藏了從編譯器引用的屬性的字面名稱。它不知道obj.propName
是否指的是與obj[p]
相同的屬性。在某些情況下,它會注意到此問題並停止彙編錯誤。在其他情況下,它會將預先名稱propName
為簡短的事物,而不會注意到此問題,從而導致輸出JS代碼損壞。
閉合編譯器會積極地嵌入全局變量和全局變量上屬性名稱的鏈條(例如myFoo.some.sub.property
> myFoo$some$sub$property
),以使對它們的推理更加易於檢測未使用的代碼。
它試圖從執行此操作的情況下退縮,或者在執行此操作時停止錯誤會產生損壞的JS輸出,但是在某些情況下,它將無法識別出該問題,而只是在沒有警告的情況下就可以生成損壞的JS。這更有可能在不用閉合編譯器的代碼中發生。
閉合編譯器及其默認使用的外部假定目標環境是Web瀏覽器窗口。
也支持網絡工程師,但是如果您嘗試使用網絡工作人員實際上不可用的功能,則編譯器可能會不會警告您。
一些外部文件和功能已添加以關閉編譯器以支持Nodejs環境,但是它們並未積極支持,並且從未很好地奏效。
不使用base.js
的goog.module()
和goog.require()
聲明和使用模塊的JavaScript不受很好的支持。
直到2015年,ECMAScript import
語法才存在export
閉合編譯器和closure-library
為聲明和使用模塊開發了自己的手段,這仍然是定義模塊的唯一支持的方式。
編譯器確實對Ecmascript模塊實施了一些了解,但是更改Google的項目使用新的語法從未提供過值得更改成本的好處。 Google的打字稿代碼使用eCmascript模塊,但在閉合編譯器看到它們之前,它們已轉換為goog.module()
語法。因此,有效地,在Google中,Ecmasiprcript模塊支持未使用。這意味著我們不太可能注意或修復對Ecmascript模塊的支持。
過去添加了對CONCORJS模塊的支持,但在Google中不使用,並且很可能在2024年的某個時候被完全刪除。
Google Projects使用CLOSURE編譯器來:
大大減少非常大的JavaScript應用程序的代碼大小
檢查JS代碼是否錯誤,並符合一般和/或特定項目的最佳實踐。
以某種方式定義用戶可見的消息,可以用翻譯版本替換它們以創建應用程序的本地化版本。
將較新的JS功能轉換為一種表格,該表格將在缺乏對這些功能的支持的瀏覽器上運行。
將輸出應用程序分成可能根據需要單獨加載的塊。
注意:這些塊是普通的JavaScript腳本。他們不使用Ecmascript import
export
。
為了實現這些目標關閉編譯器,對其投入限制了許多限制:
使用goog.module()
和goog.require()
聲明和使用模塊。
無法積極維護對ES6 export
import
的支持。
在註釋中使用註釋來聲明類型信息並提供編譯器所需的信息,以免破壞某些代碼模式(例如@nocollapse
和@noinline
)。
要么僅使用dot-access(例如object.property
),要么僅使用動態訪問(例如object[propertyName]
或Object.keys(object)
)來訪問特定對像類型的屬性。
混合這些將隱藏屬性對編譯器的某些用途,從而在重命名屬性時導致輸出代碼損壞。
通常,編譯器希望將整個應用程序視為單個編譯。必須仔細明確地構造接口,以便允許與編譯單元外的代碼進行互操作。
編譯器假設它可以看到所有變量和屬性的所有用途,並且如果它們看起來未使用,則可以自由命名或刪除它們。
使用Externs文件將其不得刪除或重命名的任何變量或屬性告知編譯器。
有默認的外部文件聲明標準JS和DOM Global API。如果您使用較少常見的API或期望某些外部JavaScript代碼訪問您正在編制的代碼中的API,則需要更多的外部文件。
安裝編譯器的最簡單方法是使用NPM或紗線:
yarn global add google-closure-compiler
# OR
npm i -g google-closure-compiler
軟件包管理器將為您鏈接二進製文件,您可以使用以下方式訪問編譯器
google-closure-compiler
這在交互模式下啟動了編譯器。類型:
var x = 17 + 25 ;
點擊Enter
,然後點擊Ctrl+Z
(在Windows)或Ctrl+D
(在Mac/Linux上),然後再次Enter
。編譯器將以編譯的輸出響應(默認使用SIMPLE
模式):
var x = 42 ;
還可以通過Maven獲得編譯器的預編譯版本。
CLOSURE編譯器有許多可以從文件中讀取輸入的選項,將輸出寫入文件,檢查您的代碼並運行優化。這是壓縮JS程序的一個簡單示例:
google-closure-compiler --js file.js --js_output_file file.out.js
如果我們將所有源代碼(請參閱編譯多個腳本)授予編譯器,我們可以從編譯器中獲得最大的收益,這使我們可以使用ADVANCED
優化:
google-closure-compiler -O ADVANCED rollup.js --js_output_file rollup.min.js
注意:下面的輸出只是一個示例,不保持最新。每個版本期間都會更新標誌和選項Wiki頁面。
要查看所有編譯器的選項,請鍵入:
google-closure-compiler --help
--flag | 描述 |
---|---|
--compilation_level (-O) | 指定要使用的彙編級別。選項: BUNDLE , WHITESPACE_ONLY , SIMPLE (默認), ADVANCED |
--env | 確定內置外部的集合。選項: BROWSER , CUSTOM 。默認為BROWSER 。 |
--externs | 包含JavaScript外部的文件。您可以指定多個 |
--js | JavaScript文件名。您可以指定多個。標誌名稱是可選的,因為默認情況下將ARGS解釋為文件。您也可以使用微型匹配風格的全球圖案。例如,使用--js='**.js' --js='!**_test.js' 以遞歸包含所有未在_test.js 中結束的JS文件 |
--js_output_file | 主要輸出文件名。如果未指定,則將輸出寫入Stdout。 |
--language_in | 設置輸入源應符合的語言規格。選項: ECMASCRIPT3 , ECMASCRIPT5 , ECMASCRIPT5_STRICT , ECMASCRIPT_2015 , ECMASCRIPT_2016 , ECMASCRIPT_2017 , ECMASCRIPT_2018 , ECMASCRIPT_2019 , STABLE , ECMASCRIPT_NEXT |
--language_out | 設置輸出應符合的語言規格。選項: ECMASCRIPT3 , ECMASCRIPT5 , ECMASCRIPT5_STRICT , ECMASCRIPT_2015 , ECMASCRIPT_2016 , ECMASCRIPT_2017 , ECMASCRIPT_2018 , ECMASCRIPT_2019 , STABLE |
--warning_level (-W) | 指定要使用的警告級別。選項: QUIET , DEFAULT , VERBOSE |
您可以通過導入google-closure-compiler
訪問JS程序中的編譯器:
import closureCompiler from 'google-closure-compiler' ;
const { compiler } = closureCompiler ;
new compiler ( {
js : 'file-one.js' ,
compilation_level : 'ADVANCED'
} ) ;
在大多數情況下,該軟件包將提供對本機Graal二進製文件的程序化訪問,否則將返回到Java版本。
如果您有多個腳本,則應將它們與一個編譯命令一起編譯。
google-closure-compiler in1.js in2.js in3.js --js_output_file out.js
您也可以使用微型匹配風格的地球儀。
# Recursively include all js files in subdirs
google-closure-compiler ' src/**.js ' --js_output_file out.js
# Recursively include all js files in subdirs, excluding test files.
# Use single-quotes, so that bash doesn't try to expand the '!'
google-closure-compiler ' src/**.js ' ' !**_test.js ' --js_output_file out.js
封閉式編譯器將以命令行中傳遞的順序加成文件。
如果您使用的是地球儀或許多文件,則可能會開始遇到腳本之間依賴關係的問題。在這種情況下,您應該使用隨附的lib/base.js,該功能可用於在腳本之間執行依賴關係(即goog.module
和goog.require
)。閉合編譯器將自動重新排序輸入。
閉合編譯器使用lib/base.js發行,可提供JavaScript函數和變量,這些函數和變量可以用作閉合編譯器的某些特徵。該文件是即將棄用的關閉庫中相同命名base.js的派生。該base.js
將由封閉編譯器前進,並可能會收到新功能。它旨在僅保留其感知的核心部分。
要自己構建編譯器,您將需要以下內容:
先決條件 | 描述 |
---|---|
Java 11或更高版本 | 用於編譯編譯器的源代碼。 |
nodejs | 用於生成Java編譯使用的資源 |
git | 巴澤爾用於下載依賴項。 |
Bazelisk | 用於構建各種編譯器目標。 |
Bazelisk是Bazel周圍的包裝紙,可以動態加載給定存儲庫的Bazel的適當版本。使用它可以防止使用錯誤版本的Bazel構建編譯器而導致的虛假錯誤,並且使得在其他項目中使用不同的Bazel版本變得易於使用。
Bazelisk可通過許多包裝管理人員提供。隨意使用無論您最舒適的人。
安裝Bazelisk的說明。
$ bazelisk build //:compiler_uberjar_deploy.jar
# OR to build everything
$ bazelisk build //:all
測試可以以類似的方式執行。以下命令將在存儲庫中運行所有測試。
$ bazelisk test //:all
有數百個單獨的測試目標,因此所有這些目標都需要幾分鐘。在開發過程中,通常最好指定您感興趣的確切測試。
bazelisk test //: $path_to_test_file
參見Bazel IDE集成。
構建編譯器後,編譯後的罐子將在bazel-bin/
Directory中。您可以使用呼叫java -jar ...
或使用package.json腳本:
# java -jar bazel-bin/compiler_uberjar_deploy.jar [...args]
yarn compile [...args]
src/com/google/javascript/jscomp/CommandLineRunner.java
或創建自己的類的擴展版本。但是,您選擇做出貢獻,請遵守我們的行為守則,以使我們的社區保持健康而熱情。
版權所有2009 The Closure編譯器作者。
根據Apache許可證(版本2.0(“許可”)獲得許可;除了符合許可外,您不得使用此文件。您可以在http://www.apache.org/licenses/license-2.0上獲取許可證的副本。
除非適用法律要求或以書面形式同意,否則根據許可證分配的軟件是按照“原樣”分發的,沒有任何明示或暗示的任何形式的保證或條件。請參閱許可證的許可,以獲取許可條款中的權限和限制。
代碼路徑 | src/com/google/javascript/rhino , test/com/google/javascript/rhino |
URL | https://developer.mozilla.org/en-us/docs/mozilla/projects/rhino |
版本 | 1.5R3,進行重大修改 |
執照 | Netscape公共許可證和MPL / GPL雙重許可證 |
描述 | Mozilla Rhino的部分副本。 Mozilla Rhino是JVM的JavaScript的實現。提取並對Google的JavaScript編譯器進行了顯著修改JavaScript解析樹數據結構。 |
本地修改 | 包裹已重新安排。所有與解析樹無關的代碼已被刪除。已經添加了JSDOC解析器和靜態打字系統。 |
URL | http://args4j.kohsuke.org/ |
版本 | 2.33 |
執照 | 麻省理工學院 |
描述 | ARGS4J是一個小型Java類庫,可以輕鬆地在CUI應用程序中解析命令行選項/參數。 |
本地修改 | 沒有任何 |
URL | https://github.com/google/guava |
版本 | 31.0.1 |
執照 | Apache許可證2.0 |
描述 | Google的核心Java庫。 |
本地修改 | 沒有任何 |
URL | https://github.com/findbugsproject/findbugs |
版本 | 3.0.1 |
執照 | BSD許可證 |
描述 | 軟件缺陷檢測的註釋。 |
本地修改 | 沒有任何 |
URL | http://junit.org/junit4/ |
版本 | 4.13 |
執照 | 公共許可證1.0 |
描述 | 在Java中編寫和運行自動測試的框架。 |
本地修改 | 沒有任何 |
URL | https://github.com/google/protobuf |
版本 | 3.0.2 |
執照 | 新的BSD許可證 |
描述 | 支持協議緩衝區的庫,結構化數據的編碼。 |
本地修改 | 沒有任何 |
URL | https://github.com/google/re2j |
版本 | 1.3 |
執照 | 新的BSD許可證 |
描述 | Java中的線性時間正則表達式匹配。 |
本地修改 | 沒有任何 |
URL | https://github.com/google/truth |
版本 | 1.1 |
執照 | Apache許可證2.0 |
描述 | Java單位測試的主張/命題框架 |
本地修改 | 沒有任何 |
URL | https://ant.apache.org/bindownload.cgi |
版本 | 1.10.11 |
執照 | Apache許可證2.0 |
描述 | 螞蟻是基於Java的構建工具。從理論上講,這有點像沒有碎片的“製造”,以及純Java代碼的全部便攜性。 |
本地修改 | 沒有任何 |
URL | https://github.com/google/gson |
版本 | 2.9.1 |
執照 | Apache許可證2.0 |
描述 | Java庫將JSON轉換為Java對象,反之亦然 |
本地修改 | 沒有任何 |
代碼路徑 | contrib/nodejs |
URL | https://github.com/dcodeio/node.js-closure-compiler-externs |
版本 | E891B4FBCF5F466CC4307B0FA842A7D8163A073A |
執照 | Apache 2.0許可證 |
描述 | nodejs apis的類型合同 |
本地修改 | 實質性更改使其與NPMCommandlinerrunner兼容。 |