The esri-loader library hit the 2.0.0 milestone this week. This release doesn’t add any features, but merely removes the old callback APIs that were deprecated when we introduced the promise-based ones in v1.5.0. If you’ve been using the new APIs, you can save yourself a few bytes by upgrading to 2.0.0. You can read more in the 2.0.0 release notes.
One does not simply load modules from the ArcGIS API
If your ArcGIS web application uses any other module loader besides the Dojo loader (i.e. webpack, Rollup.js, etc.), you should be using esri-loader.
That’s a bold statement, so let me back it up.
The two patterns
A little over a year ago, I published a blog post that described two general patterns for working around the limitation that the only reliable way to load ArcGIS API modules is to use the Dojo loader. I called these patterns “dedicated loader module” and “exclude and require” and presented them as equals, each with its own benefits and challenges. This was right after the initial release of esri-loader, and I referenced esri-loader as an implementation of the “dedicated loader module” pattern.
One library to load them all
It’s now clear that the benefits of the “dedicated loader module” pattern outweigh those of the “exclude and require” pattern. Here are a few things that you can only do if you’re using a library like esri-loader:
- Improve initial load performance by lazy loading or pre-loading the ArcGIS API
- Use the ArcGIS API in isomorphic/universal (server-rendered) applications
- Use the ArcGIS API with whatever cli or boilerplate your team prefers
- Avoid having to load the ArcGIS API just to run your unit tests
It’s also become clear that with nearly 100 stars on GitHub, and ~1,000 downloads a week, esri-loader has emerged as the de facto implementation of the “dedicated loader module” pattern. There are over a dozen open source reusable libraries and example applications that show how to use esri-loader in 7 different frameworks.
Not just for webpack
The above blog post presented these two patterns specifically as workarounds for webpack, but benefits of using esri-loader hold true regardless of which module loader you’re using. Below are a few special considerations for each module loader.
I’ve already listed above the benefits of using esri-loader rather than the “exclude and require” pattern in applications bundled with webpack. For these reasons, I have deprecated my example repository showing how to use the “exclude and require” pattern with webpack.
There have been multiple efforts to get webpack to actually load and bundle Dojo modules, but I’m not sure that would be better than using esri-loader. The latest such effort is dojo-webpack-plugin and to my knowledge, no one has successfully used it with the ArcGIS API… yet. Unlike previous efforts, the OpenNTF team have put a lot of work into that plugin to try and achieve some level of parity with the Dojo loader, so it might actually work with the ArcGIS API. So why haven’t we heard about anyone getting this working? Maybe it’s not all that it’s cracked up to be. For one thing, it’s going to slow development build times. Also, I wonder if you’ll be able to produce a build that’s any smaller than a Dojo build, or if/how it works with newer webpack features like code splitting and dynamic
import(). Even if someone ends up figuring all that out, this might not make sense for smaller applications, or those that have limited mapping needs. Until then, I’d say stick with esri-loader.
The benefits listed above apply equally in applications bundled with rollup.js. I have also deprecated my example repository showing how to use the “exclude and require” pattern with rollup.js.
SystemJS is the one module loader that you could make a case for using another library, specifically systemjs-plugin-dojo, instead of esri-loader. That will work during development to load modules from individual files, but I’m unclear what will happen during production builds. I would guess that for production builds you’d need to fall back to using the “exclude and require” pattern, and how you would do that would depend on what bundler/build tool you use. Does JSPM support external modules?
If you don’t want to figure that out, I suggest just using esri-loader in your SystemJS applications.
Ember has to be special, so has it’s own module loader. So there’s a special Ember addon that wraps esri-loader called ember-esri-loader, and it will let you enjoy the above benefits in your Ember application. Well, all the benefits except one. Ember also has it’s own special flavor of universal application called FastBoot, and we’re still working on getting that to work with the ArcGIS API. You can track the progress here.
Parcel and whatever comes next
Parcel is a new bundler similar to webpack, but it promises zero configuration. While I haven’t yet tried to get esri-loader to work in a parcel app, I’m sure it will. More importantly, I’m pretty sure that the “exclude and require” pattern will not currently work in parcel. Follow this issue for details and updates.
Basically I’m confident that you could use esri-loader with any module loader. I haven’t tried it yet, but I’m pretty sure esri-loader would even work work in
When would you not use esri-loader?
Obviously there’s no need to use esri-loader in a Dojo application that doesn’t use a module loader like any of the above. This approach makes the most sense for map-centric applications where a map (or a 3D scene) is the focus of the user experience and the source of most of the application state. Rene Rubalcava created a yeoman generator to scaffold this type of application.
This type of map-centric Dojo application can also use components from other frameworks, even without bringing in that framework’s module loader of choice. This is because other frameworks are usually distributed as UMD modules, which can be loaded by Dojo loader. The Using Frameworks guide page discusses this approach further and includes links to a few samples including ones that use React and Vue.js components.
But we must have our precious
It’s true that you can’t
import ArcGIS modules when using esri-loader, but this is not necessarily a bad thing. I’ll admit that it is very convenient to be able to write something like
import Map from 'esri/Map'. Maybe too convenient. If you use the “exclude and require” method, then there’s nothing stopping you from sprinkling statements like that throughout your app. Conversely, by forcing you to wrap all interaction with the ArcGIS API in asynchronous calls to
loadModules(), esri-loader encourages you to think about how and when you use the ArcGIS API. You will find yourself naturally gravitating toward best practices like pushing your dependency on the ArcGIS API to the edge of your application and only using it for exactly what you need it for like maps and 3D scenes. This will make it easy to replace calls to
import statements in your applications once esri-loader is no longer needed,
import ArcGIS modules using other module loaders. Ideally the ArcGIS API would then be distributed as ES modules to enable other module loaders to tree-shake application builds. I don’t know what the timeline is for that work, but even once it’s done someone will need to start using those ES modules with loaders like webpack to figure out if you can use techniques like code splitting and dynamic
import() to achieve the same lazy loading benefit that you get with esri-loader today.