Skip to content

Commit 65d5fd8

Browse files
brad4dcopybara-github
authored andcommitted
Add (un)supported usage information to OSS README.md
Add text to our Open Source `README.md` document that explains the supported and unsupported uses of Closure compiler PiperOrigin-RevId: 621673057
1 parent 7fa0b2c commit 65d5fd8

File tree

1 file changed

+132
-5
lines changed

1 file changed

+132
-5
lines changed

README.md

+132-5
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,135 @@ analyzes it, removes dead code and rewrites and minimizes what's left. It also
1313
checks syntax, variable references, and types, and warns about common JavaScript
1414
pitfalls.
1515

16+
## Important Caveats
17+
18+
1. Compilation modes other than `ADVANCED` were always an afterthought and we
19+
have deprecated those modes. We believe that other tools perform comparably
20+
for non-`ADVANCED` modes and are better integrated into the broader JS
21+
ecosystem.
22+
23+
1. Closure Compiler is not suitable for arbitrary JavaScript. For `ADVANCED`
24+
mode to generate working JavaScript, the input JS code must be written with
25+
closure-compiler in mind.
26+
27+
1. Closure Compiler is a "whole world" optimizer. It expects to directly see or
28+
at least receive information about every possible use of every global or
29+
exported variable and every property name.
30+
31+
It will aggressively remove and rename variables and properties in order to
32+
make the output code as small as possible. This will result in broken output
33+
JS, if uses of global variables or properties are hidden from it.
34+
35+
Although one can write custom externs files to tell the compiler to leave
36+
some names unchanged so they can safely be accessed by code that is not part
37+
of the compilation, this is often tedious to maintain.
38+
39+
1. Closure Compiler property renaming requires you to consistently access a
40+
property with either `obj[p]` or `obj.propName`, but not both.
41+
42+
When you access a property with square brackets (e.g. `obj[p]`) or using some
43+
other indirect method like `let {p} = obj;` this hides the literal name of
44+
the property being referenced from the compiler. It cannot know if
45+
`obj.propName` is referring to the same property as `obj[p]`. In some cases
46+
it will notice this problem and stop the compilation with an error. In other
47+
cases it will rename `propName` to something shorter, without noticing this
48+
problem, resulting in broken output JS code.
49+
50+
1. Closure Compiler aggressively inlines global variables and flattens chains
51+
of property names on global variables (e.g. `myFoo.some.sub.property` ->
52+
`myFoo$some$sub$property`), to make reasoning about them easier for detecting
53+
unused code.
54+
55+
It tries to either back off from doing this or halt with an error when
56+
doing it will generate broken JS output, but there are cases where it will
57+
fail to recognize the problem and simply generate broken JS without warning.
58+
This is much more likely to happen in code that was not explicitly written
59+
with Closure Compiler in mind.
60+
61+
1. Closure compiler and the externs it uses by default assume that the target
62+
environment is a web browser window.
63+
64+
WebWorkers are supported also, but the compiler will likely fail to warn
65+
you if you try to use features that aren't actually available to a WebWorker.
66+
67+
Some externs files and features have been added to Closure Compiler to
68+
support the NodeJS environment, but they are not actively supported and
69+
never worked very well.
70+
71+
1. JavaScript that does not use the `goog.module()` and `goog.require()` from
72+
`base.js` to declare and use modules is not well supported.
73+
74+
The ECMAScript `import` and `export` syntax did not exist until 2015.
75+
Closure compiler and `closure-library` developed their own means for
76+
declaring and using modules, and this remains the only well supported
77+
way of defining modules.
78+
79+
The compiler does implement some understanding of ECMAScript modules,
80+
but changing Google's projects to use the newer syntax has never offered
81+
a benefit that was worth the cost of the change. Google's TypeScript code
82+
uses ECMAScript modules, but they are converted to `goog.module()` syntax
83+
before closure-compiler sees them. So, effectively the ECMAScript modules
84+
support is unused within Google. This means we are unlikely to notice
85+
or fix bugs in the support for ECMAScript modules.
86+
87+
Support for CommonJS modules as input was added in the past, but is not
88+
used within Google, and is likely to be entirely removed sometime in 2024.
89+
90+
## Supported uses
91+
92+
Closure Compiler is used by Google projects to:
93+
94+
* Drastically reduce the code size of very large JavaScript applications
95+
96+
* Check the JS code for errors and for conformance to general and/or
97+
project-specific best practices.
98+
99+
* Define user-visible messages in a way that makes it possible to replace
100+
them with translated versions to create localized versions of an
101+
application.
102+
103+
* Transpile newer JS features into a form that will run on browsers that
104+
lack support for those features.
105+
106+
* Break the output application into chunks that may be individually loaded
107+
as needed.
108+
109+
NOTE: These chunks are plain JavaScript scripts. They do not use the
110+
ECMAScript `import` and `export` syntax.
111+
112+
To achieve these goals closure compiler places many restrictions on its input:
113+
114+
* Use `goog.module()` and `goog.require()` to declare and use modules.
115+
116+
Support for the `import` and `export` syntax added in ES6 is not actively
117+
maintained.
118+
119+
* Use annotations in comments to declare type information and provide
120+
information the compiler needs to avoid breaking some code patterns
121+
(e.g. `@nocollapse` and `@noinline`).
122+
123+
* Either use only dot-access (e.g. `object.property`) or only use dynamic
124+
access (e.g. `object[propertyName]` or `Object.keys(object)`) to access
125+
the properties of a particular object type.
126+
127+
Mixing these will hide some uses of a property from the compiler, resulting
128+
in broken output code when it renames the property.
129+
130+
* In general the compiler expects to see an entire application as a single
131+
compilation. Interfaces must be carefully and explicitly constructed in
132+
order to allow interoperation with code outside of the compilation unit.
133+
134+
The compiler assumes it can see all uses of all variables and properties
135+
and will freely rename them or remove them if they appear unused.
136+
137+
* Use externs files to inform the compiler of any variables or properties
138+
that it must not remove or rename.
139+
140+
There are default externs files declaring the standard JS and DOM global
141+
APIs. More externs files are necessary if you are using less common
142+
APIs or expect some external JavaScript code to access an API in the
143+
code you are compiling.
144+
16145
## Getting Started
17146

18147
The easiest way to install the compiler is with [NPM](https://npmjs.com) or
@@ -199,12 +328,10 @@ The Closure Compiler will concatenate the files in the order they're passed at
199328
the command line.
200329

201330
If you're using globs or many files, you may start to run into problems with
202-
managing dependencies between scripts. In this case, you should either use the
331+
managing dependencies between scripts. In this case, you should use the
203332
included [lib/base.js](lib/base.js) that provides functions for enforcing
204-
dependencies between scripts (namely `goog.module` and `goog.require`) or
205-
[JavaScript modules](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules)
206-
(using the ECMAScript `import` and `export` syntax). Closure Compiler will
207-
re-order the inputs automatically.
333+
dependencies between scripts (namely `goog.module` and `goog.require`). Closure
334+
Compiler will re-order the inputs automatically.
208335

209336
## Closure JavaScript Library
210337

0 commit comments

Comments
 (0)