MapStore 2: Modern WebMapping with React

MapStore at work

Dear All,
First of all this is going to be a long blog post, so be prepared. We are going to talk about the work we are doing to create the new version of our webmapping open source product, MapStore. Although the product is not ready to be released there is quite some good experience that we can share so we thought it was already worth sharing it on our blog.

Btw, if you are like me and prefer pictures over words skip at the end of the post to see some action!

MapStore 1.x: the ugly, the bad and the good

MapStore 1.x is a nice WebGis framework due to its pluggable architecture, and its coherent and familiar look & feel.
Unfortunately its pillars (OpenLayers and ExtJS) represents both its strength and its weakness. From them MapStore inherited the ease of extension and many powerful widgets, but also the difficulty to progressively evolve to embrace new emerging needs, for example a more modern look & feel and new features coming from newer mapping libraries.

MapStore was built using a monolithic approach, fully depending on ExtJS for the look & feel and the application infrastructure, and also strictly bound to OpenLayers for the mapping capabilities, through the adoption of GeoExt and gxp as an additional layer of dependency. Eventually we were at a point where we could not think to plan any important improvement without rethinking the overall MapStore architecture from the ground.

We had two alternatives: remain in the comfort zone and upgrade MapStore to new versions of ExtJS (6.0) and OpenLayers (3), eventually contributing to the GeoExt project to support them, or take the risk to choose a new set of technologies and build a completely new version of MapStore based on them. This forced us to get out of the cretaceous era of web development and discover a new world that was emerging around us.

Emerging trends in the JavaScript world

The world of web development (especially client-side based on Javascript) got a tremendous drift in the last two years, mainly due to some new frameworks that are replacing the old ones and a refreshed version of the language that has been made standard with the name of ES6 (or ES2015).

A quick history of (modern) Javascript libraries and frameworks can be the following:

  • At the beginning there was jQuery, the catch’em all DOM manipulating mini library, that was good for any small to medium website development
  • Then came ExtJS, for the enterprise level web application, that brought a full architecture and a desktop like interface to the web (for the first time we can talk of Javascript written applications instead of a bunch of scripts animating a page)
  • The need of architecture to handle complex applications, brought to a set of frameworks whose purpose was to migrate the usual patterns from the server-side to Javascript: MVC is the most common pattern, BackboneJS is probably the most common framework implementing it
  • Finally a new catch’em all came out with the name of AngularJS and was backed by Google: AngularJS had a honey trap, named two way data binding, that makes you think developing with AngularJS is very simple and synthetic, but behind the scenes there is a lot of complexity (when you start looking at factories, providers and services, you remember “Thinking in Java” and your brain starts to think: do we need all this stuff in Javascript?)
  • Facebook decided to not leave Google alone in the Javascript frameworks arena, and open sourced its internal framework to build web components named ReactJS, whose purpose was to be the V in MVC (or MVVM or WhateverVWhatever) pattern

In the meantime, also the Javascript language was changing. First of all, thanks to NodeJS it is not limited to the browser anymore. Then, the language is rapidly evolving with new standards, like the already approved ES6 and the upcoming ES7. Also several ways to handle modules and dependencies are available (UMD, CommonJS, ES6 modules).
Finally, thanks to transpilers (expecially Babel) you don’t have to wait for browsers to implement the standards anymore, you can start using them today. You can also use other languages that can be compiled to Javascript (e.g. Typescript). At the end, Javascript and expecially ES5 is rapidly becoming the assembly of the web.

On the side, a new set of tools is now available that mimic the functionalities of our beloved Java server-side tools for code and project management:

  •  Npm → maven
  • Gulp/Grunt → ant

MapStore 2: A Pinch of This, A Handful of That

We had to decide what to do with the next MapStore version and definitely, there was a lot to choose from.

Moving onto using newer versions of ExtJS and GeoExt was a no go from the beginning: we have been hurt enough already by the monolithic approach of ExtJS, and we wanted a simpler solution.
The world of web development is looking for more simplicity to handle complexity (whether this has been achieved or not is hard to say though…). We were looking for smaller libraries with a specific purpose that could be replaced with a smaller effort than the full ExtJS. We were also trying not to choose a single mapping library for any possible application.

Let’s explore the options.

Mapping Libraries

  • OpenLayers 3: a complete mapping library with many functionalities and controls, on the heavy side, with a renewed, canvas based rendering engine
  • LeafletJS: a light and simple mapping library, with a pluggable architecture
  • CesiumJS: the earth is an oblate sphere, why should we make flat boring maps?

Basic JS framework / libraries

  • AngularJS 1.x: the most promising framework with both a web component architecture (through directives) and a data flow infrastructure, based on two way data binding; modularity is handled mainly by dependency injection. Seems a little bit complex, and AngularJS 2.x is coming and it’s announced to be incompatible with version 1
  • EmberJS: MVC based, with interchangeable template system and based on conventions. Seems a little bit immature, it’s not clear what is going to be in the future, probably too rapidly evolving
  • ReactJS: opinionated library to build the view of a web application, some concerning choices (JSX, Virtual DOM, no clear architectural choice)

Our decision

The world of web development is rapidly moving, but we had to take a decision: we had to choose something that was not going (at least in our hopes) away in a couple of years, and if it did, we could plan the switch in steps, instead of throwing everything away like we are doing now.

Both AngularJS and EmberJS seemed too fast moving targets, with upcoming, revolutionary, 2.x versions at the door, and the underlying complexity of AngularJS was a little bit intimidating to us. ReactJS, on the other side was simple enough and didn’t take care of the overall application, concentrating on the view aspect, through the composition of small components.
We could choose ReactJS and use something else for other parts of the application: data flow, state management, web services interaction, etc.

We also didn’t want to choose a single mapping library, but rather trying to be compatible at least with OpenLayers 3 and LeafletJS leaving room for the integration of other libraries in the future. The component architecture of ReactJS allows this, by building interchangeable components, abstracting the underlying mapping implementation. So, the choice was to choose as little as possible, at least from the beginning.

We started building a set of core components, using ReactJS, like Map, MousePosition, TOC, etc. clearly distinguishing the ones strictly depending from the mapping libraries and the ones that do not depend on them (so that we can easily switch the mapping library as needed). The components depending from the mapping library were implemented both for OpenLayers 3 and LeafletJS, so that:

  • they shared the same interface (the set of component properties and their meaning), to be interchangeable
  • they were independent from other components, to avoid duplication

It was also important to us that the components depending strictly on the underlying mapping library were taken to the bare minimum (mostly the Map component(s)) in order to limit the coupling with it.

When the first components were ready, we needed to build a little bit of infrastructure, and we started choosing from one of the several implementations of Flux (the one-way-dataflow architecture backed by Facebook). First of all, did we need Flux? For sure we needed something to write the glue code that could made the ReactJS components communicate.

In that precise moment a new library was emerging from the crowd of Flux implementations. Its name is Redux, and it’s not a ReactJS only technology.
Redux is about simplifying state management through a set of principles:

  • Single source of truth
  • Immutability of the state
  • Pure functions to describe state transitions

It looked like the perfect match for our need of simplicity, so we adopted it right away, adding actions, reducers and a store to our components, so that they could be made into a real application, and our first examples were born.

Quality, quality and also quality

For MapStore 2 we wanted to focus on superior quality for the code with respect to the previous version. This basically meant:

  • Adding unit testing for components, actions and reducers
  • Adding a build process based on npm and webpack, integrated with server-side through maven (and this is probably the part that still needs more simplicity)
  • Add continuous build (using Travis CI) and deploy (using Jenkins) on the demo server where manual testing is performed after each deploy
  • Nobody should commit directly without a peer review, hence PR are the suggested way of contributing
  • We use codacy to control code quality
  • We use coveralls to enforce at least 80% code coverage

Have a look at the project on GitHub. We are open to suggestions for improvement…

MapStore 2: we are almost there…

Ok, enough talking let’s see some pictures to show what we have done so far. The code is Open Source (License is Simplified BSD) and is available on GitHub. The current demo page is here and the continuous build and deploy with Jenkins is here. Let’s dig a little into the various widgets and components.

We have built a minimal viewer application with a set of widgets for both LeafletJS and OpenLayers 3 (can you spot the difference?).

OL3 vs LeafletJS MapViewer

OL3 vs LeafletJS MapViewer

We have experimented with a specific layout for mobile, that kicks-in automatically when the application is used from a mobile device.

Experimental mobile layout

Experimental mobile layout

We have built a 3D viewer based on CesiumJS.

Cesium 3D viewer

Cesium 3D viewer

We have created a full set of basic components like: LocateMe, IdentifyOnMap, TableOfContents, BackgroundSwitcher, Measure, Snapshot (and more are coming).

basic components

basic components

We have built data filtering and visualization components like the QueryBuilder and the FeatureGrid.

QueryBuilder

QueryBuilder Widget

FeatureGrid

FeatureGrid Widget

We have also implemented a JSX based templating system for advanced data viewing.

JSX based templating system for advanced data viewing - Sample Template

JSX based templating system for advanced data viewing – Sample Template

JSX based templating system for advanced data viewing - Result for Sample Template

JSX based templating system for advanced data viewing – Result for Sample Template

In case you wondered, we are already using the MapStore 2 framework in some of the applications we are developing for our clients and 2 of them are already being used in production, so yes, MapStore 2 is not a toy, it can be used in production too!

As an example we have recently migrated an application based on ExtJS and OpenLayers 2 (see pictures below) to show geological and other kind of data with a powerful timeslider functionality and support for many different coordinate systems (also polar ones). The application is a clear example of the level of customization MapStore 2 allows with relative ease (the customer explicitly asked to mimic the L&F of the old application in many places).

MapStore 2 Complete Application - Advanced Filtering

MapStore 2 Complete Application

MapStore 2 Complete Application - Advanced Filtering

MapStore 2 Complete Application – Advanced Filtering

 

For another client, we are building a configurable system to query (spatial) data published as complex features on GeoServer (through the app-schema extension), using OGC protocols (WMS and WFS). The system leverages the already mentioned data visualization tools available in MapStore 2, in particular the QueryBuilder, the FeatureGrid and the JSX based templating system.

image05 image02

JSX based templating system for advanced data viewing - Result for Sample Template

JSX based templating system for advanced data viewing – Result for Sample Template

What’s next

During this journey we have already learned a lot of stuff; we learned something good:

  • the declarative programming paradigm of ReactJS is good, and together with the one-way-dataflow of Redux makes the application more predictable
  • using ES6 with Babel makes developing in Javascript more fun(ctional) and functional programming is good
  • simple and dumb components are more reusable, through the usage of composition
  • separating state from components makes components more reusable too
  • quality (unit testing, continuous deploy and so on) needs to be there from the beginning to be successful

We also learned something bad:

  • the build process can become painful very soon, and this still needs some love from us, to effectively get out of the npm dependency hell (do you remember of the maven dependency hell?)
  • introducing many new technologies at the same time can be confusing, and requires time to get ingested, mainly to understand what to use and what not, and how to use it
  • integrating ReactJS components to drive Non-ReactJS librarties (such as OpenLayers 3 and LeafletJS) is the point where most of the headaches will come from, so it’s essential to mantain the area of this surface at the minumum

However, the MapStore 2 journey is not finished yet, there is still some work ahead of us to have a full replacement of MapStore 1 and we are targeting end of May 2016 for a first release.

In addition, right now the look & feel is still a bit thrown together and the usability needs some love: we are working on this with a specialized partner as we want a captivating and easy to ise user interface for MapStore 2.

It is worth to point out that some of the work mentioned in this post has been performed under the umbrella of our GeoSolutions Enterprise Support Services offer.

If you want to know more about how we can help your organization, don’t hesitate and get in touch with us! Make sure to check our Enterprise Services Offer which has been used to complete the work described in this post.

The GeoSolutions Team,

Geosolutions