Using Esri in Single Page Application frameworks

Prepared by MSc. İbrahim ULUDAĞ (ibrahim.uludag@turkcell.com.tr) and Dr. Alp Asutay

Durandal is a modern cross-device, asynchronous cross-platform client framework written in JavaScript and designed to make Single Page Applications (SPAs) easy to create and maintain. This framework is built on latest technology libraries and web components including jQuery, Knockout and RequireJS as AMD loader.

Esri's ArcGIS API is a geographic information system (GIS) for working with maps and geographic information. It is used for: Creating and Using Maps;
Compiling geographic data; analyzing mapped information; sharing and discovering geographic information; using maps and geographic information in a range of applications; and managing geographic information in a database. ArcGIS API uses Dojo as AMD Loader.

Since they use different AMD loaders, using them together is not trivial. Esri states that the ArcGIS API can be only used with Dojo. Durandal suggests to replace RequireJS with Dojo but it is not desired to change one of the core library of Durandal. There is a workaround to use ArcGIS API in Durandal without replacing RequireJS. But there are some issues of this
technique.

  1. You cannot use CDN. The files must be placed in the project.
  2. Some effort and much care is required when going to production

The versions of RequireJS and ArcGIS API is important. This technique may not work for older versions. The minimum required version of RequireJS is 2.1.16, and 3.12 for ArcGIS API.

Here are the steps:

Download ArcGIS API 3.12 from ArcGIS web site.

Extract and copy the files into your project. For example you can place ArGIS file bulk into Scripts folder.

Add ArcGIS css to html page. It can be used either from CDN or local.

<link href="https://blogs.msdn.com//js.arcgis.com/3.12/dijit/themes/claro/claro.css" ... />            
<link rel="stylesheet" href="https://blogs.msdn.com//js.arcgis.com/3.12/esri/css/esri.css" />

Configure RequireJS paths for dojo, dijit, dojox and esri

requirejs.config({
paths: {
'text': '../Scripts/text',
'durandal': '../Scripts/durandal',
'plugins': '../Scripts/durandal/plugins',
'transitions': '../Scripts/durandal/transitions'
'dojo': '../Scripts/arcgis_js_v312_api/arcgis_js_api/library/3.12/3.12/dojo',
'dijit': '../Scripts/arcgis_js_v312_api/arcgis_js_api/library/3.12/3.12/dijit',
'dojox': '../Scripts/arcgis_js_v312_api/arcgis_js_api/library/3.12/3.12/dojox',
'esri': '../Scripts/arcgis_js_v312_api/arcgis_js_api/library/3.12/3.12/esri'
}
});

For production, Grunt is used. Add the paths as empty in the Gruntfile.js.

var requireConfig = {
      baseUrl: 'app/',
      paths: {
         "jquery": 'empty:',
         "knockout": 'empty:',
         'bootstrap': 'empty:',
         'text': '../Scripts/text',
         'durandal': '../Scripts/durandal',
         'plugins': '../Scripts/durandal/plugins',
         'transitions': '../Scripts/durandal/transitions',
         'dojo': 'empty:',
         "dijit": "empty:",
         "dojox": "empty:",
         "esri": "empty:",
      },
      catchError: true
};

Remove custom-almond in your main file by adding almondFilter and add to tasks. (Configure src and dest according to your configuration), require.js file will be added later for release mode.

replace: {
  almondFilter: {
  src: ['build/main.js'],
   dest: 'build/mainalmondFilter.js',
   replacements: [{
     from: /var requirejs, require, define;(.|[rn])*define("../Scripts/almond-custom", function(){});/g,
     to: ''
  }] } },

 grunt.registerTask('default', [
       ....
       'durandal:main',
       'replace:almondFilter'
  ]);

After following these steps, ArcGIS API can be used in Durandal SPA projects. But there are still steps before going to production and it is important to follow below steps for each release. Because ArcGIS API makes approximately 200 HTTP requests and this affects the performance of the application. These requests must be combined into one file.

Generating production from ArcGIS web site causes problems. Because it adds dojo to script. Since RequireJS is used as AMD Loader, they conflict with each other. The production code will be generated manually. The step are as below:

  1. Open Fiddler. Navigate to all your map pages and consume every action you have implemented. For example, if you have written onlick event, make sure you trigger it. The reason is to load all AMD modules.
  2. In fiddler, sort by name url. Select all URLs in the ArcGIS folder. Export by File > Export Sessions > Selected Sessions > Raw.
  3. Merge all the content of the exported files into one file. Copy the merged file into project. (e.g. ~/Scripts/all-arcgis.js). You can use MergeFileContents.zip for merging.
  4. Make the appropriate change in your cshtml file.

 

@if (HttpContext.Current.IsDebuggingEnabled)
{
     <script type="text/javascript" src="~/Scripts/require.js" data-main="/App/main"></script>
}
else
{
     <script type="text/javascript" src="~/Scripts/require.js"></script>
     <script type="text/javascript" src="~/main-built.js"></script>
     <script type="text/javascript" src="~/Scripts/all-arcgis.js"></script>
  }