docs: function onJSChanged() {
    if (typeof this.jsh === 'undefined') {
      var JSH = require('./helpers/JsHelper');
      this.jsh = new JSH(this.directory);
    }
  
    var that = this;
    // Cases to recompute:
    //    a root file changes: index.js could remove require of lib/index making index.js a root and lib/index a root
    //    a non-root file changes: b.js is the root and a.js changes to require b.js making it the new root
    return this.jsh.getRoots().then(function (roots) {
      return that.jsh.haveRootsChanged(roots);
    })
    .then(function (haveRootsChanged) {
  
      if (! haveRootsChanged) {
        console.log('roots haven\'t changed');
        return;
      }
  
      console.log('An app root has changed');
  
      // Need all of the targets to regenerate the gruntfile
      return that.getAllSettings().then(function (targets) {
        return that.engine.getConfig(targets, that.extensions);
      })
      .then(function (config) {
        // Grab the targets for the apps and merge with the existing targets
        return that.jsh.getSettings().then(function (settings) {
          utils.shallowExtend(config, settings.target);
  
          return config;
        });
      })
      .then(function (config) {
        // console.log('Config: ', config)
        return that.engine.flushConfig(config)
          .then(function () {
            return that.engine.compileTasks(config);
          });
      });
    });
  }