From 6705a343584e3ae46194632ab26debb0e1c24cef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Lemoine?= Date: Tue, 31 Mar 2015 18:28:32 +0200 Subject: [PATCH] Add "closure" tutorial Tutorial describing how to compile application and OpenLayers together. --- doc/tutorials/closure.md | 339 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 339 insertions(+) create mode 100644 doc/tutorials/closure.md diff --git a/doc/tutorials/closure.md b/doc/tutorials/closure.md new file mode 100644 index 0000000000..f1fef84697 --- /dev/null +++ b/doc/tutorials/closure.md @@ -0,0 +1,339 @@ +--- +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 [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", + "node_modules/openlayers/externs/vbarray.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", + "node_modules/openlayers/externs/vbarray.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 + + + + + + + + Simple example + + + +
+ + + +``` + +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 + +``` + +Reload the page in your browser and you should see that scripts are now loaded +individually, making debugging much easier.