├── logo.png
├── LICENSE.md
└── README.md
/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/roman01la/closure-compiler-handbook/master/logo.png
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | Creative Commons Attribution 3.0 Unported
2 |
3 | License
4 |
5 | THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CREATIVE COMMONS
6 | PUBLIC LICENSE ("CCPL" OR "LICENSE"). THE WORK IS PROTECTED BY COPYRIGHT AND/OR
7 | OTHER APPLICABLE LAW. ANY USE OF THE WORK OTHER THAN AS AUTHORIZED UNDER THIS
8 | LICENSE OR COPYRIGHT LAW IS PROHIBITED.
9 |
10 | BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND AGREE TO BE
11 | BOUND BY THE TERMS OF THIS LICENSE. TO THE EXTENT THIS LICENSE MAY BE CONSIDERED
12 | TO BE A CONTRACT, THE LICENSOR GRANTS YOU THE RIGHTS CONTAINED HERE IN
13 | CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND CONDITIONS.
14 |
15 | 1. Definitions
16 |
17 | "Adaptation" means a work based upon the Work, or upon the Work and other
18 | pre-existing works, such as a translation, adaptation, derivative work,
19 | arrangement of music or other alterations of a literary or artistic work, or
20 | phonogram or performance and includes cinematographic adaptations or any other
21 | form in which the Work may be recast, transformed, or adapted including in any
22 | form recognizably derived from the original, except that a work that constitutes
23 | a Collection will not be considered an Adaptation for the purpose of this
24 | License. For the avoidance of doubt, where the Work is a musical work,
25 | performance or phonogram, the synchronization of the Work in timed-relation with
26 | a moving image ("synching") will be considered an Adaptation for the purpose of
27 | this License. "Collection" means a collection of literary or artistic works,
28 | such as encyclopedias and anthologies, or performances, phonograms or
29 | broadcasts, or other works or subject matter other than works listed in Section
30 | 1(f) below, which, by reason of the selection and arrangement of their contents,
31 | constitute intellectual creations, in which the Work is included in its entirety
32 | in unmodified form along with one or more other contributions, each constituting
33 | separate and independent works in themselves, which together are assembled into
34 | a collective whole. A work that constitutes a Collection will not be considered
35 | an Adaptation (as defined above) for the purposes of this License. "Distribute"
36 | means to make available to the public the original and copies of the Work or
37 | Adaptation, as appropriate, through sale or other transfer of ownership.
38 | "Licensor" means the individual, individuals, entity or entities that offer(s)
39 | the Work under the terms of this License. "Original Author" means, in the case
40 | of a literary or artistic work, the individual, individuals, entity or entities
41 | who created the Work or if no individual or entity can be identified, the
42 | publisher; and in addition (i) in the case of a performance the actors, singers,
43 | musicians, dancers, and other persons who act, sing, deliver, declaim, play in,
44 | interpret or otherwise perform literary or artistic works or expressions of
45 | folklore; (ii) in the case of a phonogram the producer being the person or legal
46 | entity who first fixes the sounds of a performance or other sounds; and, (iii)
47 | in the case of broadcasts, the organization that transmits the broadcast. "Work"
48 | means the literary and/or artistic work offered under the terms of this License
49 | including without limitation any production in the literary, scientific and
50 | artistic domain, whatever may be the mode or form of its expression including
51 | digital form, such as a book, pamphlet and other writing; a lecture, address,
52 | sermon or other work of the same nature; a dramatic or dramatico-musical work; a
53 | choreographic work or entertainment in dumb show; a musical composition with or
54 | without words; a cinematographic work to which are assimilated works expressed
55 | by a process analogous to cinematography; a work of drawing, painting,
56 | architecture, sculpture, engraving or lithography; a photographic work to which
57 | are assimilated works expressed by a process analogous to photography; a work of
58 | applied art; an illustration, map, plan, sketch or three-dimensional work
59 | relative to geography, topography, architecture or science; a performance; a
60 | broadcast; a phonogram; a compilation of data to the extent it is protected as a
61 | copyrightable work; or a work performed by a variety or circus performer to the
62 | extent it is not otherwise considered a literary or artistic work. "You" means
63 | an individual or entity exercising rights under this License who has not
64 | previously violated the terms of this License with respect to the Work, or who
65 | has received express permission from the Licensor to exercise rights under this
66 | License despite a previous violation. "Publicly Perform" means to perform public
67 | recitations of the Work and to communicate to the public those public
68 | recitations, by any means or process, including by wire or wireless means or
69 | public digital performances; to make available to the public Works in such a way
70 | that members of the public may access these Works from a place and at a place
71 | individually chosen by them; to perform the Work to the public by any means or
72 | process and the communication to the public of the performances of the Work,
73 | including by public digital performance; to broadcast and rebroadcast the Work
74 | by any means including signs, sounds or images. "Reproduce" means to make copies
75 | of the Work by any means including without limitation by sound or visual
76 | recordings and the right of fixation and reproducing fixations of the Work,
77 | including storage of a protected performance or phonogram in digital form or
78 | other electronic medium. 2. Fair Dealing Rights. Nothing in this License is
79 | intended to reduce, limit, or restrict any uses free from copyright or rights
80 | arising from limitations or exceptions that are provided for in connection with
81 | the copyright protection under copyright law or other applicable laws.
82 |
83 | 3. License Grant. Subject to the terms and conditions of this License, Licensor
84 | hereby grants You a worldwide, royalty-free, non-exclusive, perpetual (for the
85 | duration of the applicable copyright) license to exercise the rights in the Work
86 | as stated below:
87 |
88 | to Reproduce the Work, to incorporate the Work into one or more Collections, and
89 | to Reproduce the Work as incorporated in the Collections; to create and
90 | Reproduce Adaptations provided that any such Adaptation, including any
91 | translation in any medium, takes reasonable steps to clearly label, demarcate or
92 | otherwise identify that changes were made to the original Work. For example, a
93 | translation could be marked "The original work was translated from English to
94 | Spanish," or a modification could indicate "The original work has been
95 | modified."; to Distribute and Publicly Perform the Work including as
96 | incorporated in Collections; and, to Distribute and Publicly Perform
97 | Adaptations. For the avoidance of doubt:
98 |
99 | Non-waivable Compulsory License Schemes. In those jurisdictions in which the
100 | right to collect royalties through any statutory or compulsory licensing scheme
101 | cannot be waived, the Licensor reserves the exclusive right to collect such
102 | royalties for any exercise by You of the rights granted under this License;
103 | Waivable Compulsory License Schemes. In those jurisdictions in which the right
104 | to collect royalties through any statutory or compulsory licensing scheme can be
105 | waived, the Licensor waives the exclusive right to collect such royalties for
106 | any exercise by You of the rights granted under this License; and, Voluntary
107 | License Schemes. The Licensor waives the right to collect royalties, whether
108 | individually or, in the event that the Licensor is a member of a collecting
109 | society that administers voluntary licensing schemes, via that society, from any
110 | exercise by You of the rights granted under this License. The above rights may
111 | be exercised in all media and formats whether now known or hereafter devised.
112 | The above rights include the right to make such modifications as are technically
113 | necessary to exercise the rights in other media and formats. Subject to Section
114 | 8(f), all rights not expressly granted by Licensor are hereby reserved.
115 |
116 | 4. Restrictions. The license granted in Section 3 above is expressly made
117 | subject to and limited by the following restrictions:
118 |
119 | You may Distribute or Publicly Perform the Work only under the terms of this
120 | License. You must include a copy of, or the Uniform Resource Identifier (URI)
121 | for, this License with every copy of the Work You Distribute or Publicly
122 | Perform. You may not offer or impose any terms on the Work that restrict the
123 | terms of this License or the ability of the recipient of the Work to exercise
124 | the rights granted to that recipient under the terms of the License. You may not
125 | sublicense the Work. You must keep intact all notices that refer to this License
126 | and to the disclaimer of warranties with every copy of the Work You Distribute
127 | or Publicly Perform. When You Distribute or Publicly Perform the Work, You may
128 | not impose any effective technological measures on the Work that restrict the
129 | ability of a recipient of the Work from You to exercise the rights granted to
130 | that recipient under the terms of the License. This Section 4(a) applies to the
131 | Work as incorporated in a Collection, but this does not require the Collection
132 | apart from the Work itself to be made subject to the terms of this License. If
133 | You create a Collection, upon notice from any Licensor You must, to the extent
134 | practicable, remove from the Collection any credit as required by Section 4(b),
135 | as requested. If You create an Adaptation, upon notice from any Licensor You
136 | must, to the extent practicable, remove from the Adaptation any credit as
137 | required by Section 4(b), as requested. If You Distribute, or Publicly Perform
138 | the Work or any Adaptations or Collections, You must, unless a request has been
139 | made pursuant to Section 4(a), keep intact all copyright notices for the Work
140 | and provide, reasonable to the medium or means You are utilizing: (i) the name
141 | of the Original Author (or pseudonym, if applicable) if supplied, and/or if the
142 | Original Author and/or Licensor designate another party or parties (e.g., a
143 | sponsor institute, publishing entity, journal) for attribution ("Attribution
144 | Parties") in Licensor's copyright notice, terms of service or by other
145 | reasonable means, the name of such party or parties; (ii) the title of the Work
146 | if supplied; (iii) to the extent reasonably practicable, the URI, if any, that
147 | Licensor specifies to be associated with the Work, unless such URI does not
148 | refer to the copyright notice or licensing information for the Work; and (iv) ,
149 | consistent with Section 3(b), in the case of an Adaptation, a credit identifying
150 | the use of the Work in the Adaptation (e.g., "French translation of the Work by
151 | Original Author," or "Screenplay based on original Work by Original Author").
152 | The credit required by this Section 4 (b) may be implemented in any reasonable
153 | manner; provided, however, that in the case of a Adaptation or Collection, at a
154 | minimum such credit will appear, if a credit for all contributing authors of the
155 | Adaptation or Collection appears, then as part of these credits and in a manner
156 | at least as prominent as the credits for the other contributing authors. For the
157 | avoidance of doubt, You may only use the credit required by this Section for the
158 | purpose of attribution in the manner set out above and, by exercising Your
159 | rights under this License, You may not implicitly or explicitly assert or imply
160 | any connection with, sponsorship or endorsement by the Original Author, Licensor
161 | and/or Attribution Parties, as appropriate, of You or Your use of the Work,
162 | without the separate, express prior written permission of the Original Author,
163 | Licensor and/or Attribution Parties. Except as otherwise agreed in writing by
164 | the Licensor or as may be otherwise permitted by applicable law, if You
165 | Reproduce, Distribute or Publicly Perform the Work either by itself or as part
166 | of any Adaptations or Collections, You must not distort, mutilate, modify or
167 | take other derogatory action in relation to the Work which would be prejudicial
168 | to the Original Author's honor or reputation. Licensor agrees that in those
169 | jurisdictions (e.g. Japan), in which any exercise of the right granted in
170 | Section 3(b) of this License (the right to make Adaptations) would be deemed to
171 | be a distortion, mutilation, modification or other derogatory action prejudicial
172 | to the Original Author's honor and reputation, the Licensor will waive or not
173 | assert, as appropriate, this Section, to the fullest extent permitted by the
174 | applicable national law, to enable You to reasonably exercise Your right under
175 | Section 3(b) of this License (right to make Adaptations) but not otherwise. 5.
176 | Representations, Warranties and Disclaimer
177 |
178 | UNLESS OTHERWISE MUTUALLY AGREED TO BY THE PARTIES IN WRITING, LICENSOR OFFERS
179 | THE WORK AS-IS AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING
180 | THE WORK, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE, INCLUDING, WITHOUT
181 | LIMITATION, WARRANTIES OF TITLE, MERCHANTIBILITY, FITNESS FOR A PARTICULAR
182 | PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, ACCURACY,
183 | OR THE PRESENCE OF ABSENCE OF ERRORS, WHETHER OR NOT DISCOVERABLE. SOME
184 | JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF IMPLIED WARRANTIES, SO SUCH
185 | EXCLUSION MAY NOT APPLY TO YOU.
186 |
187 | 6. Limitation on Liability. EXCEPT TO THE EXTENT REQUIRED BY APPLICABLE LAW, IN
188 | NO EVENT WILL LICENSOR BE LIABLE TO YOU ON ANY LEGAL THEORY FOR ANY SPECIAL,
189 | INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES ARISING OUT OF THIS
190 | LICENSE OR THE USE OF THE WORK, EVEN IF LICENSOR HAS BEEN ADVISED OF THE
191 | POSSIBILITY OF SUCH DAMAGES.
192 |
193 | 7. Termination
194 |
195 | This License and the rights granted hereunder will terminate automatically upon
196 | any breach by You of the terms of this License. Individuals or entities who have
197 | received Adaptations or Collections from You under this License, however, will
198 | not have their licenses terminated provided such individuals or entities remain
199 | in full compliance with those licenses. Sections 1, 2, 5, 6, 7, and 8 will
200 | survive any termination of this License. Subject to the above terms and
201 | conditions, the license granted here is perpetual (for the duration of the
202 | applicable copyright in the Work). Notwithstanding the above, Licensor reserves
203 | the right to release the Work under different license terms or to stop
204 | distributing the Work at any time; provided, however that any such election will
205 | not serve to withdraw this License (or any other license that has been, or is
206 | required to be, granted under the terms of this License), and this License will
207 | continue in full force and effect unless terminated as stated above. 8.
208 | Miscellaneous
209 |
210 | Each time You Distribute or Publicly Perform the Work or a Collection, the
211 | Licensor offers to the recipient a license to the Work on the same terms and
212 | conditions as the license granted to You under this License. Each time You
213 | Distribute or Publicly Perform an Adaptation, Licensor offers to the recipient a
214 | license to the original Work on the same terms and conditions as the license
215 | granted to You under this License. If any provision of this License is invalid
216 | or unenforceable under applicable law, it shall not affect the validity or
217 | enforceability of the remainder of the terms of this License, and without
218 | further action by the parties to this agreement, such provision shall be
219 | reformed to the minimum extent necessary to make such provision valid and
220 | enforceable. No term or provision of this License shall be deemed waived and no
221 | breach consented to unless such waiver or consent shall be in writing and signed
222 | by the party to be charged with such waiver or consent. This License constitutes
223 | the entire agreement between the parties with respect to the Work licensed here.
224 | There are no understandings, agreements or representations with respect to the
225 | Work not specified here. Licensor shall not be bound by any additional
226 | provisions that may appear in any communication from You. This License may not
227 | be modified without the mutual written agreement of the Licensor and You. The
228 | rights granted under, and the subject matter referenced, in this License were
229 | drafted utilizing the terminology of the Berne Convention for the Protection of
230 | Literary and Artistic Works (as amended on September 28, 1979), the Rome
231 | Convention of 1961, the WIPO Copyright Treaty of 1996, the WIPO Performances and
232 | Phonograms Treaty of 1996 and the Universal Copyright Convention (as revised on
233 | July 24, 1971). These rights and subject matter take effect in the relevant
234 | jurisdiction in which the License terms are sought to be enforced according to
235 | the corresponding provisions of the implementation of those treaty provisions in
236 | the applicable national law. If the standard suite of rights granted under
237 | applicable copyright law includes additional rights not granted under this
238 | License, such additional rights are deemed to be included in the License; this
239 | License is not intended to restrict the license of any rights under applicable
240 | law. Creative Commons Notice
241 |
242 | Creative Commons is not a party to this License, and makes no warranty
243 | whatsoever in connection with the Work. Creative Commons will not be liable to
244 | You or any party on any legal theory for any damages whatsoever, including
245 | without limitation any general, special, incidental or consequential damages
246 | arising in connection to this license. Notwithstanding the foregoing two (2)
247 | sentences, if Creative Commons has expressly identified itself as the Licensor
248 | hereunder, it shall have all rights and obligations of Licensor.
249 |
250 | Except for the limited purpose of indicating to the public that the Work is
251 | licensed under the CCPL, Creative Commons does not authorize the use by either
252 | party of the trademark "Creative Commons" or any related trademark or logo of
253 | Creative Commons without the prior written consent of Creative Commons. Any
254 | permitted use will be in compliance with Creative Commons' then-current
255 | trademark usage guidelines, as may be published on its website or otherwise made
256 | available upon request from time to time. For the avoidance of doubt, this
257 | trademark restriction does not form part of this License.
258 |
259 | Creative Commons may be contacted at http://creativecommons.org/.
260 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Introduction 👋
2 |
3 |
4 |
5 | This handbook is designed to help you understand how to use Closure Compiler and learn its features.
6 |
7 | > The Closure Compiler is a tool for making JavaScript download and run faster. Instead of compiling from a source language to machine code, it compiles from JavaScript to better JavaScript. It parses your JavaScript, analyzes it, removes dead code and rewrites and minimizes what's left. It also checks syntax, variable references, and types, and warns about common JavaScript pitfalls.
8 |
9 |
10 |
11 | [Closure Compiler](https://developers.google.com/closure/compiler/) can compile, optimize and bundle JavaScript code. You can use it for building your JavaScript apps for production. It is the most advanced JavaScript optimization tool. It generates smallest bundle and emits efficient JavaScript code by doing whole program analysis and optimization, removing closures, inlining function calls, reusing variable names and pre-computing constant expressions.
12 |
13 | React + ReactDOM build comparison
14 |
15 | Tool | Output size | Gzipped |
16 | ----------------|-------------|---------|
17 | Webpack 2 |139KB |42KB |
18 | Closure Compiler|90KB |32KB |
19 |
20 | Here's an example of compiler's compilation output:
21 |
22 | *input*
23 | ```js
24 | function hello(name) {
25 | const message = `Hello, ${name}!`;
26 | console.log(message);
27 | }
28 | hello('New user');
29 | ```
30 |
31 | *output*
32 | ```js
33 | console.log("Hello, New user!");
34 | ```
35 |
36 | # Table of Contents 📖
37 | - [Introduction](#introduction-)
38 | - [Table of Contents](#table-of-contents-)
39 | - [Getting started](#getting-started-)
40 | - [Installation](#installation)
41 | - [Using with Node](#using-with-node)
42 | - [Using with Webpack](#using-with-webpack)
43 | - [Using with Gulp](#using-with-gulp)
44 | - [Splittable bundler](#splittable-bundler)
45 | - [Compilation levels](#compilation-levels-)
46 | - [Advanced compilation](#advanced-compilation-)
47 | - [Referencing external code](#referencing-external-code)
48 | - [Referencing compiled code](#referencing-compiled-code)
49 | - [Referencing to object properties using both dot and bracket notations](#referencing-to-object-properties-using-both-dot-and-bracket-notations)
50 | - [Compiler optimizations](#compiler-optimizations-)
51 | - [Dead code elimination and Tree-shaking](#dead-code-elimination-and-tree-shaking)
52 | - [Unreachable and redundant code elimination](#unreachable-and-redundant-code-elimination)
53 | - [Cross-module code motion](#cross-module-code-motion)
54 | - [Constant folding](#constant-folding)
55 | - [Function call inlining](#function-call-inlining)
56 | - [Property flattening (collapsing)](#property-flattening-collapsing)
57 | - [Variable and property renaming](#variable-and-property-renaming)
58 | - [Statement fusion (merging) & variable declarations grouping](#statement-fusion-merging--variable-declarations-grouping)
59 | - [Alternate syntax substitution](#alternate-syntax-substitution)
60 | - [RegExp optimization](#regexp-optimization)
61 | - [Known methods folding](#known-methods-folding)
62 | - [Property assignment collection](#property-assignment-collection)
63 | - [Anonymous functions naming](#anonymous-functions-naming)
64 | - [Compiler flags](#compiler-flags-)
65 | - [Supported languages](#supported-languages-)
66 | - [JavaScript modules](#javascript-modules-)
67 | - [Recipes](#recipes-)
68 | - [Externs](#externs)
69 | - [Exporting to global scope](#exporting-to-global-scope)
70 | - [Code splitting](#code-splitting)
71 | - [Who is using it?](#who-is-using-it)
72 |
73 | # Getting started 🏁
74 |
75 | Closure Compiler is written in Java, but it also has JavaScript port.
76 | The best way to use it is [Splittable](https://github.com/cramforce/splittable) bundler.
77 |
78 | - [google/closure-compiler](https://github.com/google/closure-compiler)
79 | - [google/closure-compiler-js](https://github.com/google/closure-compiler-js)
80 | - [Splittable](https://github.com/cramforce/splittable)
81 |
82 | ## Installation
83 |
84 | ```bash
85 | npm i google-closure-compiler-js
86 | ```
87 |
88 | ## Using with Node
89 |
90 | ```js
91 | const compile = require('google-closure-compiler-js').compile;
92 |
93 | const flags = {
94 | jsCode: [{src: 'const inc = (x) => x + 1;'}]
95 | };
96 |
97 | const out = compile(flags);
98 |
99 | console.log(out.compiledCode); // 'var inc=function(a){return a+1};'
100 | ```
101 |
102 | ## Using with Webpack
103 |
104 | ```js
105 | const ClosureCompiler = require('google-closure-compiler-js').webpack;
106 | const path = require('path');
107 |
108 | module.exports = {
109 | entry: [
110 | path.join(__dirname, 'entry.js')
111 | ],
112 | output: {
113 | path: path.join(__dirname, 'build'),
114 | filename: 'bundle.js'
115 | },
116 | plugins: [
117 | new ClosureCompiler({
118 | options: {
119 | languageIn: 'ECMASCRIPT6',
120 | languageOut: 'ECMASCRIPT3',
121 | compilationLevel: 'ADVANCED'
122 | }
123 | })
124 | ]
125 | };
126 | ```
127 |
128 | ## Using with Gulp
129 |
130 | ```js
131 | const compiler = require('google-closure-compiler-js').gulp();
132 |
133 | gulp.task('build', function() {
134 | return gulp.src('enrty.js', {base: './'})
135 | .pipe(compiler({
136 | compilationLevel: 'ADVANCED',
137 | jsOutputFile: 'bundle.js',
138 | createSourceMap: true
139 | }))
140 | .pipe(gulp.dest('./build'));
141 | });
142 | ```
143 |
144 | ## Splittable bundler
145 |
146 | [Splittable](https://github.com/cramforce/splittable) is a module bundler for JavaScript based on Closure Compiler. Basically it's a wrapper with zero configuration which supports ES6 and code splitting out of the box.
147 |
148 | ```js
149 | const splittable = require('splittable');
150 |
151 | splittable({
152 | // Create bundles from 2 entry modules `./src/a` and `./src/b`.
153 | modules: ['./src/a', './src/b'],
154 | writeTo: 'dist/',
155 | })
156 | .then((info) => {
157 | console.info('Compilation successful');
158 | if (info.warnings) {
159 | console.warn(info.warnings);
160 | }
161 | })
162 | .catch((error) => console.error('Compilation failed', error));
163 | ```
164 |
165 | # Compilation levels 🎚
166 |
167 | Compilation level is a compiler setting which denotes optimizations level to be applied to JavaScript code.
168 |
169 | `WHITESPACE_ONLY`
170 |
171 | Removes comments, line breaks, unnecessary spaces and other whitespace.
172 |
173 | `SIMPLE` *(default)*
174 |
175 | Includes `WHITESPACE_ONLY` optimizations and renames variable names to shorter names to reduce the size of output code. It renames only variables local to functions, which means that it won't break references to third party code from global scope.
176 |
177 | `ADVANCED`
178 |
179 | Includes `SIMPLE` optimizations and performs aggressive transformations such as closures elimination, inlining function calls, reusing variable names, pre-computing constant expressions, tree-shaking, cross-module code motion and dead code elimination.
180 |
181 | This kind of aggressive compression makes some assumptions about your code. If it doesn't conform to those assumptions, Closure Compiler will produce output that does not run.
182 |
183 | # Advanced compilation 👷
184 |
185 | With `ADVANCED` compilation level Closure Compiler renames global variables, function names and properties and removes unused code. This can lead to output that will not run if your code doesn't follow certain rules.
186 |
187 | ## Referencing external code
188 |
189 | If you want to use globally defined variables and functions in your code safely, you must tell the compiler about those references.
190 |
191 | *input*
192 | ```js
193 | // `moment` is declared in global scope
194 | window.moment().subtract(10, 'days').calendar();
195 | ```
196 |
197 | *output*
198 | ```js
199 | // `moment` was renamed to `a`
200 | // this will not run
201 | window.a().b(10, 'days').calendar();
202 | ```
203 |
204 | The way you do it is via _externs_. See [Externs](#externs) section for more information.
205 |
206 | ## Referencing compiled code
207 |
208 | If you are about to build a library that exports to global scope, you must tell the compiler about variables that should be exported safely.
209 |
210 | *input*
211 | ```js
212 | // `MY_APP` is declared in global scope
213 | window.MY_APP = {};
214 | ```
215 |
216 | *output*
217 | ```js
218 | // `MY_APP` was renamed to `a`
219 | // it's no longer possible to reference `MY_APP`
220 | window.a = {};
221 | ```
222 |
223 | This should be done by exporting symbols into global scope. See [Exporting to global scope](#exporting-to-global-scope) section for more information.
224 |
225 | ## Referencing to object properties using both dot and bracket notations
226 |
227 | Closure Compiler never rewrites strings. You should use only one way of declaring and accessing a property:
228 | - declare with a symbol, access with dot notation
229 | - declare with a string, access with a string
230 |
231 | *input*
232 | ```js
233 | // `msg` property is declared and accessed in different ways
234 | obj = { msg: 'Hey!' };
235 | console.log(obj['msg']);
236 | ```
237 |
238 | *output*
239 | ```js
240 | // `msg` symbol is renamed to `a`, but `'msg'` text is not
241 | obj = { a: 'Hey!' };
242 | console.log(obj.msg);
243 | ```
244 |
245 | # Compiler optimizations 🎛
246 |
247 | Closure Compiler performs a number of optimizations to produce a small output size. Some of them are being applied in intermediate compilation pass to produce AST which is suited best for further code optimization.
248 |
249 | *NOTE: Below is a list of the most interesting optimizations that compiler does. But there are more of them, you can find them all in comments in the source code of the compiler.*
250 |
251 | ## Dead code elimination and Tree-shaking
252 |
253 | “Dead code” is a code that is never going to be called in your program. Closure Compiler can efficiently determine and remove such code because it is a whole-program optimization compiler, which means that it performs analysis of the whole program (in comparison to less effective analysis on module level). It constructs a graph of all variables and dependencies which are declared in your code, does graph traversal to find what should be included and dismisses the rest, which is a dead code.
254 |
255 | *input*
256 | ```js
257 | /* log.js module */
258 | export const logWithMsg = (msg, arg) => console.log(msg, arg);
259 | export const log = (arg) => console.log(arg);
260 |
261 | /* math.js module */
262 | export const min = (a, b) => Math.min(a, b);
263 | export const max = (a, b) => Math.max(a, b);
264 | export const exp = (x) => x * x;
265 | export const sum = (xs) => xs.reduce((a, b) => a + b, 0);
266 |
267 | /* entry.js entry point */
268 | import * as math from './math';
269 | import * as logger from './log';
270 |
271 | const nums = [0, 1, 2, 3, 4, 5];
272 | const msg = 'Result:';
273 |
274 | if (false) {
275 | logger.log('nothing');
276 | } else {
277 | logger.logWithMsg(msg, math.sum(nums));
278 | }
279 | ```
280 |
281 | *output*
282 | ```js
283 | // Even though the entire modules namespace was imported,
284 | // tree-shaking didn't include dependency code that is not used here.
285 | // Also a dead code within `if (false) { ... }` was removed.
286 | var c = function(a) {
287 | return a.reduce(function(a, b) {
288 | return a + b;
289 | }, 0);
290 | }([0,1,2,3,4,5]);
291 |
292 | console.log("Result:",c);
293 | ```
294 |
295 | ## Unreachable and redundant code elimination
296 |
297 | This optimization is a little different from dead code elimination. It removes “live code” that doesn't have an impact on a program, e.g. statements without side effects (`true;`), useless `break`, `continue` and `return`.
298 |
299 | ## Cross-module code motion
300 |
301 | Closure Compiler moves variables, functions and methods between modules. It moves the code along modules tree down to those modules where this code is needed. This can reduce parsing time before actual execution. This technique is especially useful for advanced code splitting which works on variables level, rather than modules level.
302 |
303 | *input*
304 | ```js
305 | /* math.js module */
306 | export const sum = (xs) => xs.reduce((a, b) => a + b, 0);
307 | export const mult = (xs) => xs.reduce((a, b) => a * b, 1);
308 |
309 | /* entry-1.js module */
310 | import * as math from './math';
311 |
312 | console.log(math.sum(nums));
313 |
314 | /* entry-2.js module */
315 | import * as math from './math';
316 |
317 | console.log(math.sum([4, 5, 6]) + math.mult([3, 5, 6]));
318 | ```
319 |
320 | *output*
321 | ```js
322 | /* common.js shared code */
323 | function c(a) {
324 | return a.reduce(function(a, b) {
325 | return a + b;
326 | }, 0);
327 | };
328 |
329 | /* entry-1.bundle.js */
330 | console.log(c(nums)); // using shared code
331 |
332 | /* entry-2.bundle.js */
333 | console.log(
334 | // using shared code
335 | c([4,5,6]) +
336 | // moved from `math.js` module
337 | function(a) {
338 | return a.reduce(function(a, b) {
339 | return a * b;
340 | }, 1);
341 | }([3,5,6])
342 | );
343 | ```
344 |
345 | ## Constant folding
346 |
347 | > Constant folding is the process of recognizing and evaluating constant expressions at compile time rather than computing them at runtime. Terms in constant expressions are typically simple literals, such as the integer literal 2 , but they may also be variables whose values are known at compile time.
348 |
349 | *input*
350 | ```js
351 | const years = 14;
352 | const monthsInYear = 12;
353 | const daysInMonth = 30;
354 |
355 | console.log(years * monthsInYear * daysInMonth);
356 | ```
357 |
358 | *output*
359 | ```js
360 | console.log(5040);
361 | // `years * monthsInYear * daysInMonth` computed at compile time
362 | // because they are known as constants
363 | ```
364 |
365 | ## Function call inlining
366 |
367 | To inline a function means to replace a function call with its body. The function definition can be dismissed and it also eliminates an additional function call. If the compiler couldn't perform this type of inlining, it can inline function declaration with a call it in place.
368 |
369 | *input*
370 | ```js
371 | const person = {
372 | fname: 'John',
373 | lname: 'Doe',
374 | };
375 |
376 | function getFullName({ fname, lname }) {
377 | return fname + ' ' + lname;
378 | }
379 |
380 | console.log(getFullName(person));
381 | ```
382 |
383 | *output*
384 | ```js
385 | var a = { a: "John", b: "Doe" };
386 | console.log(a.a + " " + a.b);
387 | ```
388 |
389 | ## Property flattening (collapsing)
390 |
391 | Collapsing object properties into separate variables enables such optimizations as variable renaming, inlining and better dead code removal.
392 |
393 | *input*
394 | ```js
395 | const person = {
396 | fname: 'John',
397 | lname: 'Doe'
398 | };
399 |
400 | console.log(person.fname);
401 | ```
402 |
403 | *output*
404 | ```js
405 | var person$fname = "John",
406 | person$lname = "Doe"; // <- is not used, can be removed
407 |
408 | console.log(person$fname);
409 | ```
410 |
411 | ## Variable and property renaming
412 |
413 | Small output size is partially achieved by renaming all variables and object properties. Because the compiler renames object properties you have to make sure that you are referencing and declaring properties either with symbol (`obj.prop`) or string (`obj['prop']`).
414 |
415 | *input*
416 | ```js
417 | const user = window.session.user;
418 | console.log(user.apiToken, user.tokenExpireDate);
419 | ```
420 |
421 | *output*
422 | ```js
423 | var a = window.b.f;
424 | console.log(a.a, a.c);
425 | ```
426 |
427 | ## Statement fusion (merging) & variable declarations grouping
428 |
429 | Statement fusion tries to merge multiple statements in a single one. And variable declarations grouping groups multiple variable declarations into a single one.
430 |
431 | *input*
432 | ```js
433 | const fname = 'John';
434 | const lname = 'Doe';
435 |
436 | if (fname) {
437 | console.log(fname);
438 | }
439 | ```
440 |
441 | *output*
442 | ```js
443 | var fname = "John", lname = "Doe";
444 | fname && console.log(fname);
445 | ```
446 |
447 | ## Alternate syntax substitution
448 |
449 | Simplifies conditional expressions, replaces `if`s with ternary operator, object and array constructs with literals and simplifies `return`s.
450 |
451 | ## RegExp optimization
452 |
453 | Removes unnecessary flags and reorders them for better gzip.
454 |
455 | ## Known methods folding
456 |
457 | This precomputes known methods such as `join`, `indexOf`, `substring`, `substr`, `parseInt` and `parseFloat` when they are called with constants.
458 |
459 | *input*
460 | ```js
461 | [0, 1, 2, 3, 4, 5].join('');
462 | ```
463 |
464 | *output*
465 | ```js
466 | "012345"
467 | ```
468 |
469 | ## Property assignment collection
470 |
471 | Looks for assignments to properties of object/array immediately following its creation using the abbreviated syntax and merges assigned values into object/array creation construct.
472 |
473 | *input*
474 | ```js
475 | const coll = [];
476 | coll[0] = 0;
477 | coll[2] = 5;
478 |
479 | const obj = { x: 1 };
480 |
481 | obj.y = 2;
482 | ```
483 |
484 | *output*
485 | ```js
486 | var coll = [0, , 5], obj = { x:1, y:2 };
487 | ```
488 |
489 | ## Anonymous functions naming
490 |
491 | Gives anonymous function names. This makes it way easier to debug because debuggers and stack traces use the function names.
492 |
493 | *input*
494 | ```js
495 | math.simple.add = function(a, b) {
496 | return a + b;
497 | };
498 | ```
499 |
500 | *output*
501 | ```js
502 | math.simple.add = function $math$simple$add$(a, b) {
503 | return a + b;
504 | };
505 | ```
506 |
507 | # Compiler flags 🚩
508 |
509 | There are much more compiler flags, see all of them in [google/closure-compiler-js](https://github.com/google/closure-compiler-js#flags) repo.
510 |
511 | | Flag | Default | Usage |
512 | |----------------------------------|---------|-------|
513 | | applyInputSourceMaps | `true` | Compose input source maps into output source map |
514 | | assumeFunctionWrapper | `false` | Enable additional optimizations based on the assumption that the output will be wrapped with a function wrapper. This flag is used to indicate that "global" declarations will not actually be global but instead isolated to the compilation unit. This enables additional optimizations. |
515 | | compilationLevel | `SIMPLE` | Specifies the compilation level to use: `WHITESPACE_ONLY`, `SIMPLE`, `ADVANCED` |
516 | | env | `BROWSER` | Determines the set of builtin externs to load: `BROWSER`, `CUSTOM` |
517 | | languageIn | `ES6` | Sets what language spec that input sources conform to. |
518 | | languageOut | `ES5` | Sets what language spec the output should conform to. |
519 | | newTypeInf | `false` | Checks for type errors using the new type inference algorithm. |
520 | | outputWrapper | `null` | Interpolate output into this string, replacing the token `%output%` |
521 | | processCommonJsModules | `false` | Process CommonJS modules to a concatenable form, i.e., support `require` statements. |
522 | | rewritePolyfills | `false` | Rewrite ES6 library calls to use polyfills provided by the compiler's runtime. |
523 | | warningLevel | `DEFAULT` | Specifies the warning level to use: `QUIET`, `DEFAULT`, `VERBOSE` |
524 | | jsCode | `[]` | Specifies the source code to compile. |
525 | | externs | `[]` | Additional externs to use for this compile. |
526 | | createSourceMap | `false` | Generates a source map mapping the generated source file back to its original sources. |
527 |
528 | # Supported languages 🙊
529 |
530 | | Language | Option name | Input | Output |
531 | |----------|----------------------|-------|--------|
532 | | ES3 | `ECMASCRIPT3` | ✅ | ✅ |
533 | | ES5 | `ECMASCRIPT5` | ✅ | ✅ |
534 | | ES5 | `ECMASCRIPT5_STRICT` | ✅ | ✅ |
535 | | ES2015 | `ECMASCRIPT6` | ✅ | |
536 | | ES2015 | `ECMASCRIPT6_STRICT` | ✅ | |
537 | | ES2015 | `ECMASCRIPT6_TYPED` | ✅ | ✅ |
538 |
539 | # JavaScript modules 🌯
540 |
541 | # Recipes 🍜
542 |
543 | ## Externs
544 |
545 | Extern is a JavaScript file which describes an interface of the external code. If you are going to use external function, you should declare a function with the same name, but without its body. In case when it is an object — declare an object with the same name and describe its shape by provinding property names.
546 |
547 | Once you have all of required externs, they should be passed to compiler using `--externs` flag per extern file, or as a value to `externs` property in compiler configuration if you are using a tool on top of the compiler.
548 |
549 | *input*
550 | ```js
551 | // `moment` is declared in global scope
552 | window.moment().subtract(10, 'days').calendar();
553 | ```
554 |
555 | *extern*
556 | ```js
557 | function moment() {}
558 |
559 | moment.prototype = {
560 | subtract: function() {},
561 | calendar: function() {}
562 | };
563 | ```
564 |
565 | *output*
566 | ```js
567 | // `moment` and its prototype methods was not renamed
568 | window.moment().subtract(10, 'days').calendar();
569 | ```
570 |
571 | Externs can be generated for most libraries, see [JavaScript Externs Generator](http://michaelmclellan.me/javascript-externs-generator/).
572 |
573 | ## Exporting to global scope
574 |
575 | If you are building a library and not using JavaScript modules, you can export functions and variables safely using bracket notation and quoted property names, since Closure Compiler doesn't rename strings.
576 |
577 | *input*
578 | ```js
579 | function logger(x) {
580 | console.log('LOG:', x);
581 | }
582 |
583 | window['logger'] = logger;
584 | ```
585 |
586 | *output*
587 | ```js
588 | // `logger` function is exported properly into global scope
589 | window.logger = function(a) {
590 | console.log('LOG:', a);
591 | };
592 | ```
593 |
594 | ## Code splitting
595 |
596 | Code splitting is a technique used to reduce initial script loading time by splitting a program into a number of bundles that are loaded later. This is especially important for modern web apps. With code splitting you could have a separate bundle for every route in a program, so initially browser will load only minimal amount of code to run and show requested view to a user and other code can be lazy-loaded later.
597 |
598 | # Who is using it?
599 |
600 | - [ClojureScript](https://clojurescript.org/)
601 | - [Scala.js](https://www.scala-js.org/)
602 | - [Dart](https://www.dartlang.org/)
603 | - [GWT](http://www.gwtproject.org/)
604 | - [Tsickle — TypeScript to Closure Annotator](https://github.com/angular/tsickle)
605 |
--------------------------------------------------------------------------------