Faster, smaller, better
Compiling your application together with
OpenLayers 3
 
 
Tobias Sauerwein - Guillaume Beraudo
Camptocamp
 
CAMPTOCAMP
How do you like your OpenLayers?
 
 
full build
(ol.js)
custom build compiled
with
application
 
JavaScript
development today
CHALLENGES OF WRITING LARGE JS APPLICATIONS
namespaces/modules?
visibility control?
type checking?
static checking?
testing?
GOOGLE CLOSURE TOOLS
Google Closure Compiler
Google Closure Library
GOOGLE CLOSURE COMPILER
compiles JavaScript to better JavaScript
 
code checks (syntax, variable references)
checks for common pitfalls
static type checking
Transpiler (ES 6 > ES 5)
advanced optimizations (inlining, dead-code)
DEAD-CODE REMOVAL + INLINING
goog.provide('app');
app.printHello = function() {
    console.log('Hello');
};
app.someUnusedFunction = function() {
    console.log('Unused function');
};
app.run = function() {
    app.printHello();
};
app.run();
Compiled
(function(){console.log("Hello");})();
RENAMING
goog.provide('app');
function hello(o) {
    alert('Hello, ' + o.firstName + ' ' + o.last
}
app.run = function() {
    var person = {firstName: 'New', lastName: 
    hello(person);
    console.log(person);
};
app.run();
Compiled (pretty_print)
(function(){var a = {a:"New", b:"user"};
alert("Hello, " + a.a + " " + a.b);
console.log(a);
})();
EXPORTS
<button onclick="app.doSomething()">...</button
 
How to prevent that app.doSomethingis renamed or removed?
 
/**
 * @export
 */
app.doSomething = function() {
    ...
};
TYPE ANNOTATIONS
/**
 * @constructor
 * @param {number} x X.
 * @param {number} y Y.
 * @param {number=} opt_z Z.
 */
app.Point = function(x, y, opt_z) { ... };
/**
 * @param {!app.Point} other An other point.
 * @return {number} The distance.
 */
app.Point.prototype.distanceTo = function(other)
JSDOC TAGS: A SELECTION
@const@constructor@enum@export
@extends@final@implements@interface
@nosideeffects@param@private
@protected@return@throws@type...
 
Reference
Why bother with types?
WHY TYPES?
Understanding code
entries.forEach(function(entry) {
  entry.data.validate();
});
What does this code do?
WHY TYPES?
Static type check
var point = new app.Point([0, 0]);
ERR! compile src/main.js:14: WARNING ­ Function app.P
  called with 1 argument(s). Function requires at lea
  2 argument(s) and no more than 3 argument(s).
ERR! compile     var p5 = new app.Point([0, 0]);
ERR! compile              ^
ERR! compile
ERR! compile src/main.js:14: WARNING ­ actual paramet
  app.Point does not match formal parameter
ERR! compile found   : Array
ERR! compile required: number
ERR! compile     var p5 = new app.Point([0, 0])
ERR! compile 0 error(s), 2 warning(s)
ERR! compile 95.5% typed
WHY TYPES?
IDE integration, refactorings
USING EXTERNAL LIBRARIES
Compile with application
library must be compatible to Closure Compiler
Reference library outside compilation
compilation requires an externsfile
<script type="text/javascript" src="libs/jquery.min.j
<script type="text/javascript" src="build/app.js"></
EXTERNS FILES
var map = L.map('map').setView([0, 0], 13);
ERR! compile src/main.js:4: ERROR ­ variable L is und
externsfile
/** @const */
var L = {};
/**
 * @param {string} div
 * @return {LeafletMap}
 */
L.map = function(div) {};
/** @constructor */
var LeafletMap = function() {};
...
And OpenLayers?
SIMPLE EXAMPLE WITH OL3
goog.provide('app');
goog.require('ol.Map');
goog.require('ol.View');
goog.require('ol.layer.Tile');
goog.require('ol.source.OSM');
var 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})
});
COMPILER CONFIGURATION
{
  "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",
      ...
    ],
    "define": ["ol.ENABLE_DOM=false", "ol.ENABLE_WEBGL=false
    "compilation_level": "ADVANCED",
    "output_wrapper": "(function(){%output%})();",
    ...
  }
}
TOOLING
compiler.jar
Closure Compiler as Java CLI tool
closure-util
npm package, wrapper around compiler.jar, dev. server
closure-utilbuildconfig.jsondist/app.js
closure-utilserveconfig.json
WHY COMPILE WITH OPENLAYERS?
Only pay for what you use (build size)
Easier to extend OpenLayers
Benefit from the advantages of the Closure Compiler
(static/type checking, efficient code, ...)
BUILD SIZES
EXAMPLE PROJECTS
(ol3 + Cesium)
(ol3 + Angular)
(ol3 + ngeo + Angular)
(ol3 + Angular + Cesium)
(ol3 + ngeo + Angular + Cesium)
(ol3 + ngeo +
Angular)
...
openlayers/ol3
openlayers/ol3-cesium
camptocamp/ngeo
Geoportail-Luxembourg/geoportailv3
geoadmin/mf-geoadmin3
SwitzerlandMobility
camptocamp/provelobern_bicyclerouteplanner
Learning curve?
RESOURCES: HOW TO GET STARTED
OpenLayers 3 Tutorial: Compiling Application with Closure
Compiler
Google Closure Documentation
Book: Closure - The Definitive Guide by Michael Bolin
Annotating JavaScript for the Closure Compiler
Google I/O 2011: JavaScript Programming in the Large with
Closure Tools
Externs files
Compiler options
closure-util
More resources
Examples used in this talk
FUTURE / ALTERNATIVES
Support for ES 6 modules in OpenLayers 3 (module
bundlers: tree-shaking)
Closure Compiler is a transpiler (ES 6 > ES 5)
TypeScript
THIS TALK
Slides
bit.ly/ol3-closure
 
Find us on GitHub/Twitter
Tobias: @tsauerwein
Guillaume: @gberaudo
CREDITS FOR THESE GREAT PHOTOS!

OpenLayers 3 & Google Closure Compiler