Alloy selective compilation, for an even faster Titanium development process

The typical development toolchain in a modern Titanium project involves many tools:

  • Titanium itself;
  • the Alloy framework;
  • TiShadow, for faster development deployments/tests;
  • one or several pre-processors (Coffeescript, Jade, STSS, ticons, etc.) and their Grunt bindings;
  • Grunt and grunt-contrib-watch to wrap it all.

My colleague Claire already explained a lot in her conference “Titanium – Automating Workflow” during the TiConf Amsterdam, but recent projects have proved us that we can go one step further.

While TiShadow is a very good way of improving your production rate with Titanium and Alloy, it can be limited with large Alloy projects. We recently had the case with a huge codebase, where even using TiShadow wasn’t a sufficient improvement to make the developer’s life “easy”.

With our classical Titanium development environment, each and every file change launches the following steps:

  1. a file gets change (coffeescript, stss, etc.)
  2. grunt-coffescript compiles it from the coffee directory to the app folder
  3. grunt-tishadow runs the tishadow run command

By default, in an Alloy project, the tishadow run command runs a complete Alloy compilation, which means that every js, XML or tss file in the app folder will be processed to create their equivalent in the Resources folder. With a project large of 1000+ files, the Alloy compilation is slow (which means 5–15 seconds on a performant Macbook pro) and can be a pain for the developer, annihilating all the ease introduced by TiShadow.

TiShadow lately introduced the -s switch, which allows to bypass the Alloy compilation, and therefore directly runs the code available in the Resources directory. When developing an Alloy app, this won’t however match the requirements of the Titanium developer, who wants to be able to test the very last modifications made in the coffee or stss files.

We lately digged into Alloy’s compiler code and found it could be optimized to allow only process the compilation path of a single file. The pull request ALOY-620 – #625 introduces a new “file” option, which allows to tell the compile command which file was changed and which compilation path has to be worked out by the compiler.

When changing one single file in an Alloy project, there’s no more need for a complete Alloy rebuild: simply launch the compile command with the file= switch:

$ alloy compile --config platform=ios,file=app/controllers/index.js

Depending on the filetype (controller, stylesheet, view, theme, library, alloy.js, etc.), this will only re-generate the required files, not the whole bunch of Titanium Classic files it used to build. And the result is blazing fast:

$ time alloy compile --config platform=ios
...
[INFO] Alloy compiled in 9.64312s

$ time alloy compile --config platform=ios,file=app/controllers/index.js
...
[INFO] Alloy compiled in 0.40075s

Instead of waiting for almost 10 seconds, the Titanium developer will be able to observe the changes in a couple of seconds. Automating this flow with grunt-contrib-watch and grunt-tishadow isn’t an immediate task though. It requires several steps:

  • watch for changes made in the app folder with grunt-contrib-watch. Listen for the change event and, for each file modified, change the configuration of grunt-alloy to pass the name of the file to be changed ;
  • with grunt-tishadow, disable Alloy’s automatic compilation (skipAlloyCompile set to true). A recently merged pull-request has made it possible and only listen changed on Resources/ ;
  • instead of developping in app or Resources, the developer now writes code in the src folder. As a convenience, a copy task copies everything (apart from ltss and coffee files) from src to app ;
  • several instances of grunt-contrib-watch must be run simultaneously and, hence, are watching through grunt-concurrent.

I forked the Alloy Bootstrap project made by my colleague Vincent to wrap all the required tools together. If you have a look at it, pay attention to the Gruntfile’s watch event manager. Most of the magic is made inside this listener, which drastically restricts the (pre-) compilation operations.

Developing for native targets can be painful and slow. TiShadow helped a lot in this sake, let’s make it a bit even faster!

Code Strong !

blog comments powered by Disqus