├── 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 | Closure Compiler handbook logo 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 | Creative Commons License 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 | --------------------------------------------------------------------------------