# esri-loader
[](https://travis-ci.org/Esri/esri-loader/builds/) [](https://github.com/Esri/esri-loader/releases) [](https://www.npmjs.com/package/esri-loader) [](https://github.com/Esri/esri-loader/blob/master/LICENSE) [](https://github.com/Esri/esri-loader/stargazers)
A tiny library to help you use the [ArcGIS API for JavaScript](https://developers.arcgis.com/javascript/) in applications built with popular JavaScript frameworks and bundlers.

Ready to jump in? Follow the [Install](#install) and [Usage](#usage) instructions below to get started. Then see more in depth instructions on how to [configure esri-loader](#configuring-esri-loader) and use it with [React](#react), [Vue.js](#vuejs), [Angular](#angular), [Ember](#ember), or the [ArcGIS Types](#arcgis-types).
Want to learn more? Read below about [why this library is needed](#why-is-this-needed) and how it can help [improve application load performance](#lazy-loading-the-arcgis-api-for-javascript) and allow you to [use the ArcGIS API in server side rendered applications](#server-side-rendering).
Want to be inspired? See the [Examples](#examples) section below for links to applications that use this library in over a dozen different frameworks.
## Table of Contents
- [Install](#install)
- [Usage](#usage)
- [Loading Modules from the ArcGIS API for JavaScript](#loading-modules-from-the-arcgis-api-for-javascript)
- [Lazy Loading the ArcGIS API for JavaScript](#lazy-loading-the-arcgis-api-for-javascript)
- [Loading Styles](#loading-styles)
- [Why is this needed?](#why-is-this-needed)
- [Examples](#examples)
- [Angular](#angular)
- [Ember](#ember)
- [React](#react)
- [Vue.js](#vuejs)
- [Advanced Usage](#advanced-usage)
- [ArcGIS Types](#arcgis-types)
- [Configuring esri-loader](#configuring-esri-loader)
- [Configuring Dojo](#configuring-dojo)
- [Overriding ArcGIS Styles](#overriding-arcgis-styles)
- [Pre-loading the ArcGIS API for JavaScript](#pre-loading-the-arcgis-api-for-javascript)
- [Using your own script tag](#using-your-own-script-tag)
- [Without a module bundler](#without-a-module-bundler)
- [Using a module script tag](#using-a-module-script-tag)
- [Using the esriLoader Global](#using-the-esriloader-global)
- [Pro Tips](#pro-tips)
- [Using Classes Synchronously](#using-classes-synchronously)
- [Server Side Rendering](#server-side-rendering)
- [FAQs](#faqs)
- [Updating from previous versions](#updating-from-previous-versions)
- [From < v1.5](#from--v15)
- [From angular-esri-loader](#from-angular-esri-loader)
- [Dependencies](#dependencies)
- [Browsers](#browsers)
- [Promises](#promises)
- [Issues](#issues)
- [Contributing](#contributing)
- [Licensing](#licensing)
## Install
```bash
npm install --save esri-loader
```
or
```bash
yarn add esri-loader
```
## Usage
The code snippets below show how to load the ArcGIS API and its modules and then use them to create a map. Where you would place similar code in your application will depend on which application framework you are using. See below for examples that are specific to [React](#react), [Vue.js](#vuejs), [Angular](#angular), [Ember](#ember), and [example applications](#examples) written in over a dozen frameworks.
### Loading Modules from the ArcGIS API for JavaScript
#### From the Latest Version
Here's an example of how you could load and use the `WebMap` and `MapView` classes from the latest 4.x release to create a map (based on [this sample](https://developers.arcgis.com/javascript/latest/sample-code/sandbox/index.html?sample=webmap-basic)):
```js
import { loadModules } from 'esri-loader';
// this will lazy load the ArcGIS API
// and then use Dojo's loader to require the classes
loadModules(['esri/views/MapView', 'esri/WebMap'])
.then(([MapView, WebMap]) => {
// then we load a web map from an id
var webmap = new WebMap({
portalItem: { // autocasts as new PortalItem()
id: 'f2e9b762544945f390ca4ac3671cfa72'
}
});
// and we show that map in a container w/ id #viewDiv
var view = new MapView({
map: webmap,
container: 'viewDiv'
});
})
.catch(err => {
// handle any errors
console.error(err);
});
```
#### From a Specific Version
By default esri-loader will load modules from the [latest 4.x release of the API from the CDN](https://developers.arcgis.com/javascript/latest/guide/get-api/#cdn), but you can [configure the default behavior](#configuring-esri-loader) by calling `setDefaultOptions()` once _before_ making any calls to `loadModules()`.
For example, the snippet below configures esri-loader to use the [latest 3.x release of the API from the CDN](https://developers.arcgis.com/javascript/3/jshelp/intro_accessapi.html#cdn) by setting the default `version` option during application start up.
```js
// app.js
import { setDefaultOptions } from 'esri-loader';
// configure esri-loader to use version 3.34 from the ArcGIS CDN
// NOTE: make sure this is called once before any calls to loadModules()
setDefaultOptions({ version: '3.34' })
```
Then later, for example after a map component has mounted, you would use `loadModules()` as normal, except in this case you'd be using the [3.x `Map` class](https://developers.arcgis.com/javascript/3/jsapi/map-amd.html) instead of the 4.x classes.
```js
// component.js
import { loadModules } from 'esri-loader';
// this will lazy load the ArcGIS API
// and then use Dojo's loader to require the map class
loadModules(['esri/map'])
.then(([Map]) => {
// create map with the given options at a DOM node w/ id 'mapNode'
let map = new Map('mapNode', {
center: [-118, 34.5],
zoom: 8,
basemap: 'dark-gray'
});
})
.catch(err => {
// handle any script or module loading errors
console.error(err);
});
```
You can load the ["next" version of the ArcGIS API](https://github.com/Esri/feedback-js-api-next#esri-loader) by passing `version: 'next'`.
#### From a Specific URL
If you want to load modules from a build that you host on your own server (i.e. that you've [downloaded](https://developers.arcgis.com/javascript/latest/guide/get-api/#download-api) or [built with Dojo](https://developers.arcgis.com/javascript/latest/guide/using-npm/)), you would set the default `url` option instead:
```js
// app.js
import { setDefaultOptions } from 'esri-loader';
// configure esri-loader to use version from a locally hosted build of the API
// NOTE: make sure this is called once before any calls to loadModules()
setDefaultOptions({ url: `http://server/path/to/esri` });
```
See [Configuring esri-loader](#configuring-esri-loader) for all available configuration options.
### Lazy Loading the ArcGIS API for JavaScript
Lazy loading the ArcGIS API can dramatically improve the initial load performance of your mapping application, especially if your users may never end up visiting any routes that need to show a map or 3D scene. That is why it is the default behavior of esri-loader. In the above snippets, the first time `loadModules()` is called, it will lazy load the ArcGIS API by injecting a `
```
### Without a module bundler
Typically you would [install the esri-loader package](#install) and then use a module loader/bundler to `import` the functions you need as part of your application's build. However, ES5 builds of esri-loader are also distributed on [UNPKG](https://unpkg.com/) both as ES modules and as a [UMD](http://jargon.js.org/_glossary/UMD.md) bundle that exposes the `esriLoader` global.
This is an _excellent_ way to prototype how you will use the ArcGIS API for JavaScript, or to isolate any problems that you are having with the API. Before we can help you with any issue related to the behavior of a map, scene, or widgets, we will **require** you to reproduce it _outside_ your application. A great place to start is one of the codepens linked below.
#### Using a module script tag
You can load the esri-loader [ES modules directly in modern browsers](https://caniuse.com/#feat=es6-module) using `
```
You can fork [this codepen](https://codepen.io/gavinr/pen/wvavjwp) to try this out yourself.
A disadvantage of this approach is that the ES module build of esri-loader is not bundled. This means your browser will make multiple requests for a few (tiny) JS files, which may not be suitable for a production application.
#### Using the esriLoader Global
If you need to run the script in an older browser, you can load the UMD build and then use the `esriLoader` global.
```html
```
You can fork [this codepen](https://codepen.io/tomwayson/pen/PoqwZYm) to try this out yourself.
## Pro Tips
### Using Classes Synchronously
Let's say you need to create a map in one component, and then later in another component add a graphic to that map. Unlike creating a map, creating a graphic and adding it to a map is ordinarily a synchronous operation, so it can be inconvenient to have to wait for `loadModules()` just to load the `Graphic` class. One way to handle this is have the function that creates the map _also_ load the `Graphic` class before its needed. You can then hold onto that class for later use to be exposed by a function like `addGraphicToMap(view, graphicJson)`:
```javascript
// utils/map.js
import { loadModules } from 'esri-loader';
// NOTE: module, not global scope
let _Graphic;
// this will be called by the map component
export function loadMap(element, mapOptions) {
return loadModules(['esri/Map', 'esri/views/MapView', 'esri/Graphic'])
.then(([Map, MapView, Graphic]) => {
// hold onto the graphic class for later use
_Graphic = Graphic;
// create the Map
const map = new Map(mapOptions);
// return a view showing the map at the element
return new MapView({
map,
container: element
});
});
}
// this will be called by the component that needs to add the graphic to the map
export function addGraphicToMap(view, graphicJson) {
// make sure that the graphic class has already been loaded
if (!_Graphic) {
throw new Error('You must load a map before creating new graphics');
}
view.graphics.add(new _Graphic(graphicJson));
}
```
You can [see this pattern in use in a real-world application](https://github.com/tomwayson/create-arcgis-app/blob/master/src/utils/map.js).
See [#124 (comment)](https://github.com/Esri/esri-loader/issues/124#issuecomment-408482410) and [#71 (comment)](https://github.com/Esri/esri-loader/issues/71#issuecomment-381356848) for more background on this pattern.
### Server Side Rendering
This library also allows you to use the ArcGIS API in [applications that are rendered on the server](https://medium.com/@baphemot/whats-server-side-rendering-and-do-i-need-it-cb42dc059b38). There's really no difference in how you invoke the functions exposed by this library, however you should avoid trying to call them from any code that runs on the server. The easiest way to do this is to call `loadModules()` in component lifecyle hooks that are only invoked in a browser, for example, React's [useEffect](https://reactjs.org/docs/hooks-effect.html) or [componentDidMount](https://reactjs.org/docs/react-component.html#componentdidmount), or Vue's [mounted](https://vuejs.org/v2/api/#mounted).
Alternatively, you could use checks like the following to prevent calling esri-loader functions on the server:
```js
import { loadCss } from 'esri-loader';
if (typeof window !== 'undefined') {
// this is running in a browser, so go ahead and load the CSS
loadCss();
}
```
See [next-arcgis-app](https://github.com/tomwayson/next-arcgis-app/) or [esri-loader-react-starter-kit](https://github.com/tomwayson/esri-loader-react-starter-kit/) for examples of how to use esri-loader in server side rendered (SSR) applications.
### FAQs
In addition to the pro tips above, you might want to check out some [frequently asked questions](https://github.com/Esri/esri-loader/issues?utf8=%E2%9C%93&q=label%3AFAQ+sort%3Aupdated-desc).
## Updating from previous versions
### From < v1.5
If you have an application using a version that is less than v1.5, [this commit](https://github.com/odoe/vue-jsapi4/pull/1/commits/4cb6413c0ea31fdd09e94f3a0ce0d1669a9fd5ad) shows the kinds of changes you'll need to make. In most cases, you should be able to replace a series of calls to `isLoaded()`, `bootstrap()`, and `dojoRequire()` with a single call to `loadModules()`.
### From angular-esri-loader
The angular-esri-loader wrapper library is no longer needed and has been deprecated in favor of using esri-loader directly. See [this issue](https://github.com/Esri/esri-loader/issues/75) for suggestions on how to replace angular-esri-loader with the latest version of esri-loader.
## Dependencies
### Browsers
This library doesn't have any external dependencies, but the functions it exposes to load the ArcGIS API and its modules expect to be run in a browser. This library officially supports [the same browsers that are supported by the latest version of the ArcGIS API for JavaScript](https://developers.arcgis.com/javascript/latest/guide/system-requirements/index.html#supported-browsers). Since this library also works with [v3.x of the ArcGIS API](https://developers.arcgis.com/javascript/3/), the community [has made some effort](https://github.com/Esri/esri-loader/pull/67) to get it to work with [some of the older browsers supported by 3.x](https://developers.arcgis.com/javascript/3/jshelp/supported_browsers.html) like IE < 11.
You cannot run the ArcGIS API for JavaScript in [Node.js](https://nodejs.org/), but you _can_ use this library in [server side rendered applications](#server-side-rendering) as well as [Electron](#electron). If you need to execute requests to ArcGIS REST services from something like a Node.js CLI application, see [arcgis-rest-js](https://github.com/Esri/arcgis-rest-js).
### Promises
Since v1.5 asynchronous functions like `loadModules()` and `loadScript()` return [`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)s, so if your application has to support [browsers that don't support Promise (i.e. IE)](https://caniuse.com/#search=promise) you have a few options.
If there's already a Promise implementation loaded on the page you can configure esri-loader to use that implementation. For example, in [ember-esri-loader](https://github.com/Esri/ember-esri-loader), we configure esri-loader to use the RSVP Promise implementation included with Ember.js.
```js
import { utils } from 'esri-loader';
init () {
this._super(...arguments);
// have esriLoader use Ember's RSVP promise
utils.Promise = Ember.RSVP.Promise;
},
```
Otherwise, you should consider using a [Promise polyfill](https://www.google.com/search?q=promise+polyfill), ideally [only when needed](https://philipwalton.com/articles/loading-polyfills-only-when-needed/).
## Issues
Find a bug or want to request a new feature? Please let us know by [submitting an issue](https://github.com/Esri/esri-loader/issues/).
## Contributing
Esri welcomes contributions from anyone and everyone. Please see our [guidelines for contributing](https://github.com/esri/contributing).
## Licensing
Copyright © 2016-2019 Esri
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
A copy of the license is available in the repository's [LICENSE]( ./LICENSE) file.