Skip to content

Latest commit

 

History

History
525 lines (339 loc) · 13.6 KB

ADDON_HOOKS.md

File metadata and controls

525 lines (339 loc) · 13.6 KB

Table of Contents:

  1. config

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 "development")
  • baseConfig - Initial application config

Source: lib/models/addon.js:485

Default implementation:

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

  if (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:457

Default implementation:

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

  if (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:388

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:64

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:117

Default implementation: None

Uses:

  • Slow tree listing
  • May be used to manipulate your project after build has happened

preBuild

Hook called before build takes place.

Received arguments:

Source: lib/models/builder.js:112

Default implementation: None

Uses:

outputReady

Hook called after the build has been processed and the files have been copied to the output directory

Received arguments:

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

Default implementation: None

Examples:

  • Opportunity to symlink or copy files elsewhere.
  • 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.

buildError

buildError hook will be called on when an error occurs during the preBuild, postBuild or outputReady hooks for addons, or when builder#build fails

Received arguments:

  • The error that was caught during the processes listed above

Source: lib/models/builder.js:119

Default implementation: None

Uses:

  • Custom error handling during build process

Examples:

included

Usually used to import assets into the application.

Received arguments:

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

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.apply(this, arguments);

  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'));
}

shouldIncludeChildAddon

Can be used to exclude addons from being added as a child addon.

Received arguments:

Source: lib/models/addon.js:638

Default implementation: return true

Uses:

  • abstract away multiple addons while only including one into the built assets

Examples:

shouldIncludeChildAddon: function select_shouldIncludeChildAddon(childAddon) {
  if(childAddon.name === 'ember-cli-some-legacy-select-component') {
    return this.options.legacyMode;
  } else if(childAddon.name === 'ember-cli-awesome-new-select-component') {
    return !this.options.legacyMode;
  } else {
    return this._super.shouldIncludeChildAddon.apply(this, arguments);
  }
}

setupPreprocessorRegistry

Used to add preprocessors to the preprocessor registry. This is often used by addons like ember-cli-htmlbars and ember-cli-coffeescript to add a template or js preprocessor to the registry.

Received arguments

  • type either "self" or "parent"
  • registry the registry to be set up

Source: lib/preprocessors:7

Default implementation: None

Uses:

  • Adding preprocessors to the registry.

Examples:

// https://github.com/ember-cli/ember-cli-htmlbars/blob/master/ember-addon-main.js
setupPreprocessorRegistry: function(type, registry) {
  var addonContext = this;

  registry.add('template', {
    name: 'ember-cli-htmlbars',
    ext: 'hbs',
    toTree: function(tree) {
      return htmlbarsCompile(tree, addonContext.htmlbarsOptions());
    }
  });
}

postprocessTree

Received arguments:

  • post processing type (eg all)
  • receives tree after build
  • receives tree for a given type after preprocessors (like HTMLBars or babel) run.

available types:

  • js
  • template
  • all
  • css
  • test

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

Default implementation: None

preprocessTree

Received arguments:

  • type of tree (eg template, js)
  • receives tree for a given type before preprocessors (like HTMLBars or babel) run.

available types:

  • js
  • template
  • css
  • test

Default implementation: None

Uses:

  • removing / adding files from the build.

Examples:

lintTree

Return value is merged into the tests tree. This lets you inject linter output as test results.

Received arguments:

  • tree type ('app', 'tests', or 'addon')
  • tree of Javascript files

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

Default implementation: None

Uses:

  • JSHint
  • any other form of automated test generation that turns code into tests

Examples:

contentFor

Allow addons to implement contentFor method to add string output into the associated {{content-for 'foo'}} section in index.html

Received arguments:

  • type
  • config
  • content

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

Default implementation: None

Uses:

  • For instance, to inject analytics code into index.html

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:296

Default implementation:

var mergeTrees = require('broccoli-merge-trees');

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 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
  • treeForAddonTemplates
  • treeForAddon
  • treeForVendor
  • treeForTestSupport
  • treeForPublic
  • treeForAddonTestSupport

When overriding a hook, if you want to preserve it's original functionality, call the same method on _super with the function arguments.

Examples:

treeForAddon: function(tree) {
  var checker = new VersionChecker(this);
  var isOldEmber = checker.for('ember', 'bower').lt('1.13.0');

  if (isOldEmber) {
    tree = new Funnel(tree, { exclude: [ /instance-initializers/ ] });
  }

  return this._super.treeForAddon.call(this, tree);
}

isDevelopingAddon

Allows to mark the addon as developing, triggering live-reload in the project the addon is linked to

Received arguments: None

Default implementation: None

Uses:

  • Working on projects with internal addons

Examples:

  // addon index.js
  isDevelopingAddon: function() {
    return true;
  }

See more here.