Hashrocket.com / blog

Large 6713554905 51817878f7 o

A Compendium of Hooks in EmberCLI

posted on and written by in

Image 100x100 jonathan jackson

Below you'll find information relevant to creating addons in EmberCLI. Addons are a powerful abstraction in EmberCLI. These addons help enable the extension of Ember applications built with the framework. EmberCLI has several generators that make creating addons simple, but knowing where to put your addon specific customizations can be difficult. This post will attempt to list all known addon hooks as of EmberCLI version 0.1.4.

Table of Contents:

  1. config
  2. bluprintsPath
  3. includedCommands
  4. serverMiddleware
  5. postBuild
  6. preBuild
  7. included
  8. postProcess
  9. treeFor
    1. treeForApp
    2. treeForStyles
    3. treeForTemplates
    4. treeForAddon
    5. treeForVendor
    6. treeForTestSupport
    7. treeForPublic

For each hook we'll cover the following (if applicable):

  • Received arguments
  • Source
  • Default implementation
  • Uses
  • Examples

Compendium is largely based of a talk by @rwjblue which can be found here

Config

Augments the applications configuration settings. Object returned from this hook is merged with the application's configuration object. Application's configuration always take precedence.

Received arguments:

  • env - name of current environment (ie "developement")
  • baseConfig - Initial application config

Source: lib/models/addon.js:312

Default implementation:

Addon.prototype.config = function (env, baseConfig) {
  var configPath = path.join(this.root, 'config', 'environment.js');

  if (fs.existsSync(configPath)) {
    var configGenerator = require(configPath);

    return configGenerator(env, baseConfig);
  }
};

Uses:

  • Modifying configuration options (see list of defaults here)
    • For example
    • minifyJS
    • storeConfigInMeta
    • es3Safe
    • et, al

Examples:

blueprintsPath

Tells the application where your blueprints exist.

Received arguments: None

Source: lib/models/addon.js:304

Default implementation:

Addon.prototype.blueprintsPath = function() {
  var blueprintPath = path.join(this.root, 'blueprints');

  if (fs.existsSync(blueprintPath)) {
    return blueprintPath;
  }
};

Uses:

  • Let application know where blueprints exists.

Examples:

includedCommands

Allows the specification of custom addon commands. Expects you to return an object whose key is the name of the command and value is the command instance.

Received arguments: None

Source: lib/models/project.js:234

Default implementation: None

Uses:

  • Include custom commands into consuming application

Examples:

  // https://github.com/rwjblue/ember-cli-divshot/blob/v0.1.6/index.js
  includedCommands: function() {
    return {
      'divshot': require('./lib/commands/divshot')
    }
  }

serverMiddleware

Designed to manipulate requests in development mode.

Received arguments: - options (eg express_instance, project, watcher, environment)

Source: lib/tasks/server/express-server.js:63

Default implementation: None

Uses:

  • Tacking on headers to each request
  • Modifying the request object

Note: that this should only be used in development, and if you need the same behavior in production you'll need to configure your server.

Examples:

postBuild

Gives access to the result of the tree, and the location of the output.

Received arguments:

  • Result object from broccoli build
    • result.directory - final output path

Source: lib/models/builder.js:111

Default implementation: None

Uses:

  • Slow tree listing
  • May be used to manipulate your project after build has happened
  • Opportunity to symlink or copy files elsewhere.

Examples:

  • ember-cli-rails-addon
    • In this case we are using this in tandem with a rails middleware to remove a lock file. This allows our ruby gem to block incoming requests until after the build happens reliably.

preBuild

Hook called before build takes place.

Received arguments:

Source: lib/models/builder.js:114

Default implementation: None

Uses:

Examples:

  • ember-cli-rails-addon
    • In this case we are using this in tandem with a rails middleware to create a lock file. [See postBuild]

included

Usually used to import assets into the application.

Received arguments:

Source: lib/broccoi/ember-app.js:216

Default implementation: None

Uses:

  • including vendor files
  • setting configuration options

Note: Any options set in the consuming application will override the addon.

Examples:

// https://github.com/yapplabs/ember-colpick/blob/master/index.js
included: function colpick_included(app) {
  this._super.included(app);

  var colpickPath = path.join(app.bowerDirectory, 'colpick');

  this.app.import(path.join(colpickPath, 'js',  'colpick.js'));
  this.app.import(path.join(colpickPath, 'css', 'colpick.css'));
}

postProcess

Received arguments:

  • post processing type (eg all)
  • receives tree after build

Source: lib/broccoli/ember-app.js:251

Default implementation: None

Uses:

  • fingerprint assets
  • running processes after build but before toTree

Examples:

treeFor

Return value is merged with application tree of same type

Received arguments:

  • returns given type of tree (eg app, vendor, bower)

Source: lib/broccoli/ember-app.js:240

Default implementation:

Addon.prototype.treeFor = function treeFor(name) {
  this._requireBuildPackages();

  var tree;
  var trees = [];

  if (tree = this._treeFor(name)) {
    trees.push(tree);
  }

  if (this.isDevelopingAddon() && this.app.hinting && name === 'app') {
    trees.push(this.jshintAddonTree());
  }

  return this.mergeTrees(trees.filter(Boolean));
};

Uses:

  • manipulating trees at build time

Examples:

treeFor (cont...)

Instead of overriding treeFor and acting only if the tree you receive matches the one you need EmberCLI has custom hooks for the following Broccoli trees

  • treeForApp
  • treeForStyles
  • treeForTemplates
  • treeForAddon
  • treeForVendor
  • treeForTestSupport
  • treeForPublic

See more here

Posted in Ember and tagged with Ember, ember-cli, addons, ember-cli-addons