Sponsored Links

Optimizing OpenLayers PDF Print E-mail
Written by Richard Marsden   
Monday, 05 October 2009 07:40

OpenLayers is a powerful open source JavaScript client that is often used to create AJAX "slippy" maps in an open source stack (see our previous technical overview). OpenLayers supports a wide range of data sources, layer types, and languages; and this list keeps growing with each release. Unfortunately this constant growth has a downside: the standard JavaScript file is now 711K in size!

This article shows you how to make your OpenLayers map applications more efficient by drastically reducing the size of this script file.

 

In the two years since I started to use OpenLayers, it has doubled in size to 711K (version 2.8). This growth has been due to the addition of a growing number of data sources, layer types, standard controls, and languages. These are all useful things which increase the utility of OpenLayers, but they also result in code bloat. Few if any applications use more than a small number of the available features. Of course each application uses a different subset of features! Would it not be great if we could cut OpenLayers.js down to just include the features that we require? We can, by using the build scripts which are provided with OpenLayers.

The standard OpenLayers package can be downloaded from the main OpenLayers website. In addition to the main OpenLayers.js script, this package includes a complete set of component scripts and a build environment. We shall use the scripts in this build environment to create a custom OpenLayers.js with just the support that we require. The following examples assume you are working with OpenLayers v2.8. You may need to change the exact directory names to match the version you are using.

Make sure you also have Python installed because this is used by the main build script. You will also need to use a command line environment. The Windows command prompt should be usable, but I used FreeBSD (as used by my web host).

Download and uncompress the latest version of OpenLayers. Navigate to the OpenLayers root directory (~/OpenLayers-2.8 in this example). Note that this directory holds the standard build of OpenLayers.js along with auxiliary files (eg. the standard theme). It also holds other directories that you might find useful, such as the documentation and source components. We are interested in the build sub-directory. Navigate to this. You will see a number of explanatory text file notes, three cfg configuration files, and two Python scripts called build.py and buildUncompressed.py. These simply build a new OpenLayers.js using a particular configuration file. Normally, you will use build.py which compresses the final output, but buildUncompressed.py might be useful if you wish to edit or otherwise amend the resulting script.

Running the script is very simple. In a Unix-like shell, simply run "./build.py yourconfig.cfg" where yourconfig.cfg is the name of the configuration file to use. The script takes a few seconds to run, and provides a list of the included components, and further components that are required by these. The resulting OpenLayers.js is written to the build directory.

Three standard configurations ship with OpenLayers:

  • full.cfg : This is the full build with all file components.
  • lite.cfg : A small subset of OpenLayers, designed for integration into other applications. Supports WMS, but excludes all of the standard controls.
  • library.cfg : Includes everything except for vector support.

 

You will probably want to create your own configuration file. Here is the one I created for the OpenLayers/MapServer map at EcoMapCostaRica.com:

   1 
   2 
   3 
   4 
   5 
   6 
   7 
   8 
   9 
  10 
  11 
  12 
  13 
  14 
  15 
  16 
  17 
  18 
  19 
  20 
  21 
  22 
  23 
  24 
  25 
  26 
  27 
  28 
  29 
  30 
  31 
  32 
  33 
  34 
  35 
  36 
  37 
  38 
  39 
  40 
  41 
  42 
  43 
  44 
  45 
  46 
  47 
  48 
  49 
  50 
  51 
  52 
  53 
  54 
  55 
  56 
  57 
  58 
  59 
  60 
  61 
  62 
  63 
  64 
  65 
  66 
  67 
  68 
  69 
  70 
  71 
  72 
  73 
  74 
  75 
  76 
  77 
  78 
  79 
  80 
  81 
  82 
  83 
  84 
  85 
  86 
  87 
  88 
  89 
  90 
  91 
  92 
  93 
  94 
  95 
  96 
  97 
  98 
  99 
 100 
 101 
 102 
 103 
 104 
 105 
 106 
 107 
 108 
 109 
 110 
 111 
 112 
 113 
 114 
 115 
 116 
 117 
 118 
 119 
 120 
 121 
 122 
 123 
 124 
 125 
 126 
 127 
 128 
 129 
 130 
 131 
 132 
 133 
 134 
 135 
 136 
 137 
 138 
 139 
 140 
 141 
 142 
 143 
 144 
 145 
 146 
 147 
 148 
 149 
 150 
 151 
 152 
 153 
 154 
 155 
 156 
 157 
 158 
 159 
 160 
 161 
 162 
 163 
 164 
 165 
 166 
 167 
 168 
 169 
 170 
 171 
 172 
 173 
 174 
 175 
 176 
 177 
 178 
 179 
 180 
 181 
 182 
 183 
 184 
 185 
 186 
 187 
 188 
 189 
 190 
 191 
 192 
 193 
 194 
 195 
 196 
 197 
 198 
 199 
 200 
 201 
 202 
 203 
 204 
 205 
 206 
 207 
 208 
 209 
 210 
 211 
# OpenLayers build script for EcoMapCostaRica.com 

[first]
OpenLayers/SingleFile.js
OpenLayers.js
OpenLayers/BaseTypes.js
OpenLayers/BaseTypes/Class.js
OpenLayers/Util.js
Rico/Corner.js

[last]

[include]

[exclude]
Firebug/firebug.js
Firebug/firebugx.js
Gears/gears_init.js

OpenLayers/Projection.js
OpenLayers/Protocol.js
OpenLayers/Rule.js
OpenLayers/Console.js
OpenLayers/Filter.js
OpenLayers/Ajax.js
OpenLayers/StyleMap.js
OpenLayers/Marker.js
OpenLayers/Request.js
OpenLayers/Events.js
OpenLayers/Style.js
OpenLayers/Lang.js
OpenLayers/Feature.js
OpenLayers/Map.js
OpenLayers/Popup.js
OpenLayers/Geometry.js
OpenLayers/Icon.js
OpenLayers/Tween.js
OpenLayers/Format.js
OpenLayers/Handler.js
OpenLayers/Strategy.js
OpenLayers/Tile.js
OpenLayers/Renderer.js
OpenLayers/Control.js
OpenLayers/Layer.js

OpenLayers/Format/GML.js
OpenLayers/Format/GML/v3.js
OpenLayers/Format/GML/v2.js
OpenLayers/Format/GML/Base.js
OpenLayers/Format/GeoRSS.js
OpenLayers/Format/Filter.js
OpenLayers/Format/Filter/v1_0_0.js
OpenLayers/Format/Filter/v1_1_0.js
OpenLayers/Format/Filter/v1.js
OpenLayers/Format/WKT.js
OpenLayers/Format/WFS.js
OpenLayers/Format/WFST.js
OpenLayers/Format/WFST/v1_0_0.js
OpenLayers/Format/WFST/v1_1_0.js
OpenLayers/Format/WFST/v1.js
OpenLayers/Format/WFSCapabilities.js
OpenLayers/Format/WFSCapabilities/v1_0_0.js
OpenLayers/Format/WFSCapabilities/v1_1_0.js
OpenLayers/Format/WFSCapabilities/v1.js
OpenLayers/Format/WFSDescribeFeatureType.js
OpenLayers/Format/WMC.js
OpenLayers/Format/WMC/v1_0_0.js
OpenLayers/Format/WMC/v1_1_0.js
OpenLayers/Format/WMC/v1.js
OpenLayers/Format/WMSDescribeLayer.js
OpenLayers/Format/WMSDescribeLayer/v1_1.js
OpenLayers/Format/WMSCapabilities.js
OpenLayers/Format/WMSCapabilities/v1_1.js
OpenLayers/Format/WMSCapabilities/v1_1_0.js
OpenLayers/Format/WMSCapabilities/v1_1_1.js
OpenLayers/Format/WMSGetFeatureInfo.js
OpenLayers/Format/SLD.js
OpenLayers/Format/SLD/v1_0_0.js
OpenLayers/Format/SLD/v1.js
OpenLayers/Format/ArcXML.js
OpenLayers/Format/ArcXML/Features.js
OpenLayers/Format/GeoJSON.js
OpenLayers/Format/Text.js
OpenLayers/Format/OSM.js
OpenLayers/Format/GPX.js
OpenLayers/Format/XML.js
OpenLayers/Format/JSON.js

OpenLayers/Popup/Framed.js
OpenLayers/Popup/AnchoredBubble.js
OpenLayers/Popup/Anchored.js

OpenLayers/Filter/Comparison.js
OpenLayers/Filter/FeatureId.js
OpenLayers/Filter/Spatial.js
OpenLayers/Filter/Logical.js

OpenLayers/Geometry/Surface.js
OpenLayers/Geometry/Curve.js
OpenLayers/Geometry/Polygon.js
OpenLayers/Geometry/LinearRing.js
OpenLayers/Geometry/Collection.js
OpenLayers/Geometry/LineString.js
OpenLayers/Geometry/MultiPolygon.js
OpenLayers/Geometry/Rectangle.js
OpenLayers/Geometry/Point.js
OpenLayers/Geometry/MultiPoint.js
OpenLayers/Geometry/MultiLineString.js

OpenLayers/Strategy/Save.js
OpenLayers/Strategy/Paging.js
OpenLayers/Strategy/Fixed.js
OpenLayers/Strategy/Cluster.js
OpenLayers/Strategy/BBOX.js

OpenLayers/Layer/ArcIMS.js
OpenLayers/Layer/ArcGIS93Rest.js
OpenLayers/Layer/Boxes.js
OpenLayers/Layer/FixedZoomLevels.js
OpenLayers/Layer/GeoRSS.js
OpenLayers/Layer/Google.js
OpenLayers/Layer/Grid.ks
OpenLayers/Layer/HTTPRequest.js
OpenLayers/Layer/Image.js
OpenLayers/Layer/KaMap.js
OpenLayers/Layer/KaMapCache.js
OpenLayers/Layer/MapGuide.js
OpenLayers/Layer/Markers.js
OpenLayers/Layer/MultiMap.js
OpenLayers/Layer/PointTrack.js
OpenLayers/Layer/SphericalMercator.js
OpenLayers/Layer/Text.js
OpenLayers/Layer/TileCache.js
OpenLayers/Layer/TMS.js
OpenLayers/Layer/VirtualEarth.js
OpenLayers/Layer/WMS.js
OpenLayers/Layer/WMS/Untiled.js
OpenLayers/Layer/WorldWind.js
OpenLayers/Layer/XYZ.js
OpenLayers/Layer/Yahoo.js
OpenLayers/Layer/WFS.js

OpenLayers/Protocol/SQL.js
OpenLayers/Protocol/WFS.js
OpenLayers/Protocol/WFS/v1_0_0.js
OpenLayers/Protocol/WFS/v1_1_0.js
OpenLayers/Protocol/WFS/v1.js
OpenLayers/Protocol/SQL/Gears.js

OpenLayers/Protocol/HHTP.js
OpenLayers/Request/XMLHttpRequest.js

OpenLayers/Control/KeyboardDefaults.js
OpenLayers/Control/DrawFeature.js
OpenLayers/Control/Snapping.js
OpenLayers/Control/Button.js
OpenLayers/Control/WMSGetFeatureInfo.js
OpenLayers/Control/Measure.js
OpenLayers/Control/DragFeature.js
OpenLayers/Control/OverviewMap.js
OpenLayers/Control/Split.js
OpenLayers/Control/ModifyFeature.js
OpenLayers/Control/Permalink.js
OpenLayers/Control/EditingToolbar.js
OpenLayers/Control/Scale.js
OpenLayers/Control/ZoomOut.js
OpenLayers/Control/ZoomIn.js
OpenLayers/Control/ZoomBox.js
OpenLayers/Control/Pan.js
OpenLayers/Control/PanZoom.js
OpenLayers/Control/ZoomToMaxExtent.js
OpenLayers/Control/Navigation.js
OpenLayers/Control/NavigationHistory.js
OpenLayers/Control/MouseDefaults.js
OpenLayers/Control/MousePosition.js
OpenLayers/Control/DragPan.js

OpenLayers/Control/PanPanel.js
OpenLayers/Control/Panel.js
OpenLayers/Control/ZoomPanel.js
OpenLayers/Control/MouseToolbar.js
OpenLayers/Control/GetFeature.js

OpenLayers/Feature/WFS.js
OpenLayers/Feature/Vector.js
OpenLayers/Tile/WFS.js
OpenLayers/Marker/Box.js
OpenLayers/Renderer/VML.js

OpenLayers/Handler/Keyboard.js
OpenLayers/Handler/Hover.js
OpenLayers/Handler/Polygon.js
OpenLayers/Handler/RegularPolygon.js
OpenLayers/Handler/Box.js
OpenLayers/Handler/Path.js

OpenLayers/Lang/ca.js
OpenLayers/Lang/cs-CZ.js
OpenLayers/Lang/da-DK.js
OpenLayers/Lang/de.js
OpenLayers/Lang/en-CA.js
OpenLayers/Lang/es.js
OpenLayers/Lang/fr.js
OpenLayers/Lang/it.js
OpenLayers/Lang/nb.js
OpenLayers/Lang/nl.js
OpenLayers/Lang/pt-BR.js
OpenLayers/Lang/sv-SE.js
OpenLayers/Lang/zh-TW.js
OpenLayers/Lang/zh-CN.js

 

Comment lines start with a '#' character. This configuration file is split into groups: first, last, include, and exclude. We only use the first and exclude sections. The first section includes all of the core components. We then switch individual components off with the exclude section. All of the non-English language support is excluded because the parent website currently only uses English.

Our exclude section is probably a lot larger than it needs to be. OpenLayers contains a lot of components and their inter-dependencies are often complex. Many of the component names are easy to understand (eg. OpenLayers/Layer/WMS.js provides WMS layer support), but it is harder to determine if many are required. I therefore used a trial-and-error approach excluding about half a dozen components at a time, and checking that the resulting build worked in the final application. Many of the excluded components are actually included because other essential components require on them. The output from build.py was useful in identifying possible components to exclude.

And the result? The final OpenLayers.js has shrunk more than 50% from 711KB to 343KB. This will reduce the website bandwidth requirements, but more importantly, it will result in a web map that loads and becomes active more quickly for the end user.

A similar process was applied to Equal-Area-Maps.com (URL), but GeoRSS layer support was included and Vector layer support was excluded.

The trial-and-error approach to building a configuration file that produces a minimal but usable OpenLayers.js, is time consuming to say the least. Tom MacWright is in the process of solving this with his OpenLayerer online build tool. Simply select the checkboxes for the required components, press the Generate button, and an OpenLayers.js script is ready for download. I tried using this, but I was not able to produce a usable OpenLayers.js script for my online maps. It would appear that OpenLayerer automatically excludes some rendering components: I was not able to use the OpenLayers.js script even with all checkboxes checked. So a "work in progress" but something which should make the process of creating small, efficient OpenLayers scripts a lot quicker and easier.


Comments (3)Add Comment
0
HTTP compression
written by -, October 05, 2009
How about enabling HTTP compression? That should reduce the needed bandwidth by about 90%.
0
Use include instead of exclude
written by Paul Spencer, October 05, 2009
If you are going for a minimalist build, try using include to keep the things you know you want rather than exclude the things you don't. The advantages are that the list will (probably) be shorter, you know you have what you just what you need plus dependencies, and you don't need to change when updating to a newer version that has new things to be excluded.
62
Thanks for the suggestions
written by Richard Marsden, October 06, 2009
Thanks for the suggestions. If anyone has any recommendations for speeding OpenLayers, then feel free to add them to this thread.

"Anonymous": Good idea. Also the build script does "compress" the Javascript by removing all pretty printing. HTTP compression would cut this further, and also speed many of the data downloads (eg. KML).

Paul: Yes in theory this is a much better approach. However, when starting from scratch it is difficult to know exactly which components are required. Some are obvious (eg. I needed the GML layer support for KML) but others are not, so a trial&error approach is still required. The [first] section would also have to be cut back, and it would be a case of adding lots of things until it works. It is easier to start with something that works, rather than to try to keep adding things until it does.

Perhaps the output from my build script could be used as a basis of a script along the lines that you describe. The end result would then be the more stable build (as you describe).

Write comment

security code
Write the displayed characters


busy