Building an

Ember Addon

Alex Zirbel

Ember at

Using Ember since 2012!

Keeping up to date

Talk Structure

  • Intro to Ember Addons

  • Converting a library to the new Addon format

Part 1:

Intro to Ember Addons

Components

  • Reuse code in your apps

  • Modular structure

  • Share with the Ember community

Intended Workflow

bower install --save ember-table

Actual Workflow

bower install --save ember-table

...Doesn't seem to be working.

Ah, console claims EmberTable is not found

Include ember-table.js in index.html/app.js

Fix erroneous include order

...Hmm, doesn't look quite right

Include CSS files

...Functionality seems broken

Install and include all dependencies, some undocumented

Works!

Other Problems

  • Global Namespacing

  • Dependencies

  • Compilation

  • Discovery

Ember CLI

ember new app-name
ember server
ember install

Quick Demos

App File Structure

app/
dist/
public/
tests/
vendor/
Brocfile.js
bower.json
package.json

Addon File Structure

app/
addon/
blueprints/
tests/
vendor/
Brocfile.js
package.js
index.js

Library Problems

  • Global Namespacing

  • Dependencies

  • Compilation

  • Discovery
app/

     Merged with app's namespace

 

addon/

     Addon's namespace

addon-side
     export default SelectComponent


app-side
     import SelectComponent from
     'select-component/components/select'

Library Problems

  • Global Namespacing

  • Dependencies

  • Compilation

  • Discovery
bower.json
     "dependencies": {"some-library": "1.1"}


index.js
     module.exports = {
       included: function(app) {
         app.import(app.bowerDirectory +
                   '/some-library/lib.js');
       }
     }

Library Problems

  • Global Namespacing

  • Dependencies

  • Compilation

  • Discovery

Old Way
     dist/ folder

 

New Way: Broccoli
     minification

     LESS/SASS compilation

     Coffeescript compilation

Library Problems

  • Global Namespacing

  • Dependencies

  • Compilation

  • Discovery
package.json
     "keywords": [
       "ember-addon",
       ...
     ]


www.emberaddons.com

Library Problems

  • Global Namespacing

  • Dependencies

  • Compilation

  • Discovery
ember install:addon addon-name

Part 2:

Converting Ember Table to Addon Format

"Stability without Stagnation"

(Unlike                           )

Ember Values

  • Reliability

  • Consistency

  •  

(Also unlike                           )

Ember Values

  • Reliability

  • Consistency

  • Easy Upgrade Path

  •  

Ember 2.0 Lessons

  • Have a transition plan

  • Avoid full rewrites

  • Deprecate then remove

Current Structure

app/
dist/
gh_pages/
tests/
src/
vendor/
Gruntfile.js
bower.json
package.json

Challenges

  • Global Namespacing

  • Install Process

  • Distribution Files

  •  
  <!-- Note that you need antiscroll CSS to support ember-table -->
  <link rel="stylesheet" href="http://rawgit.com/LearnBoost/antiscroll/master/antiscroll.css">
  <link rel="stylesheet" href="http://cdnjs.cloudflare.com/ajax/libs/normalize/2.1.0/normalize.css">
  <link rel="stylesheet" href="http://rawgit.com/Addepar/ember-table/v0.4.0/dist/ember-table.css">
  
  <!-- Ember and dependencies -->
  <script src="//cdnjs.cloudflare.com/ajax/libs/jquery/1.10.2/jquery.js"></script>
  <script src="//cdnjs.cloudflare.com/ajax/libs/handlebars.js/1.3.0/handlebars.js"></script>
  <script src="http://builds.emberjs.com/tags/v1.4.0/ember.js"></script>
  
  <!-- Ember Table and dependencies -->
  <script src="//cdnjs.cloudflare.com/ajax/libs/jqueryui/1.10.2/jquery-ui.js"></script>
  <script src="//cdnjs.cloudflare.com/ajax/libs/jquery-mousewheel/3.1.6/jquery.mousewheel.js"></script>
  <script src="http://rawgit.com/LearnBoost/antiscroll/master/antiscroll.js"></script>
  <script src="http://rawgit.com/Addepar/ember-table/v0.4.0/dist/ember-table.js"></script>

Transition Plan

  • Phase 1: Import and Export

  • Phase 2: Migrate Demo App

  • Phase 3: Migrate src

  •  

Phase 1: Import and Export

ember addon ember-table

Phase 1: Import and Export

{
  "name": "ember-table",
  "version": "0.2.3",
  "dependencies": {
    "handlebars": "~1.3.0",
    "jquery": "^1.11.1",
    "ember": "1.7.0",
  },
  "devDependencies": {
    "ember-table": "0.2.3"
  }
}

bower.json

Phase 1: Import and Export

module.exports = {
  // Hack for previous versions of Ember CLI
  normalizeEntityName: function() {},

  afterInstall: function(options) {
    return this.addBowerPackageToProject('ember-table');
  }
};

blueprints/ember-table/index.js

Phase 1: Import and Export

'use strict';

module.exports = {
  name: 'ember-table',

  included: function(app) {
    this._super.included(app);

    app.import(app.bowerDirectory + '/antiscroll/antiscroll.js');
    app.import(app.bowerDirectory + '/antiscroll/antiscroll.css');
    app.import(app.bowerDirectory + '/jquery-ui/ui/jquery-ui.custom.js');
    app.import(app.bowerDirectory + '/jquery-mousewheel/jquery.mousewheel.js');
    app.import(app.bowerDirectory + '/ember-table/dist/ember-table.js');
    app.import(app.bowerDirectory + '/ember-table/dist/ember-table.css');
  }
};

index.js

Phase 1: Import and Export

export default Ember.Table.ColumnDefinition;

addon/column-definition.js

export default Ember.Table.EmberTableComponent;

app/components/ember-table.js

Phase 1: Import and Export

  • Installation:

 

 

 

 

  • ​Problems
    • ​Globals still pollute namespace
    • Source code not actually ported
ember install:addon ember-table

# Which does:
npm install --save ember-table
ember generate ember-table

Phase 2: Migrate Demo App

app/
dist/
gh_pages/
tests/
src/
vendor/
Gruntfile.js
bower.json
package.json
app/
addon/
blueprints/
tests/
  dummy/
    app/
    config/
    public/
vendor/
Brocfile.js
package.js
index.js

Phase 2: Migrate Demo App

app/
dist/
gh_pages/
tests/
src/
vendor/
Gruntfile.js
bower.json
package.json
app/
addon/
blueprints/
tests/
  dummy/
    app/
    config/
    public/
vendor/
Brocfile.js
package.js
index.js

Phase 2: Migrate Demo App

  • Only src/ code remains
  • Can test ported code

Phase 3: Migrate src

app/
dist/
gh_pages/
tests/
src/
vendor/
Gruntfile.js
bower.json
package.json
app/
addon/
blueprints/
tests/
  dummy/
    app/
    config/
    public/
vendor/
Brocfile.js
package.js
index.js

Phase 3: Migrate src

import TableComponent from 'ember-table/components/table-component';

export default TableComponent;

app/components/ember-table.js

Optionally, re-export in the app namespace

Phase 3: Migrate src

import TableComponent from 'ember-table/components/table-component';
import ColumnDefinition from 'ember-table/column-definition';
...

Ember.Table.EmberTableComponent = TableComponent;
Ember.Table.ColumnDefinition = ColumnDefinition;
...

globals/ember-table.js

Optionally, add a globals build

Done!

Publish to NPM

 

(For ember-table - coming soon!)

ember install:addon ember-table

Thanks!

We're hiring

Contact & Info

Addepar

www.addepar.com

Building an Ember Addon

By Alex Zirbel

Building an Ember Addon

A review of how to build a component addon in Ember CLI. There are two parts: an introduction to Ember Addons, and a look at the migration process for an existing library (Addepar's Ember Table).

  • 5,167