One of the things I really like about ember is the tooling it provides to developers. It’s a great workflow. You just use the command-line to generate an app and it has other built in generators to develop other pieces of your application as you need them. Under the hood the ember-cli is powered by tons of node and broccoli.
I had some basic goals for this generator.
- All code to be written in ES6/ES2015
- Testing built in
- Provide a Dojo build process
- Simple component structure
- Easy development workflow
I just did a recent write up on testing your code. So to help you a bit with that, intern3 is included as the default testing library. For every component you generate, you’ll also get an accompanying unit test. I’d recommend reading over the Sitepen blog for more detailed intern info. By default, tests are written in chai bdd style with sinon-chai for spies and mocks as needed. The generated app also includes a local selenium driver so you can run functional tests locally without a SauceLabs account if you want. For more info on functional tests, check out intern recorder. Functional tests can be run using grunt e2e in the command line.
Dojo build process
For a long time, I found the Dojo build process to be this mysterious, difficult thing to grasp. When you get the basics down, it starts to fall into place and becomes simpler. It has a lot of options though and various settings that could be tweaked depending on what it is you want to do. I wanted to kind of simplify this for developers by setting up all the basics and keep the process as easy as possible.
The generator uses grunt-dojo to execute the Dojo build. Here is a snippet from the provided Gruntfile. gist
And here is a link to the build profile. One of the important parts of the profile is the layers portion. gist
This is pretty much taken from Tom Wayson’s sample. If you find that Dojo is still lazy-loading some files after the build process, you can add them the include section of the layers in the profile to include them in the single-file build. Also, if you really want that mythical single-file build, be sure to include any locales you need to support in the includeLocales list.
One more note on the Dojo build bits. When running the Dojo build via grunt use grunt release —force. There is something up with some files in the ArcGIS API not being recognized as AMD when using grunt-esri-slurp to add them to the project. I’m hoping to alleviate this issue in the near future. I’m working on it, I swear, sorry for the delays.
Simple component structure
The output structure of the generated app is as follows.
app/ ...components/ ...helpers/ ...models/ ...styles/ ...templates/ ......Application.html ......Application.js ...app.profile.js ...config.js ...main.js ...package.json ...router.js
So this structure is again very Ember-inspired. The components folder is essentially where widgets would go. Each component has it’s own templates and css folder and is defined by a View.js file. Very standard structure. Except for the Map component. This has a MapView and WebMap view you can use depending on whether or not you are creating a map from scratch or using a WebMap itemid to generate a map. This might change in the future.
The helpers folder is basically where small helper utilities would go. The models folder would be used for any common models used in your application. The generator utilizes dmodel for model generation. I’m still thinking through this. I’m not sure if models explicitly would be needed or if it would be better to have a stores module using dstore. I’ve also implemented a services folder in a couple of projects, so that might make it’s way into the generator, although I have to think of a way to design it that would work for everyone.
There is a styles folder for all the common css for your application. Stylus is used as the css preprocessor for the generated application.
The templates folder would contain global areas of your application. There is an Application.html and Application.js that are the base of the application. You may also want to put other files in here for multiple routes of your application. The dojo/router is used for routing in the generated app. I wrote more about it here. I’m considering switching this out for a different routing library though to simplify passing model data around to routes.
The main.js just wires the whole application together. The config.js has various configuration bits of the application. I’m kind of moving away from the whole configuration-based widget generation that I have done in the past. Mainly due to every application needing slight tweaks to individual modules that requires forking a module and that this configuration based workflow requires more work in the build process. I’m a bit on the fence on this one, but for now I think the generator is best without it. The app.profile.js and package.json are used for the Dojo build process to define the app folder as a package.
Easy development workflow
Once you’ve installed Yeoman and other dependencies as needed you can use the generator to create your application.
You’ll be prompted for some basic info, such as what version of the ArcGIS JS API esri-slurp should download, name of project and your email address. It will then start the process of downloading all npm and bower dependencies and when done do an initial compile of your ES6 to a dist folder. At this point you can run grunt dev and it will start a local server where you can view your application at
http://localhost:8282/dist/. It will automatically inject a livereload script into your page so if you have it installed in your browser it will turn on without you needing to activate it. It’s also set up so that as you make changes to your code, it will recompile your ES6 code to ES5 and livereload will reload your page. You can also view your tests at
http://localhost:8282/node_modules/intern/client.html?config=tests/intern. I like to keep two browser windows open, one for my app, the other for my tests.
You can generate additional components by using yo arcgis-js-app:components ComponentName. As I said, it will add the component to your app and also add the tests to intern for the component.
Check out a demo application built using the generator here on github.
When you are ready to release, you can run grunt release —force and it will take a few minutes or so run the Dojo build process on your application. The build output will be a release folder. The intermediate build is located in a built folder. When the build is done it will automatically copy the dojo/dojo.js file into the release folder as app.js. It will also use a new grunt plugin I wrote called grunt-css-url-copy to scan the app/styles/main.css file for all url references and copy them into a release/resources folder. It will then create a release/app.css with modified url references to point to the new resources folder. The index.html file copied into the release folder is modified to point to these new files and stripped of the livereload script and dojoConfig, since the dojoConfig is baked into the app.js file during the build. This gives you the following folder structure for release.
release/ ...index.html ...app.css ...app.js ...resources/
This is all you need to deploy for your application. Rather than all the built files the Dojo build will generate. Remember, you need to include all locales you want to support into the build or it will try to lazy-load them as needed. If any other files are trying to be lazy-loaded, you can read back on the build section of this post to see how to add them to your build.
I’m thinking this is a good starting point for most people. I might try to offer some options during the generator portion on whether you want this single-file build or maybe a build where all the EsriJS/Dojo stuff is a vendor.js, your code is app.js. Or that could be left up to the user to decide after the fact.
As you can see, you get a lot of simple to use tooling from this generator. I looked at other generators like the generator-dojo-class and generator-dojo-widget as samples. I should point out, I had issues with the Dojo build process using empty nls files, so I removed them from the generator. These should probably be created by the developer anyway if they need them or I can include them with some dummy strings that I think will fix the build.