---
title: Compiling Application with Closure Compiler
layout: doc.hbs
---

# Compiling Application with Closure Compiler

The OpenLayers 3 code uses the Closure Library, and it is compiled with the
Closure Compiler. Using OpenLayers 3 in an application does not require using
Closure. But using Closure in an OpenLayers 3 application is possible. And this
is what this tutorial is about.

This tutorial will teach you how to set up an OpenLayers 3 application based on
the [`closure-util`](https://github.com/openlayers/closure-util) node package,
which provides utilities for working with Closure. Using `closure-util` is one
way to use Closure in a web application, but there are others. This tutorial
just covers the "`closure-util`" way.

The `closure-util` documentation is available on the [`closure-util` readme
page](https://github.com/openlayers/closure-util/blob/master/readme.md). You
don't need to read the `closure-util` documentation to follow this tutorial,
but it's available in `closure-util`'s [readme
file](https://github.com/openlayers/closure-util/blob/master/readme.md) if you
need it.

Also, the sample application built in this tutorial is
[available](https://github.com/openlayers/openlayers-closure-application) on
GitHub.

## Advantages of using Closure

This tutorial will show you how to use the Closure Compiler to compile an
application and OpenLayers 3 together. Compiling the application code together
with the OpenLayers 3 code has a number of advantages.

First of all, it allows you to only "pay" for the OpenLayers 3 code your
application uses, as the compiler will exclude the OpenLayers 3 code that the
application doesn't use. And there is no need to write and maintain a list of
"exports", which is necessary when creating custom builds of OpenLayers 3.

Also, compiling the application and OpenLayers 3 together allows using
OpenLayers 3 functions and objects that are not part of the official OpenLayers
3 API. Using non-API functions and objects may be risky, but it is mitigated by
the fact that the compiler will complain if you use functions or objects
that are not in OpenLayers 3 anymore.

## Setting up the Application

First, create a directory for the application. We will name that directory
`openlayers-closure-application` in this tutorial.

    $ mkdir openlayers-closure-application

Now change to that directory:

    $ cd openlayers-closure-application

Our application will be a `node` application, and the `openlayers` and
`closure-util` node packages will be downloaded from the node package registry
using the `npm` command line tool.

So we're going to create a `package.json` file for the application, which every
node application includes. This file basically includes metadata for the
application.

Create the application's `package.json` file:

    $ npm init

You can pretty much use the default answers to the questions `npm init` asks
you.

Now install OpenLayers 3 using:

    $ npm install openlayers --save

The `--save` flag persists the `openlayers` dependency in the application's
`package.json` file. You can edit `package.json` to verify that the dependency
was added.

`closure-util` is a dependency of the `openlayers` package, so it should have
been installed with `openlayers`. Use the following to verify that
`closure-util` is installed:

    $ ./node_modules/openlayers/node_modules/.bin/closure-util

    command argument is required

    Usage: node closure-util <command> [options]

    command     
      update-compiler     Update the Compiler
      update-library      Update the Library
      update              Update both the Library and the Compiler
      build               Build with Closure Compiler
      serve               Start the development server

    Options:
       -l LEVEL, --loglevel LEVEL   Log level  [info]


## Create an OpenLayers 3 map

You're now going to create a JavaScript file that creates an OpenLayers 3 map.
This is the file that we will define the application's entry point.

First of all create an `src` directory at the root of the application:

    $ mkdir src

Now add a file `main.js` to `src`, with the following content:

```js
goog.provide('app');

goog.require('ol.Map');
goog.require('ol.View');
goog.require('ol.layer.Tile');
goog.require('ol.source.OSM');


/**
 * @type {ol.Map}
 */
app.map = new ol.Map({
  target: 'map',
  layers: [
    new ol.layer.Tile({
      source: new ol.source.OSM()
    })
  ],
  view: new ol.View({
    center: [0, 0],
    zoom: 4
  })
});
```

`goog.provide('app')` creates the namespace `app` for the application. The
`goog.require` statements that follow define the OpenLayers constructors and
namespaces that the application uses. The rest of the code just creates the
OpenLayers map as you would do in any OpenLayers application.

## Compiling the Application

We're now going to compile the application and OpenLayers 3 together, using the
Closure Compiler and `closure-util`. For this we need to create a JSON config
file, that we will then pass as an input file to the `closure-util` command.

The minimum config file looks like this:

```json
{
  "lib": [
    "node_modules/openlayers/src/**/*.js",
    "node_modules/openlayers/build/ol.ext/**/*.js",
    "src/**/*.js"
  ],
  "compile": {
    "closure_entry_point": "app",
    "externs": [
      "node_modules/openlayers/externs/bingmaps.js",
      "node_modules/openlayers/externs/closure-compiler.js",
      "node_modules/openlayers/externs/geojson.js",
      "node_modules/openlayers/externs/proj4js.js",
      "node_modules/openlayers/externs/tilejson.js",
      "node_modules/openlayers/externs/topojson.js"
    ],
    "define": [
      "goog.array.ASSUME_NATIVE_FUNCTIONS=true",
      "goog.dom.ASSUME_STANDARDS_MODE=true",
      "goog.json.USE_NATIVE_JSON=true",
      "goog.DEBUG=false",
      "ol.ENABLE_DOM=false",
      "ol.ENABLE_WEBGL=false"
    ],
    "js": [
      "node_modules/openlayers/externs/olx.js",
      "node_modules/openlayers/externs/oli.js"
    ],
    "jscomp_off": [
      "unknownDefines"
    ],
    "extra_annotation_name": [
      "api", "observable"
    ],
    "compilation_level": "ADVANCED",
    "warning_level": "VERBOSE",
    "output_wrapper": "(function(){%output%})();",
    "use_types_for_optimization": true
  }
}
```

Create a `config.json` file with the above content at the root of the
application directory.

We can now use `closure-util` to compile the code:

    $ ./node_modules/openlayers/node_modules/.bin/closure-util build config.json app.js

The resulting `app.js` file, which you can view in your editor if you're
curious, includes a minified version of the application code (`main.js`), and
the OpenLayers 3 code that the application code uses.

Here is a version of `config.json` with more compilation checks enabled:

```json
{
  "lib": [
    "node_modules/openlayers/src/**/*.js",
    "node_modules/openlayers/build/ol.ext/**/*.js",
    "src/**/*.js"
  ],
  "compile": {
    "closure_entry_point": "app",
    "externs": [
      "node_modules/openlayers/externs/bingmaps.js",
      "node_modules/openlayers/externs/closure-compiler.js",
      "node_modules/openlayers/externs/geojson.js",
      "node_modules/openlayers/externs/proj4js.js",
      "node_modules/openlayers/externs/tilejson.js",
      "node_modules/openlayers/externs/topojson.js"
    ],
    "define": [
      "goog.array.ASSUME_NATIVE_FUNCTIONS=true",
      "goog.dom.ASSUME_STANDARDS_MODE=true",
      "goog.json.USE_NATIVE_JSON=true",
      "goog.DEBUG=false",
      "ol.ENABLE_DOM=false",
      "ol.ENABLE_WEBGL=false"
    ],
    "js": [
      "node_modules/openlayers/externs/olx.js",
      "node_modules/openlayers/externs/oli.js"
    ],
    "jscomp_error": [
      "accessControls",
      "ambiguousFunctionDecl",
      "checkEventfulObjectDisposal",
      "checkRegExp",
      "checkStructDictInheritance",
      "checkTypes",
      "checkVars",
      "const",
      "constantProperty",
      "deprecated",
      "duplicateMessage",
      "es3",
      "es5Strict",
      "externsValidation",
      "fileoverviewTags",
      "globalThis",
      "internetExplorerChecks",
      "invalidCasts",
      "misplacedTypeAnnotation",
      "missingGetCssName",
      "missingProperties",
      "missingProvide",
      "missingRequire",
      "missingReturn",
      "newCheckTypes",
      "nonStandardJsDocs",
      "suspiciousCode",
      "strictModuleDepCheck",
      "typeInvalidation",
      "undefinedNames",
      "undefinedVars",
      "uselessCode",
      "visibility"
    ],
    "jscomp_off": [
      "unknownDefines"
    ],
    "extra_annotation_name": [
      "api", "observable"
    ],
    "compilation_level": "ADVANCED",
    "warning_level": "VERBOSE",
    "output_wrapper": "(function(){%output%})();",
    "use_types_for_optimization": true
  }
}
```

## Create an HTML file for the Application

You can now go ahead and create a simple HTML for the application. Create
a `index.html` file with the following content at the root the application
directory:

```html
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="chrome=1">
    <meta name="viewport" content="initial-scale=1.0, user-scalable=no, width=device-width">
    <link rel="stylesheet" href="node_modules/openlayers/css/ol.css" type="text/css">
    <title>Simple example</title>
    <style>
      #map {
        width: 600px;
        height: 400px;
      }
    </style>
  </head>
  <body>
    <div id="map"></div>
    <script src="app.js" type="text/javascript"></script>
  </body>
</html>
```

Note that the page includes a `script` tag referencing the `app.js` file,
which is the file resuted from the compilation.

You are done!

## Run Application in Debug Mode

As a bonus, we're going to show how to use `closure-util` to run the
application in "debug" mode, where the original application and OpenLayers
scripts are loaded one by one in the page.

Start the `closure-util` development server:

    $ ./node_modules/openlayers/node_modules/.bin/closure-util serve config.json

Now change the `script` tag to the following in the `index.html` file:

```html
      <script src="@?main=src/main.js" type="text/javascript"></script>
```

Reload the page in your browser and you should see that scripts are now loaded
individually, making debugging much easier.
