Using npm for Custom Builds

Using npm (A package manager for JavaScript) is another option for developers of the JavaScript API to generate custom builds of the ArcGIS API for JavaScript. You would use the npm package of the ArcGIS API for JavaScript if you wanted to create local builds of your application.

Note: See the prerequisites section on configuring your system before proceeding. If your system is already configured with Git, Node.js, and Java you may proceed to the Getting Started section.

Prerequisites

  1. Node.js (includes npm, the node package manager)
  2. git
  3. Java 7 or greater - required by Closure Compiler (Dojo build)

To check if these are installed:

node --version
git --version
java -version

Tip: if you have issues with ssh on your machine, which is common on Windows or due to firewall settings, you can tell git to use https over ssh.

git config --global url."https://github.com".insteadOf git://github.com

Getting Started

We provide a sample application hosted on Github under the npm directory in the jsapi-resources repository for you to get started.

jsapi-resources/4.x/npm/demo
├── Gruntfile.js
├── README.md
├── SASS.md
├── build.profile.js
├── custom-theme-setup.png
├── default-theme.png
├── dojoconfig.js
├── gulpfile.js
├── makefile
├── package-lock.json
├── package.json
├── skinny-green-latte-theme.png
└── src
    ├── app
    │   ├── main.js
    │   ├── package.js
    │   └── package.json
    ├── built.html
    └── index.html

However, if you prefer to start from scratch you can install the ArcGIS API for JavaScript yourself.

npm install --save arcgis-js-api

You can also clone the jsapi-resources repository (code below) to your local machine or download the repository to your local machine.

git clone https://github.com/Esri/jsapi-resources.git

Now that your system is configured, it is time to make a decision on whether you are going to use the Dojo Toolkit or Webpack for your custom build. The Dojo Toolkit build system uses the Closure Compiler and requires Java 7 or greater. If you are going to use webpack, you should probably read the Using webpack guide topic.

Understanding npm

You get npm when you install Node.js. It is package manager for JavaScript. In the provided npm sample, you are given you are given some npm scripts in the package.json as shortcuts for your development environment.

Note: If you are new to node and are unfamiliar or need a refresher on what is contained in a package.json file, please refer to the documentation.

Your package.json will look something like this.

{
  "name": "arcgis-js-api-sample-app",
  "version": "1.0.0",
  ...
  "dependencies": {
    "arcgis-js-api": "^4.8.1"
  }
}

In the Generate a custom build (Dojo), you will be asked to issue a command npm install. When npm install is invoked, it will install version 4.9 of the ArcGIS API for JavaScript locally, as well as any dependencies and/or devDependencies listed in the package.json file. See the package.json file in the dojo sample for more information.

All npm dependencies are downloaded to a folder called node_modules. Notice how we have a dependency for arcgis-js-api. This dependency will download the current version of the ArcGIS JS API package and its own predefined dependencies. You can see a list of the dependencies in the README for the package.

When everything is downloaded, you should have a similar folder structure. Now you have full access to the ArcGIS API for JavaScript and its dependencies.

node_modules
├── @dojo
├── arcgis-js-api
├── cldrjs
├── dgrid
├── dijit
├── dojo
├── dojo-dstore
├── dojo-util
├── dojox
├── globalize
├── intersection-observer
├── maquette
├── maquette-css-transitions
├── maquette-jsx
├── moment
├── pepjs
├── tslib
└── web-animations-js

When you develop your application, you can set up your dojoConfig to point to these folders.

// create or use existing global dojoConfig
var dojoConfig = this.dojoConfig || {};

(function() {
  var config = dojoConfig;

  // set default properties
  if (!config.hasOwnProperty("async")) {
    config.async = true;
  }

  // add packages for libs that are not siblings to dojo
  (function() {
    var packages = config.packages || [];

    function addPkgIfNotPresent(newPackage) {
      for (var i = 0; i < packages.length; i++) {
        var pkg = packages[i];
        if (pkg.name === newPackage.name) {
          return;
        }
      }

      packages.push(newPackage);
    }
    addPkgIfNotPresent({
      name: "app",
      location: "./../../src/app"
    });
    addPkgIfNotPresent({
      name: "esri",
      location: "../arcgis-js-api"
    });
    addPkgIfNotPresent({
      name: "@dojo",
      location: "../@dojo"
    });
    addPkgIfNotPresent({
      name: "cldrjs",
      location: "../cldrjs",
      main: "dist/cldr"
    });
    addPkgIfNotPresent({
      name: "globalize",
      location: "../globalize",
      main: "dist/globalize"
    });
    addPkgIfNotPresent({
      name: "maquette",
      location: "../maquette",
      main: "dist/maquette.umd"
    });
    addPkgIfNotPresent({
      name: "maquette-css-transitions",
      location: "../maquette-css-transitions",
      main: "dist/maquette-css-transitions.umd"
    });
    addPkgIfNotPresent({
      name: "maquette-jsx",
      location: "../maquette-jsx",
      main: "dist/maquette-jsx.umd"
    });
    addPkgIfNotPresent({
      name: "tslib",
      location: "../tslib",
      main: "tslib"
    });

    config.packages = packages;
  })();

  // configure map.globalize
  var map = config.map || {};
  if (!map.globalize) {
    map.globalize = {
      "cldr": "cldrjs/dist/cldr",
      "cldr/event": "cldrjs/dist/cldr/event",
      "cldr/supplemental": "cldrjs/dist/cldr/supplemental",
      "cldr/unresolved": "cldrjs/dist/cldr/unresolved"
    };
    config.map = map;
  }
})();

The scripts field in the package.json file is used to issue commands to build your application..

{
  ...
  "scripts": {
    "build": "grunt build",
    "clean": "grunt clean",
    "styles": "grunt styles --force"
  }
  ...
}

The npm install sequence is where Grunt and the supporting plugins grunt-contrib-clean and grunt-contrib-copy are installed. The npm run clean sequence will remove the built files from the dist directory, and the npm run build command will run the Dojo build on the sample application. If you are interested in building the Sass files included in the npm release of the API, or creating a custom theme based upon one of the existing themes, please refer to this document.

Generate a custom build (Dojo)

For both options (clone or download), you need to copy the source files from https://github.com/Esri/jsapi-resources/tree/master/4.x/npm/demo to a new directory. In the following steps, we'll name the new directory esrijs-npm-dojo.

The contents of your directory should appear as follows:

esrijs-npm-dojo
├── Gruntfile.js
├── README.md
├── SASS.md
├── build.profile.js
├── custom-theme-setup.png
├── default-theme.png
├── dojoconfig.js
├── gulpfile.js
├── makefile
├── package-lock.json
├── package.json
├── skinny-green-latte-theme.png
└── src
    ├── app
    │   ├── main.js
    │   ├── package.js
    │   └── package.json
    ├── built.html
    └── index.html
  1. Open a terminal window or shell command window
  2. Change directory to esrijs-npm-dojo
    • In the terminal window run: npm install
    • The first time this is run it may take a while
    • The arcgis-js-api and other dependencies will be downloaded by npm
    • Subsequent times when npm runs, the arcgis-js-api repository will be cached by npm and take less time to download
    • dependencies and/or devDependencies will download via npm (Grunt plugins including grunt-dojo)
  3. In the terminal window type npm run build and press return
  4. The command will run the dojo build system against the ArcGIS API for JavaScript library and your application
  5. Note: (This will delete the built application!). In the terminal window type npm run clean and press return to delete the built application

Dojo technical details

The Dojo build system accepts a build configuration profile. A sample build profile is available in the npm dojo sample in the jsapi-resources repository on GitHub. The key is to define your build packages, which you can learn more about in this AMD loader tutorial. In addition to packages, you should understand what a layer file is, which is essentially a single file that is composed of many modules and their dependencies.

layers: {
  'dojo/dojo': {
    include: [
      'app/main', // Your application entry point
      'esri/widgets/Attribution' // a dynamically loaded module
    ]
  }
}

This tells the Dojo build system to build the dojo/dojo.js file and to include other files into it. This will become the entry point for your application. This will get you an optimized single-file that you can use to deploy your application. Please see the sample build profile for more details.