ember.jsember-cliember-addon

ember-cli and the contentFor method in an Ember Addon dependency chain


My problem is I am unable to get the contentFor method in an addon to run when this addon is used in a dependency of another addon (confusing I know).

My organization has an in-house ember addon that we use to distribute common styles, images and components for our ember applications. I'll refer to that addon as org-components. We have decided to adopt material design, and so we have chosen to use ember-paper along with our existing addon.

In order to reduce the number of dependancies people would need to reference in the ingesting applications, we would prefer to include ember-paper as a dependency of org-components (not a devDependency).

Thus our dependency chain goes like so:

ember-paper -> org-components -> ember-engine

ember-paper has a contentFor method defined in ~/index.js that will inject a couple of stylesheets for Material icons and fonts in the head and paper-wormhole divs into body-footer for use by the select menu dropdowns and toast messages. For reasons I do not know, the contentFor method does not execute when ember-paper is included as a dependency as shown above.

When I include both components as separate dependancies, then the contentFor method is executed and things work as expected: ember-paper -> ember-engine org-components -> ember-engine

So I am looking to understand why I am unable to leverage the ember-paper addon when it is used as a dependency of our existing addon. What is preventing the contentFor build step from being executed? Is their a best practice I should keep in mind while trying to solve this problem?


Solution

  • I eventually was able to discover a solution to this problem, thanks to the always helpful Robert Jackson from the Ember Team.

    After pleading for help in the Ember Slack community, Robert made me aware that the existing contentFor functionality in ember-engines was not extended yet to handle this use-case. He acknowledged that it was an oversight and that they would most likely be adding the functionality in the future, but for the time being he provided me with a workaround to add into /lib/engine-addon.js.

    options.contentFor = function(type, config) {
      let deprecatedHooks = ['app-prefix', 'app-suffix', 'vendor-prefix', 'vendor-suffix'];
      if (deprecatedHooks.indexOf(type) > -1) {
        // ember-engines does not support the deprecated contentFor hooks
        return '';
      }
    
      let content = [];
      if (type === 'head') {
        let engineConfig = this.engineConfig(config.environment, {});
        let escapedConfig = escape(JSON.stringify(engineConfig));
    
        content = content.push(
            `<meta name="${options.name}/config/environment" content="${escapedConfig}" />`
        );
      }
    
      content = this.addons.reduce((content, addon) => {
        let addonContent = addon.contentFor ? addon.contentFor(type, config, content) : null;
        if (addonContent) {
          return content.concat(addonContent);
        }
    
        return content;
      }, content);
    
      return content.join('\n');
    };
    

    Also available as a Gist

    I have not kept up with the dev roadmap for ember-engines or whether this has been added into a later version than what we are currently using. As noted the folks in the Ember Slack are very helpful and will point you in the right direction if you have those questions.