odoe

EsriJS App Structure Opinions

Blog Post created by odoe on Aug 26, 2015

esrijs-structure.jpg

Every now and then, someone will ask me about how they should structure their ArcGIS JS API app. In my book, I recommend the following app structure:

 

app/

   |-- css/

   |-- js/

         |-- controllers/

         |-- services/

         |-- utils/

         |-- widgets/

         |-- main.js

         |-- run.js

   |-- index.html

 

I've used this app structure for a lot of projects and it's worked fine. Typically my run.js looked like this:

(function() {
  'use strict';
  var pathRX = new RegExp(/\/[^\/]+$/)
  , locationPath = location.pathname.replace(pathRX, '');
  require({
  packages: [{
  name: 'controllers',
  location: locationPath + 'js/controllers'
  }, {
  name: 'widgets',
  location: locationPath + 'js/widgets'
  }, {
  name: 'utils',
  location: locationPath + 'js/utils'
  }, {
  name: 'services',
  location: locationPath + 'js/services'
  }, {
  name: 'app',
  location: locationPath + 'js',
  main: 'main'
  }]
  }, ['app']);
})();

 

This works out pretty nice. But one thing it doesn't take into consideration is treating the app and all submodules as an app package. This is more concerned with treating my modules as packages when using the CDN. What's the difference? Glad you asked!

 

Let's say you want to build your application. Maybe you're going to utilize the ArcGIS optimizer or esri-slurp, which has a great example here by the way. You're going to want to treat your application as it's own package. What do I mean by that? Well, let's take a look at how you use the ArcGIS JS API.

 

require(['esri/map', 'dojo/declare'], function(Map, declare) {/*cool stuff*/});

 

In this case, esri is a package and dojo is a package.  There are other packages included in the API, such as dgrid, dstore, and diijt. This because when you use the Dojo build system, it knows how to reference the files. So you can naturally bundle your application as it's own package, called app. You can call it Sally if you want, but let's assume app works just fine.

 

So these days, the way I like to structure my app similar to this.

index.html

dojoConfig.js

app/

   |-- styles/

   |-- models/

   |-- services/

   |-- utils/

   |-- widgets/

   |-- main.js

   |-- app.profile.js

    |-- package.json

    |-- config.json

 

Here, I have dojoConfig file that does some basic setup. It could look like this:

var dojoConfig = {
  async: true,
  parseOnLoad: true,
  isDebug: true,
  deps: ['app/main']
  }
};

 

Ok, so this assumes I'm going to use esri-slurp to download the API and use bower to install other dependencies. If I were using this as a CDN, I would add packages property like this:

packages: [{
  name: 'app',
  location: location.pathname.replace(/\/[^\/]+$/, '') + 'app'
}]

 

That's it.

 

Ok, bear with me a second. What is this app.profile.js nonsense? This file defines some resourceTags for our app package. This basically tells the Dojo build system my package is using AMD. A coworker told me about this, I didn't think I needed it, but the Dojo build system nags you if you don't have it. It looks like this:

var profile = (function(){
  return {
    resourceTags: {
      amd: function(filename, mid) {
        return /\.js$/.test(filename);
      }
    }
  };
})();

 

The pacakge.json let's the Dojo build system know where to find the app.profile to use.

{
  "name": "myapp",
  "version": "1.0.0",
  "main": "main",
  "description": "Demo app.",
  "homepage": "",
  "dojoBuild": "app.profile.js"
}

 

The config.json is something that i've been using for years in my ArcGIS JS API apps. It's basically settings or what the map looks like or configurations for widgets. I can use this file or call a web service to get this config data. You can see an example of what that might look like here. The rest of the application is pretty basic. Currently my application structure is heavily inspired by ember-cli as it's something I've been using a lot lately.

 

However, if I'm using React for building my UI, I like to use a more Flux oriented structure.

index.html

dojoConfig.js

app/

   |-- styles/

   |-- stores/

   |-- actions/

   |-- helpers/

   |-- views/

   |-- main.js

   |-- app.profile.js

   |-- package.json

   |-- config.json

 

I would also do the same if I were using Angular, where I'd adopt a structure that uses directives instead of views or components. I'm currently working on a Yeoman generator for ArcGIS JS Apps, which you can see a demo app here. It's still pretty experimental, but could be useful to some.

 

The cmv-app has an interesting app structure using configuration base similar to this starterkit I was working on.

 

They key here, whether you like my advice or not, is pick a structure that works for you. You could have your main.js work as the application controller and just have a widget folder with all your UI stuff. Again, as long as it works for you, you're all set.

 

I'll get to a follow-up blog post that talks about the next step here, which is creating a custom build of your application. That should be fun!

 

For more geodev tips and tricks, check out my blog.

Outcomes