Node + Ember
Dean Sofer
Follow Along: slides.com/ProLoser/node-plus-ember/live
whois dean sofer?
- Github.com/ProLoser
 - Señor Engineer at Sony
 - Founder of AngularUI
 - Started on CakePHP/jQuery
 - Playstation Vue Architect
 - Glorious mustache proprietor
 

Wise Man Says
- API design === User Experience Design
 - Refactor-friendly FTW
 - Composition over Convention
 - Obfuscation for its own sake is evil
 - Pretend everything is public
 - Expect the unexpected
 
Node First
- The library is node first, everything else second
 - Node packages and standards increase compatibility
 - Ember has a very specific and opinionated API
 - Core library is written without knowledge of Ember
 
ES6 in Node.js
- Native ES6 support with 'use strict'
 - Easier development / debugging
 - See node.green for details
 - Compiled source tree for most
 - BUT DON'T BUNDLE NODE CODE!
 
Bundling Antipattern
Redundant bundling breaks tree-shaking
- Redundant libraries
 - Bigger filesize
 - Debugging is much harder
 - Complicated dependency upgrades
 
App
- Dependency B
- Library(A+B)
App(B+Library(A+B))Library
- Dependency A
- Dependency BLibrary(A+B)
bundle
library
bundle
app
Compiled Tree
/*** core-library/package.json ***/
{
  ...
  "main": "compiled/index.js",
  "dependencies": {
    "babel-preset-es2015": "^6.6.0",
    "babel": "^6.5.2"
  }
}/*** core-library/.babelrc ***/
{
  "presets": [
    "es2015"
  ]
}Save the trees!
- Files are local, unlike websites
 - Files are smaller
 - Building is faster (and incremental)
 
Node in Ember
- Ember recommended solution
 - Bower is dying. Long live Browserify!
 - Namespaced imports "npm:core-library"
 - Browserify can compile too
 
?
Compiling Antipattern
DON'T double compile your code
es6
compile
compile
watchers
sourcemaps
es5
bundled
waiting
watchers
waiting
sourcemaps
build tool A
build tool B
Targetting Clients
/*** core-library/package.json ***/
{
  ...
  "browser": "src/index.js",
  "browserify": {
    "transform": [
      "babelify"
    ]
  },
  "dependencies": {
    ...
    "babel-preset-es2015": "^6.6.0",
    "babelify": "^7.2.0"
  }
}/*** core-library/.babelrc ***/
{
  "presets": [
    "es2015"
  ]
}es6
es5 bundled
browserify
Separating Concerns
- What can I do without Ember?
	
- Classes
 - Queries
 - Reads
 - Utilities
 
 - What must I do with Ember?
	
- Rendering
 - Ember.set()
 - Function.property()
 
 
Show me
the Code
/*** core-library/Base.js ***/
class Base {
  constructor(data) {
    Object.assign(this, data);
  }
}
module.exports = Base;
/*** core-library/Project.js ***/
const Base = require('./Base');
const Task = require('./Task');
class Project extends Base {
  static get(id) {
    return query(`/projects/${id}`).then( project =>
      new Project( project );
    );
  }
  constructor(data) {
    super(data);
    this.tasks = this.tasks.map( task => 
      new Task( task )
    );
  }
  isComplete() {
    return this.tasks.every( task => 
      task.completed
    );
  }
}
module.exports = Project;But Ember-Data!
- Ember-Data doesn't work for everything
 - Want to use business logic outside of Ember
 - We have a terrible server API
 - Easy to roll our own with ES6
 - Code is transparent and refactor friendly
 
ember Wrapper
/*** my-addon ***/
import CoreLibrary from 'npm:core-library';
import Ember from 'ember';
const Base = CoreLibrary.Base;
// Monkey-patch CoreLibrary with Ember utils
Base.prototype.set = function(property, value) {
    return Ember.set(this, property, value);
};
Base.prototype.get = function(property) {
    return Ember.get(this, property);
};
// Configure environment for Ember statically
CoreLibrary.setPromiseLibrary(Ember.RSVP.Promise);
CoreLibrary.configure({ ... });
// Or create Ember configured instance
export default new CoreLibrary({ ... });- Ember addon for core library
 - Handles installation
 - Handles dependencies
 - Handles library configuration
 - Adds Ember-specific logic
 - NOT an alias for core library
 
Ember Wrapper Setup
/*** my-addon/package.json ***/
{
  ...
  "peerDependencies": {
    "ember-browserify": "^1.1.8",
    "my-node-library": "^1.0.0"
  }
}
/*** my-addon/blueprints/my-addon/index.js ***/
module.exports = {
  ...
  afterInstall: function(options) {
    return this.addPackagesToProject([
      { name: 'ember-browserify' },
      { name: 'my-node-library' }
    ]);
  }
};my-app/
  node_modules/
    ember-browserify/
    my-addon/
      addon/
        index.js
      app/
        dependencies.js
      blueprints/
        my-addon/
          index.js
    core-library/
      library.js
      package.json
      node_modules/
        babelify/
        babel-preset-es2015//*** my-addon/addon/index.js ***/
import CoreLibrary from 'npm:core-library';
...
/*** my-addon/app/dependencies.js ***/
import coreLibrary from 'npm:core-library';
// Informs ember-cli of npm:core-library
// This file never gets executedReady to Use
/*** my-app ***/
import CoreLibrary from 'npm:core-library';
import coreLibrary from 'my-addon';
CoreLibrary.Project.get(123).then( project =>
  project.set('name', 'Presentation');
);
coreLibrary.Project.get(123).then( ... )ember install my-addonmind = blown
FEEN
Node + Ember
By Dean Sofer
Node + Ember
Presentation video: https://youtu.be/kmRsjnTZXpE Additional notes: https://github.com/ProLoser/node-to-embe
- 2,817