broccoli-dist-es6-module icon indicating copy to clipboard operation
broccoli-dist-es6-module copied to clipboard

Cannot support both globals and named-amd when building ember components

Open DingoEatingFuzz opened this issue 10 years ago • 0 comments

I wanted to start a discussion regarding imports, multiple distribution targets, and side-effects.

Consider a library of components that you want to include in your ember-cli project. These components would be used in your application in the templates. This alone is achievable.

Import the library in the Brocfile

app.import('vendor/third-party-components/dist/named-amd/main.js', {
  'third-party-components': [
    'ThirdPartyComponentOne',
    'ThirdPartyComponentTwo'
  ]
});

Then it needs to be initialized in an initializer file.

import { 
  ThirdPartyComponentOne, 
  ThirdPartyComponentTwo 
} from 'third-party-components';

export default {
  name: 'thirdPartyComponents',
  initialize: function(container) {
    container.register('component:component-one', ThirdPartyComponentOne,
    container.register('component:component-two', ThirdPartyComponentTwo
  }
};

Perfect. This will work. In fact we can go one step further and introduce a default initializer for people who want to quickly use everything the way we named it.

import { initializer } from 'third-party-components';
export default initializer;

This is great for people using ember-cli and named-amd.

As the author of this library of components, I want to support people who are building ember apps with globals.

To do this, I would have to change the way I am authoring my main.js file.

import { 
  ThirdPartyComponentOne, 
  ThirdPartyComponentTwo 
} from 'third-party-components';
import Ember from 'ember';

Ember.Application.initializer({
  name: 'thirdPartyComponents',
  initialize: function(container) {
    container.register('component:component-one', ThirdPartyComponentOne,
    container.register('component:component-two', ThirdPartyComponentTwo
  }
});

This way, when the file is imported in the Brocfile, it will automatically be initialized.

This is great for people using globals.

The problem comes when I want to support both named-amd and globals.

The globals method works by initializing on evaluation. This doesn't jive well with the import export nature of modules. The initialization then happens as a side-effect of importing. This is an issue since ember apps throw errors when the same initializer is initialized twice.

I have currently settled on an unhappy compromise favoring globals. It looks like this:

// Components are initialized as a side-effect of import
// This is necessary for exporting components for both
// Globals and named-amd support
window.console.log('HACK!', BooleanInputComponent);

The build will only pass if I use that which I am importing. However, I am actually using what I am importing simply by importing it.

So here are the questions:

  1. Should initializing these components even be a part of what I am exporting?
  2. Is this es6 module the correct place to facilitate the need for differences between named-amd, globals, etc. builds?
  3. Is there a popular opinion regarding modules and side-effects?

DingoEatingFuzz avatar May 15 '14 00:05 DingoEatingFuzz