# Advanced Compilation

## Overview


Using the Closure Compiler with a `compilation_level`
of `ADVANCED_OPTIMIZATIONS` offers better compression rates
than compilation with `SIMPLE_OPTIMIZATIONS`
or `WHITESPACE_ONLY`. Compilation
with `ADVANCED_OPTIMIZATIONS` achieves extra compression by
being more aggressive in the ways that it transforms code and renames
symbols. However, this more aggressive approach means that you must
take greater care when you use `ADVANCED_OPTIMIZATIONS`
to ensure that the output code works the same way as the
input code.


This tutorial illustrates what the `ADVANCED_OPTIMIZATIONS`
compilation level does and what you can do to make sure your code
works after compilation with `ADVANCED_OPTIMIZATIONS`. It
also introduces the concept of the *extern*: a symbol that is
defined in code external to the code processed by the compiler.


Before reading this tutorial you should be familiar with the process
of compiling JavaScript with one of the Closure Compiler tools, such as the Java-based
[compiler application](https://developers.google.com/closure/compiler/docs/gettingstarted_app).


A note on terminology: the `--compilation_level` command line flag
supports the more commonly used abbreviations `ADVANCED` and
`SIMPLE` as well as the more precise
`ADVANCED_OPTIMIZATIONS` and `SIMPLE_OPTIMIZATIONS`.
This document uses the longer form, but the names may be used interchangeably on
the command line.

1. [Even Better Compression](https://developers.google.com/closure/compiler/docs/api-tutorial3#better)
2. [How to
   Enable ADVANCED_OPTIMIZATIONS](https://developers.google.com/closure/compiler/docs/api-tutorial3#enable)
3. [What to Watch Out for When
   Using ADVANCED_OPTIMIZATIONS](https://developers.google.com/closure/compiler/docs/api-tutorial3#dangers)
   1. [Removal of Code You Want to Keep](https://developers.google.com/closure/compiler/docs/api-tutorial3#removal)
   2. [Inconsistent Property Names](https://developers.google.com/closure/compiler/docs/api-tutorial3#propnames)
   3. [Compiling Two Portions of Code
      Separately](https://developers.google.com/closure/compiler/docs/api-tutorial3#separately)
   4. [Broken References between Compiled and
      Uncompiled Code](https://developers.google.com/closure/compiler/docs/api-tutorial3#mixed)

## Even Better Compression


With the default compilation level
of `SIMPLE_OPTIMIZATIONS`, the Closure Compiler makes
JavaScript smaller by renaming local variables. There are symbols
other than local variables that can be shortened, however, and there
are ways to shrink code other than renaming symbols. Compilation
with `ADVANCED_OPTIMIZATIONS` exploits the full range of
code-shrinking possibilities.

Compare the outputs for `SIMPLE_OPTIMIZATIONS`
and `ADVANCED_OPTIMIZATIONS` for the following
code:

```
function unusedFunction(note) {
  alert(note['text']);
}

function displayNoteTitle(note) {
  alert(note['title']);
}

var flowerNote = {};
flowerNote['title'] = "Flowers";
displayNoteTitle(flowerNote);
```

Compilation with `SIMPLE_OPTIMIZATIONS` shortens the
code to this:

```
function unusedFunction(a){alert(a.text)}function displayNoteTitle(a){alert(a.title)}var flowerNote={};flowerNote.title="Flowers";displayNoteTitle(flowerNote);
```

Compilation with `ADVANCED_OPTIMIZATIONS` fully shortens the
code to this:

```
alert("Flowers");
```


Both of these scripts produce an alert reading `"Flowers"`,
but the second script is much smaller.


The `ADVANCED_OPTIMIZATIONS` level goes beyond simple
shortening of variable names in several ways, including:

- *more aggressive renaming:*

  Compilation with `SIMPLE_OPTIMIZATIONS` only
  renames the `note` parameters of
  the `displayNoteTitle()`
  and `unusedFunction()` functions, because these are
  the only variables in the script that are local to a
  function. `ADVANCED_OPTIMIZATIONS` also renames the
  global variable `flowerNote`.
- *dead code removal:*


  Compilation with `ADVANCED_OPTIMIZATIONS` removes
  the function `unusedFunction()` entirely, because it
  is never called in the code.
- *function inlining:*

  Compilation with `ADVANCED_OPTIMIZATIONS` replaces
  the call to `displayNoteTitle()` with the
  single `alert()` that composes the function's
  body. This replacement of a function call with the function's
  body is known as "inlining". If the function were longer or more
  complicated, inlining it might change the behavior of the code,
  but the Closure Compiler determines that in this case inlining
  is safe and saves space. Compilation
  with `ADVANCED_OPTIMIZATIONS` also inlines constants
  and some variables when it determines that it can do so
  safely.


This list is just a sample of the size-reducing transformations
that `ADVANCED_OPTIMIZATIONS` compilation can perform.

## How to Enable ADVANCED_OPTIMIZATIONS


To enable `ADVANCED_OPTIMIZATIONS` for the Closure
Compiler application, include the command line
flag `--compilation_level ADVANCED_OPTIMIZATIONS`, as in
the following command:

```
java -jar compiler.jar --compilation_level ADVANCED_OPTIMIZATIONS --js hello.js
```

## What to Watch Out for When
Using ADVANCED_OPTIMIZATIONS


Below are listed some common unintended effects
of ADVANCED_OPTIMIZATIONS, and steps you can take to avoid them.

### Removal of Code You Want to Keep


If you compile just the function below
with `ADVANCED_OPTIMIZATIONS`, Closure Compiler produces
empty output:

```
function displayNoteTitle(note) {
  alert(note['myTitle']);
}
```


Because the function is never called in the JavaScript that you pass to
the compiler, Closure Compiler assumes that this code is not needed!


In many cases this behavior is exactly what you want. For example, if
you compile your code together with a large library, Closure Compiler can
determine which functions from that library you actually use and
discard the ones that you don't use.


If, however, you find that Closure Compiler is removing functions you want to
keep, there are two ways to prevent this:

- Move your function calls into the code processed by Closure Compiler.
- Include externs for the functions you want to expose.


The next sections discuss each option in more detail.

#### Solution: Move Your Function Calls into the Code
Processed by the Closure Compiler


You may encounter unwanted code removal if you only compile part of
your code with Closure Compiler. For example, you might have a library file that
contains only function definitions, and an HTML file that includes the
library and that contains the code that calls those functions. In this
case, if you compile the library file
with `ADVANCED_OPTIMIZATIONS`, Closure Compiler removes
all of your library functions.


The simplest solution to this problem is to compile your functions
together with the portion of your program that calls those functions.
For example, Closure Compiler will not remove `displayNoteTitle()`
when it compiles the following program:

```
function displayNoteTitle(note) {
  alert(note['myTitle']);
}
displayNoteTitle({'myTitle': 'Flowers'});
```


The `displayNoteTitle()` function isn't removed in this
case because Closure Compiler sees that it is called.


In other words, you can prevent unwanted code removal by including
your program's *entry point* in the code that you pass to
Closure Compiler. The entry point of a program is the place in the
code where the program begins executing. For example, in
the [flower note program](https://developers.google.com/closure/compiler/docs/api-tutorial3#smallex) from the previous
section, the last three lines are executed as soon as the JavaScript
is loaded in the browser. This is the entry point for this program. To
determine what code you need to keep, Closure Compiler starts at this
entry point and traces the control flow of the program forward from
there.

#### Solution: Include Externs for the Functions You
Want to Expose


More information on this solution is given [below](https://developers.google.com/closure/compiler/docs/api-tutorial3#extocomp)
and in the page on [externs and exports](https://developers.google.com/closure/compiler/docs/externs-and-exports).

### Inconsistent Property Names


Closure Compiler compilation never changes string literals in your code, no
matter what compilation level you use. This means that compilation
with `ADVANCED_OPTIMIZATIONS` treats properties differently
depending on whether your code accesses them with a string. If you mix
string references to a property with dot-syntax references, Closure Compiler
renames some of the references to that property but not others. As a
result, your code will probably not run correctly.


For example, take the following code:

```
function displayNoteTitle(note) {
  alert(note['myTitle']);
}
var flowerNote = {};
flowerNote.myTitle = 'Flowers';

alert(flowerNote.myTitle);
displayNoteTitle(flowerNote);
```


The last two statements in this source code do exactly the same
thing. However, when you compress the code
with `ADVANCED_OPTIMIZATIONS`, you get this:

```
var a={};a.a="Flowers";alert(a.a);alert(a.myTitle);
```


The last statement in the compressed code produces an error. The
direct reference to the `myTitle` property has been renamed
to `a`, but the quoted reference to `myTitle`
within the `displayNoteTitle` function has not been
renamed. As a result, the last statement refers to
a `myTitle` property that is no longer there.

#### Solution: Be Consistent in Your Property Names


This solution is pretty simple. For any given type or object, use dot-syntax
or quoted strings exclusively. Don't mix the syntaxes, especially in reference
to the same property.


Also, when possible, prefer to use dot-syntax, as it supports better
checks and optimizations. Use quoted string property access only when
you don't want Closure Compiler to do renaming, such as when the name
comes from an outside source, like decoded JSON.

### Compiling Two Portions of Code Separately


If you split your application into different chunks of code, you
might want to compile the chunks separately. However, if two chunks
of code interact at all, doing so may cause difficulty. Even if you
succeed, the output of the two Closure Compiler runs will not be compatible.


For example, assume that an application is divided into two parts: a
part that retrieves data, and a part that displays data.


Here's the code for retrieving the data:

```
function getData() {
  // In an actual project, this data would be retrieved from the server.
  return {title: 'Flower Care', text: 'Flowers need water.'};
}
```

Here's code for displaying the data:

```
var displayElement = document.getElementById('display');
function displayData(parent, data) {
  var textElement = document.createTextNode(data.text);
  parent.appendChild(textElement);
}
displayData(displayElement, getData());
```


If you try to compile these two chunks of code separately, you will
encounter several problems. First, the Closure Compiler removes
the `getData()` function, for the reasons described
in [Removal of Code You Want to Keep](https://developers.google.com/closure/compiler/docs/api-tutorial3#removal). Second,
the Closure Compiler produces a fatal error when processing the code
that displays the data.

```
input:6: ERROR - variable getData is undefined
displayData(displayElement, getData());
```


Because the compiler does not have access to the `getData()`
function when it compiles the code that displays the data, it
treats `getData` as undefined.

#### Solution: Compile All Code for a Page Together


To ensure proper compilation, compile all the code for a page together
in a single compilation run. The Closure Compiler can accept
multiple JavaScript files and JavaScript strings as input, so you can
pass library code and other code together in a single compilation
request.


**Note:** This approach won't work if you need to mix compiled and
uncompiled code. See [Broken References between
Compiled and Uncompiled Code](https://developers.google.com/closure/compiler/docs/api-tutorial3#mixed) for tips on handling this situation.

### Broken References between Compiled and
Uncompiled Code


Symbol renaming in `ADVANCED_OPTIMIZATIONS` will break
communication between code processed by the Closure Compiler and any
other code. Compilation renames the functions defined in your source
code. Any external code that calls your functions will break after you
compile, because it still refers to the old function name. Similarly,
references in compiled code to externally defined symbols may be
altered by Closure Compiler.


Keep in mind that "uncompiled code" includes any code passed to
the `eval()` function as a string. Closure Compiler never alters
string literals in code, so Closure Compiler does not change strings passed
to `eval()` statements.


Be aware that these are related but distinct problems: maintaining
compiled-to-external communication, and maintaining
external-to-compiled communication. These separate problems have a common
solution, but there are nuances to each side. To get the most out of
Closure Compiler it's important to understand which case you have.


Before continuing, you may want to familiarize yourself with
[externs and exports](https://developers.google.com/closure/compiler/docs/externs-and-exports).

#### Solution for Calling into External Code from
Compiled Code: Compiling with Externs


If you use code supplied into your page by another script, you need
to be sure that Closure Compiler doesn't rename your references to the
symbols defined in that external library. To do this, include a file
containing the externs for the external library into your compilation.
That will tell Closure Compiler which names you do not control and
therefore cannot be changed. Your code must use the same names that
the external file uses.


Common examples of this are APIs like the
[OpenSocial API](http://wiki.opensocial.org/index.php?title=JavaScript_API_Overview_(v0.8))
and the [Google Maps API](https://developers.google.com/maps). For instance, if
your code calls the OpenSocial function `opensocial.newDataRequest()`,
without the appropriate externs, Closure Compiler will transform
this call into `a.b()`.

#### Solution for Calling into Compiled Code from
External Code: Implementing Externs


If you have JavaScript code that you reuse as a library, you may want
to use Closure Compiler to shrink only the library while still allowing
uncompiled code to call functions in the library.


The solution in this situation is to implement a set of externs defining
the public API of your library. Your code will supply definitions
for the symbols declared in these externs. This means any classes or
functions your externs mention. It may also mean having your classes
implement interfaces declared in the externs.


These externs are useful for others as well, not just yourself. Consumers
of your library will need to include them if they are compiling their
code, since your library represents an external script from their
perspective. Think of the externs as the contract between you and your
consumers, you both need a copy.


To this end, make sure that when you compile your code, you also include
the externs in the compilation. This may seem unusual, since we often think
of externs as "coming from somewhere else", but it's necessary to tell
Closure Compiler which symbols you're exposing, so they aren't renamed.


One important caveat here is that you may get "duplicate definition"
diagnostics about the code defining the extern symbols. Closure Compiler
assumes that any symbol in the externs is being supplied by an outside library,
and can't currently understand that you are intentionally supplying a definition.
These diagnostics are safe to
[suppress](https://github.com/google/closure-compiler/wiki/@suppress-annotations), and
you can think of the suppression as a confirmation that you really are fulfilling your API.


Additionally, Closure Compiler may typecheck that your definitions match
the types of the extern declarations. This provides additional confirmation
that your definitions are correct.