npm and ArcGIS API for JavaScript 4.3

7150
16
04-13-2017 01:52 PM
BjornSvensson
Esri Regular Contributor
6 16 7,150

When the 4.0 version of the ArcGIS API for JavaScript was released, we also released a Bower compatible minified version of the API for users interested in doing their own custom local builds. This was a big step in our direction to help users integrate the ArcGIS API for JavaScript into their own workflows.

We have since had numerous requests to publish the ArcGIS API for JavaScript to NPM. One of the reasons we have not done this is that Bower provides us with some advantages when it comes to creating custom local builds. Publishing the API to NPM will not automatically make it compatible with build tools like Webpack. It actually adds a couple of steps to the Dojo build needed to compile the ArcGIS API for JavaScript.

With the upcoming release of 4.4 we will publish the ArcGIS API for JavaScript to NPM. We will also be providing some updated resources about how to do a Dojo build with the API.

Start using NPM today

However, you could start using NPM today to install the ArcGIS API for JavaScript locally.

Let's start with the sample application provided in the resources repo on github.

Take a look at the bower.json file provided with the ArcGIS API for JavaScript repo.

...
  "dependencies": {
    "dojo": "Esri/dojo#v1.12.1/esri-3.20.0",
    "dojox": "Esri/dojox#v1.12.1/esri-3.20.0",
    "dijit": "Esri/dijit#v1.12.1/esri-3.20.0",
    "util": "Esri/dojo-util#v1.12.1/esri-3.20.0",
    "dgrid": "Esri/dgrid#v1.1.0/esri-3.20.0",
    "dstore": "1.1.1",     "moment": "2.17.1"
  },
...

We can borrow most of this for our package.json of our custom application.

...
  "dependencies": {
    "dgrid": "Esri/dgrid#v1.1.0/esri-3.20.0",
    "dijit": "Esri/dijit#v1.12.1/esri-3.20.0",
    "dojo": "Esri/dojo#v1.12.1/esri-3.20.0",
    "dojo-dstore": "^1.1.1",
    "dojo-util": "^1.12.2",
    "dojox": "Esri/dojox#v1.12.1/esri-3.20.0",
    "arcgis-js-api": "Esri/arcgis-js-api#4.3.1",
    "moment": "2.17.1"
  },
...

You can see this looks very similar. Main difference is that util is now dojo-util and dstore is now dojo-dstore, because these are the names of the published packages on NPM. You may also notice that we can bring in the arcgis-js-api repo using Esri/arcgis-js-api#4.3.1. This tells NPM too look on github at the Esri org and install the arcgis-js-api repo using the 4.3.1 release.

At this point you can delete the bower.json and .bowerrc files from the project since they are not going to be used.

One disadvantage of using NPM instead of Bower is that NPM does not allow you to change the name of the folder the package is installed. Meaning that the JavaScript API will installed to node_modules/arcgis-js-api instead of node_modules/esri which would be ideal as far as how we typically use the Dojo build system.

Hint: If you use Yarn instead of NPM, it can install to custom named directories.

Once you NPM install these packages you will have a folder structure that should look something like this.

node_modules/
  arcgis-js-api/
  dgrid/
  dijit/
  dojo/
  dojo-dstore/
  dojo-util/
  dojox/
src/
  app/
    main.js

Now you need to tell Dojo where to locate the packages. You can do this by supplying a global dojoConfig object.

<!-- index.html -->
    <script>
      // point to node_modules folder
      window.dojoConfig = {
        baseUrl: '../node_modules/',
        packages: [
          'dijit',
          'dojo',
          'dojox',
          'dgrid',
          'moment',
          {
            name: 'app',
            location: '../src/app'
          },
          // alias for dstore package
          {
            name: 'dstore',
            location: 'dojo-dstore'
          },
          // alias for esri package
          {
            name: 'esri',
            location: 'arcgis-js-api'
          }
        ]
      };
    </script>
    <script src="../node_modules/dojo/dojo.js"></script>
    <script>require(["app/main"]);</script>

There is one more thing you will need to do your own code in order for this to work. The ArcGIS API for JavaScript uses Web Workers for Vector Tiles. You will need to let the workers know where the esri package is located in order for them to function. You can do this in the following manner using esri/config and dojo/has.

//app/main.js
if (!has("dojo-built")) {
  esriConfig.workers.loaderConfig = {
    paths: {
      "esri": "../arcgis-js-api"
    }
  };
}

The reason we use dojo/has is that once the application is built, the Dojo build system will install the esri package into an esri folder and not arcgis-js-api. So we only need this configuration during the development process.

Now you can develop your application using the JavaScript API installed in node_modules.

When you do your Dojo build, you will need to do something similar. However, the Dojo build is expecting the build tools to be located in a folder called util, but they are in fact installed in a folder called dojo-util. This requires you to create a dojoConfig for the build system in the root of your project.

// dojoconfig.js
dojoConfig = {
  baseUrl: './node_modules/',
  packages: [
    {
      name: 'dojo',
      location: 'dojo'
    },
    {
      name: 'build',
      location: 'dojo-util/build'
    }
  ]
};
require('./node_modules/dojo/dojo.js');

Then to run your Dojo build from the command line you can use node dojoconfig.js load=build --profile build.profile.js --releaseDir ../dist.

This will now tell Dojo where to find the build tools needed.

You will also need to update the build.profile.js to reflect the new locations of the packages.

// build.profile.js
  packages: [
    // "app" is a sample path for your application
    // set this accordingly
    "app",
     {
       name: 'dijit',
       location: '../node_modules/dijit',
       trees: [
           // don"t bother with .hidden, tests, min, src, and templates
          [".", ".", /(\/\.)|(~$)|(test|node_modules)/]
       ]
     },
     {
       name: 'dojo',
       location: '../node_modules/dojo',
       trees: [
           // don"t bother with .hidden, tests, min, src, and templates
          [".", ".", /(\/\.)|(~$)|(test|node_modules)/]
       ]
     },
     {
       name: 'dojox',
       location: '../node_modules/dojox'
     },
     {
       name: 'dstore',
       location: '../node_modules/dojo-dstore',
       trees: [
           // don"t bother with .hidden, tests, min, src, and templates
          [".", ".", /(\/\.)|(~$)|(test|txt|src|min|templates|node_modules)/]
       ]
     },
     {
       name: 'dgrid',
       location: '../node_modules/dgrid',
       trees: [
           // don"t bother with .hidden, tests, min, src, and templates
          [".", ".", /(\/\.)|(~$)|(test|node_modules)/]
       ]
     },
     {
       name: 'esri',
       location: '../node_modules/arcgis-js-api'
    },
     {
       name: "moment",
       location: "../node_modules/moment",
       main: "moment",
       trees: [
           // don"t bother with .hidden, tests, min, src, and templates
          [".", ".", /(\/\.)|(~$)|(test|txt|src|min|templates)/]       ],
       resourceTags: {
         amd: function(filename, mid){
           return /\.js$/.test(filename);
         }
       }
     }
   ],

Notice the addition of the trees array for each package. This lets the Dojo compiler know which files and folders to ignore so it doesn't try to include tests and documentation in the build process.

Summary

So if you are interested in using NPM to install the ArcGIS API for JavaScript locally today, these are the steps you would need to take. All this is still valid once we publish the JavaScript API to NPM, except you will only need to install the arcgis-js-api package by name and not need to install the other dependencies yourself. Bower does provide us with a distinct advantage when it comes naming the folders and locations that packages are installed, but NPM allows to keep all dependency code in a single location.

Please note, that if you want to use RequireJS and the RequireJS Optimizer to build the ArcGIS API for JavaScript, you should continue to use Bower as some of the required build tools cannot be installed via NPM.

Even once the API is published to NPM, we will continue to provide the Bower release for as long as it's sustainable since it's all the same codebase.

Contributed by Rene Rubalcava !

16 Comments
JeffJacobson
Regular Contributor

I happened to be looking at the Bower site today and noticed this message:

...psst! While Bower is maintained, we recommend yarn and webpack for new front-end projects!

Also their latest blog entry (from last Oct.) is about using yarn instead of the Bower API.

BjornSvensson
Esri Regular Contributor

Yes, they added that sentence last month. There's more info in the commit https://github.com/bower/bower.github.io/commit/12566e5b777ef4c93c525cf3d2fa35ebc9f4d2e5, including a link to https://advancedweb.hu/2016/12/21/bower/ which discusses some use cases for when Bower might be preferred to npm.

EvelynHernandez
Regular Contributor

I have a question. Why not let webpack handle the arcgis api?
Some time ago i made a package.json and webpack.config.js with some help of some guys here ( @lobsteropteryx and @tomwayson) to run the api without any kind of problem (No extra code, no extra configuration, just KEEP IT SIMPLE).  
Right now i have learned a lot of new things, and i changed the code for webpack 2 (Nowadays is wp 3). Right now I can handle everything using import, like: 

import Map from 'esri/map';‍‍‍

(I let webpack compile as amd the whole app). So later, in the html i just import and make a file like this:

<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>My App</title>
    <meta name="description" content="ReactJS - Arcgis JS API - Webpack 2.">
    <meta name="author" content="Evelyn Hernández">
    <meta name="viewport" content="initial-scale=1.0,user-scalable=no,maximum-scale=1,width=device-width">
    <meta name="viewport" content="initial-scale=1.0,user-scalable=no,maximum-scale=1" media="(device-height: 568px)">
    <meta name="apple-mobile-web-app-title" content="Material Console">
    <meta name="apple-mobile-web-app-capable" content="yes">
    <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
    <meta name="format-detection" content="telephone=no">
    <meta name="HandheldFriendly" content="True">
    <meta http-equiv="cleartype" content="on">


    <link rel="stylesheet" type="text/css" href="arcgis_js_api/library/3.17/3.17/dijit/themes/tundra/tundra.css" />
    <link rel="stylesheet" href="arcgis_js_api/library/3.17/3.17//esri/css/esri.css">

    <style>html, body { margin: 0; padding: 0; }</style>

  </head>
  <body class="claro">
    <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
    <link href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700" rel="stylesheet">
    <script src="arcgis_js_api/library/3.17/3.17/init.js"></script>


    <div id="app"></div>
    <script type="text/javascript">require(["bundle.js"], function (bundle) {});</script>

  </body>
 
</html>
‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

The ArcGIS API files i have them in the root directory of my app with the name of arcgis_js_api that comes always inside the .zip from the download. I just modify the dojo.js and init.js HOSTNAME URL to = localhost:443 (cuz in the readme from the api, it says that only work in 2 ports).

For those who use Webpack Dev Server and Webpack, my webpack.config,js (for webpack 2) and package.json with some utilities that i have found that are super good for developing apps with Arcgis for JS u can find them in this link: Package & WP 2 Config. · GitHub 

I hope this helps! 

ReneRubalcava
Frequent Contributor

There's some technical limitations that prevent us from fully using Webpack for building the API. You can get almost there, but not single-file builds. We're looking at how far we can push it, and if we can overcome the technical hurdles, believe me, I'll be the first to talk about it.

ZakiEldsoque1
New Contributor

please i want sample how to use it in node.js ?? 

AdebayoYusuf_Ishola
New Contributor II

Hi Zaki Eldsoque,

Kindly refer to the snippet @svensson had at the top.

"dependencies":

{ "dgrid": "Esri/dgrid#v1.1.0/esri-3.20.0",

"dijit": "Esri/dijit#v1.12.1/esri-3.20.0",

"dojo": "Esri/dojo#v1.12.1/esri-3.20.0",

"dojo-dstore": "^1.1.1",

"dojo-util": "^1.12.2",

"dojox": "Esri/dojox#v1.12.1/esri-3.20.0",

"arcgis-js-api": "Esri/arcgis-js-api#4.3.1",

"moment": "2.17.1"

},

 

If you add the above to package.json, which contains your development dependencies, run (sudo) npm install to get everything installed.

PS: I haven't tried it.

I hope this helps!

JohnRood
New Contributor

Any rumors on whether v4.4 is still going to be published to npm?

ReneRubalcava
Frequent Contributor

Sorry, took longer than expected to do some build testing. It's up now.

arcgis-js-api 

JohnRood
New Contributor

Woah, awesome thanks!

EvelynHernandez
Regular Contributor

is that compatible with webpack?, i dont use bower, i use npm+webpack 😞

ReneRubalcava
Frequent Contributor

Not at the moment.

TomWayson
Esri Contributor

Until it's possible to build the ArcGIS API for JavaScript with another module loader/bundler like webpack you can always use esri-loader.

JohnRood
New Contributor

I feel ya. I'm holding out hope that someday the ArcGIS JS API will break free from the dojo and take up residence in some es2015 modules! (...a man can dream)

TomWayson
Esri Contributor
EvelynHernandez
Regular Contributor

It is still little bit harder to implement as the way we found with some people here long time ago.

TomWayson
Esri Contributor

I agree that the new plugin is harder to configure than the above solution, but once you do get it working, at least you have the option of being able to achieve acceptable load performance on mobile. Here's more information on that: https://community.esri.com/people/TWayson-esristaff/blog/2018/05/10/arcgiswebpack-plugin-vs-esri-loa...