Esri’s Web AppBuilder (WAB) is a great tool for getting organizational data into the hands of users without a lot of overhead, and it can be extended when custom functionality is needed. For consultants working as part of a larger team, as well as lone GIS professionals dealing with growing complexity in a set of internal applications, scaling WAB applications can be a challenge. This article proposes some workflows that we have used to write and maintain custom code for WAB apps.
If you are a single developer, the versioning tools built into the WAB may be all that you need. For larger teams following a typical workflow, it is easier to export the application from the WAB and add it to your existing version control system (i.e., git). This will allow multiple developers to work on features simultaneously, taking advantage of existing infrastructure for testing, continuous integration, etc. Once a release is ready, the application can be zipped into an archive, and either imported back into the WAB or deployed directly to a web server.
Custom functionality for a WAB application is almost always implemented via custom widgets. When working on a custom WAB app in a large team, we use the following guidelines:
- Every custom WAB widget gets its own repository;
- Dependencies are managed via bower;
- Each widget is added to the main application in a feature branch, together with the necessary changes to config.json;
- The widget and configuration changes are always checked-in to the main app repository.
It is almost always worth creating a separate repository in your source control system for each custom widget you develop. That way, you can reuse widgets across multiple WAB applications. The simplest workflow is to have each WAB widget contain its own dependencies and to check those dependencies into the widget repository. Once the individual widget repos are set up, the application dependencies can be managed using bower.
Once you have your custom widgets safely checked into their repositories, you can set up bower to pull the custom widgets into the WAB application. The process looks like this:
- Create a .bowerrc file in the WAB application directory, with the following content:
This will configure bower to install the widgets into the widgets/ directory, rather than the default bower_components/.
- Run bower in it within the WAB application directory, to generate a JSON file.
- Add a dependencies object to your bower.json file, with the following structure:
You can add as many widget dependencies as you need, and the git url can be any git repository.
- Now you can use bower to manage your custom widgets as normal, by running
bower install, bower update, etc.
Now each member of the dev team can create their own branch of the WAB application, and their own repository to hold the custom widget they’re working on. When a developer starts on a new feature (a custom widget), they do the following:
- Create a new repository to hold the custom widget;
- Add basic scaffolding and logic for the widget (you can use Tom Wayson’s excellent Yeoman generator!);
- Create a branch from the main line of the WAB application;
- Add the widget to the application’s dependencies in JSON file;
- Add the necessary configuration for the widget to the application’s JSON file;
- Install the widget using bower install <Widget Name>
- Iterate and test
Checking in Dependencies
In general, we check the entire WAB application project into source control, including the widgets/ directory, and any necessary configuration. This means that changes to a custom widget will be included in the widget’s own repository, as well as the application repository. This allows the default widgets to be included with the app, while also giving us an easy way to update custom widgets using bower.
More advanced workflows
While this workflow is fine for smaller projects (perhaps customizing an existing WAB widget), it does have some limitations:
- It does not handle nested dependencies. We may want to have multiple WAB widgets, that all have a dependency on the same module. In the current workflow, that module would have to be checked-in to each WAB widget repository.
- It does not allow management of non-widget dependencies (i.e., libs/) via bower. Because bower requires all dependencies to be installed to a single directory, we can’t manage both the libs/ and widgets/
- It locks business logic into the WAB. We may have custom functionality that already exists in another application, i.e., custom dojo dijits. Ideally, we would like to develop new WAB widgets in such a way that the underlying logic can be used in other applications. Placing logic directly into the WAB widgets makes this difficult.
Bower itself cannot address these issues, but they can be solved readily by using Grunt, together with some custom node modules. We will cover this workflow in part 2.