gisdev-km / esri-rollup-example

Example application using Rollup to bundle local ES2015 modules that use CDN hosted modules from the ArcGIS API for JavaScript

Home Page:http://tomwayson.github.io/esri-rollup-example/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Esri Rollup Example

Life's Too $hort to Use Dojo Build TM

TLDR: An example of a fast, flexible, modern way for you to build just your application code locally while using the CDN hosted builds of the ArcGIS API for JavaScript.

This is an example application using Rollup to bundle local ES2015 modules that use CDN hosted modules from the ArcGIS API for JavaScript.

You can view the site created by this repo live, and see the (unminified) bundled source code.

This example application also uses Gulp to minify the bundled code and manage static assets, but you can use Rollup with whatever build system you prefer. Earlier versions of the application simply used npm scripts as a build tool.

Getting started

  1. Clone/download this repository
  2. cd into the repository root folder and run npm install && npm start
  3. Make some changes to the source code and the browser will live reload the newly built code

Why?

Ever waited minutes for a Dojo build only to have it fail? If not, you're doing it wrong. Ever not been able to figure out why it failed? I have. Even when a Dojo build does work, have you ever looked at the size of the optimized output and realize that you saved exactly 0 bytes over the size of the compact build? There's 4 hours of your life you'll never get back. Ever used the Web Optimizer and wonder why part of your build process involves visiting a web site?

If you're like me, you're fed up with all that. It's time we respect ourselves and take back our valuable time. Esri's already done the Dojo builds for us and left them on a CDN. We should be able to pull in any of those and just build our own application code. Now with Rollup, it looks like we can. Even better, we can do so in a fast, flexible, and modern way!

Known benefits

  • ~10 million times faster than a Dojo build - something that can be used with live reload!
  • No need to bower install half the Internet (i.e. all of Dojo and the ArcGIS API for JavaScript)
  • No need for bower at all, use either npm or bower, or both, or neither! I'd rather not know about how you handle other people's packages.
  • No longer dependent on grunt-dojo, so use whatever build system you prefer: Gulp, npm scripts, or Grunt - I ain't mad atcha!
  • Develop and test off your built code
  • Your users' browsers may already have the CDN build of the ArcGIS API for JavaScript cached

Potential benefits

These have not (yet) been tested:

What's the catch?

Too good to be true? There a few known limitations that you should understand. However, there are workarounds that might work for you. They work for me!

Known limitations

  • Any code to be included in the bundle must use ES2015 imports/exports
  • Can't use dojo/text plugin (but you can use Rollup's, or ES2015 template literals)
  • Can't inline i18n bundles, but you can use dojo/i18n!
  • Build output is a single AMD module, not a Dojo build layer, so sub modules are not exposed. This should be fine when building apps, but is probably not suitable for building libraries.

Caveats

How does it work?

This approach relies on default behavior of Rollup to ignore modules that it can't resolve (i.e. anything in the esri or dojo packages) and only bundle our application code into a single AMD module.

$ rollup -c rollup-config.js
Treating 'dojo/_base/declare' as external dependency
Treating 'dijit/_WidgetBase' as external dependency
Treating 'dijit/_TemplatedMixin' as external dependency
Treating 'dojo/_base/declare' as external dependency
Treating 'esri/Map' as external dependency
Treating 'esri/views/MapView' as external dependency
Treating 'esri/layers/FeatureLayer' as external dependency
Treating 'esri/widgets/BasemapToggle' as external dependency
Treating 'esri/widgets/BasemapToggle/BasemapToggleViewModel' as external dependency
Treating 'dojo/_base/declare' as external dependency
Treating 'dijit/_WidgetBase' as external dependency
Treating 'dijit/_TemplatedMixin' as external dependency
Treating 'dojo/i18n!./nls/strings' as external dependency

Rollup's so smart. We didn't even need to tell it to ignore those modules.

We can then use the Dojo loader that is included in the ArcGIS API for JavaScript to load and run the bundled output like so:

// index.html
require(['app/bundle']);

Handling Third Party Dependencies

As with the Dojo build you have a few options for how to handle third party libraries.

ES2015 imports/exports

As stated above, any code to be included in the bundle must use ES2015 imports/exports. If you have a dependency that is written in ES2015, such as lodash-es, you can use import statements from your application modules and Rollup will try include only the code (down to the function level) required by your application, a process called tree shaking.

Globals

If a library exposes a global (such as $, _, d3, etc), you can just use the global in your code (no one will get hurt, I promise). You can load the library on the page by including a script tag pointing to either a CDN or a local file. If using the latter, it is best to first concatenate all local scripts into a single minified file (vendor.js). I find that most of the libraries I use expose a global, and sometimes I'll use those even with a Dojo build (just to reduce the chances of build errors).

AMD

If a library only exposes AMD modules and no global (for example Dojo Bootstrap or dojox.charting), then unfortunately there's no good way to include that library in this build process. You can still use the library in your application by defining a dojoConfig package that points to either the CDN or local path to the library, but the modules will be loaded asynchronously at runtime.

Considering your choices

Tree shaking sounds great on paper, but it is far from perfect. I have it working in this example app, but even just pulling in one function (along w/ all of the code Rollup thought might be needed by that function) the bundle starts to get a little cluttered. You can imagine how cluttered the bundle could get if you have a lot of dependencies. In a real app, I'd probably bring in a custom build of lodash as a global.

Obviously the Dojo build is much better than Rollup at handling AMD-only libraries. That said, I can't think of a single AMD-only library that is better than non-AMD equivalents. Need Bootstrap? Use jQuery. Need charts? Use C3. Branch out, see how the other half lives.

FAQ

  • When should I use this?
    • Best suited for developing new web apps with the ArcGIS API for JavaScript with modern tools without the hassles of the Dojo build
  • When should I not use this?
    • Not suitable for apps that are written in ES5 or use a lot of Dijit and Dojox.
  • What versions of the ArcGIS API for JavaScript can I use with this?
    • This has been tested with v3.16 and v4.0 Beta 3
  • Should I use the compact build?
    • Depends. You should use the compact build unless you are going to use modules that aren't included in it (i.e. esri/dijit/...), in which case you should use the full build
  • Shouldn't I be able to do the same thing with webpack?
    • Go for it. Let me know how that works out for ya.
  • I used to (twitter/facebook/read War and Peace/prep for the Bar exam/crochet) while I was waiting for the Dojo build to finish, when can I do that now?
    • Now you can spend time on your hobbies after you've shipped!

About

Example application using Rollup to bundle local ES2015 modules that use CDN hosted modules from the ArcGIS API for JavaScript

http://tomwayson.github.io/esri-rollup-example/


Languages

Language:JavaScript 71.8%Language:CSS 15.7%Language:HTML 12.4%