闭合编译器是使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兼容。 |