Aligning Ember.js with Web Standards

Preview:

Citation preview

Aligning Ember withWeb Standards

EmberConf 2015

@mixonic

Matthew Beale

201 Created

The JavaScript standardizationprocess is about to change

#1

STANDARDS PROCESS

WHATWG + W3C

TC39 + Ecma International

WHATWG + W3C

TC39 + Ecma International

DOMHTML Web Components XHR, Fetch

Promises for loops var, let, const classes

WHATWG W3C

TC39 Ecma International

WHATWG W3C

TC39 Ecma International

WORKING

GROUPSSTANDARDS GROUPS

The plan at the time was to finish the specification this year and publish a snapshot of "HTML5" in 2012. However, shortly after that we realized that the demand for new features in HTML remained high, and so we would have to continue maintaining HTML and adding features to it before we could call “HTML5" complete, and as a result we moved to a new development model, where the technology is not versioned and instead we just have a living document that defines the technology as it evolves.

Ian Hickson, 2011

“Living Standard”

ES3

ES4

ES5

ES6

ES6

ES2015

“ES2015” signifies a newstandardization process

github.com/ tc39/ecma262

0. Strawman 1. Proposal 2. Draft 3. Candidate 4. Finished

0. Strawman 1. Proposal -> Polyfills 2. Draft -> Experimental 3. Candidate -> Compliant 4. Finished -> Shipping

a “Living Web”

Aligning with standardsis not a one time event

Aligning with standardsis not free

Why standards?

Productivity

1. are portable 2. reflect best practices 3. endure

Standards…

Participants win

Design

Polyfill, demo

Real world use

Learning

Design

Polyfill, demo

Real world use

Learning

2. Transpilers are here to stay

This is not the first time features have been added to JavaScript

ES3 -> ES5

HTML5

“Polyfill”- Remy Sharp

ES5 -> ES2015

var map = new Map(); map.set('key', 'value'); var value = map.get('key');

var map = new Map(); map.set('key', 'value'); var value = map.get('key');

1 var delayed = new Promise( 2 function(resolve, reject){ 3 setTimeout(resolve, 100); 4 } 5 ); 6 delayed.then(function(){ 7 console.log('HTMLBars'); 8 });

1 var delayed = new Promise( 2 function(resolve, reject){ 3 setTimeout(resolve, 100); 4 } 5 ); 6 delayed.then(function(){ 7 console.log('HTMLBars'); 8 });

1 var loggingObject = new Proxy({}, { 2 get(target, propertyKey, receiver) { 3 console.log('GET '+propertyKey); 4 return target[propertyKey]; 5 } 6 }); 7 8 loggingObject.whatever; // Logs: GET whatever

1 var loggingObject = new Proxy({}, { 2 get(target, propertyKey, receiver) { 3 console.log('GET '+propertyKey); 4 return target[propertyKey]; 5 } 6 }); 7 8 loggingObject.whatever; // Logs: GET whatever

1 var runner = { 2 count: 0, 3 call: function() { 4 setTimeout(() => { 5 console.log(this.count++); 6 }, 100); 7 } 8 }; 9 10 runner.call();

1 var runner = { 2 count: 0, 3 call: function() { 4 setTimeout(() => { 5 console.log(this.count++); 6 }, 100); 7 } 8 }; 9 10 runner.call();

“Babel will turn your ES6+ code into ES5 friendly code, so you can start using it right

now without waiting for browser support.”

1 "use strict"; 2 3 var runner = { 4 count: 0, 5 call: function call() { 6 var _this = this; 7 8 setTimeout(function () { 9 console.log(_this.count++); 10 }, 100); 11 } 12 }; 13 14 runner.call();

1 var runner = { 2 count: 0, 3 call: function() { 4 setTimeout(() => { 5 console.log(this.count++); 6 }, 100); 7 } 8 }; 9 10 runner.call();

1. syntax (fat arrow, let) 2. APIs (Map, Set) 3. not everything

Enables new…

“Not born to die”

- James Kyle

kangax.github.io/compat-table/es6

ES2015 feature: Uint8Array

ES2015 feature: Uint8Array

IE10+

ES2015 feature: Spread Operator

var list = [1,2,3]; Math.max(...list);

ES2015 feature: Spread Operator

var list = [1,2,3]; Math.max(...list);

Firefox only

ES2015 feature: Block-level function scope1 "use strict"; 2 function a(){ return 1; } 3 { 4 function a(){ return 2; } 5 }; 6 7 a() === 1;

ES2015 feature: Block-level function scope

Chrome only

1 "use strict"; 2 function a(){ return 1; } 3 { 4 function a(){ return 2; } 5 }; 6 7 a() === 1;

The target platforms of Babelare inconsistent

Babel

Chrome

Firefox

The platforms your application supports will drive what features are transpiled.

Targeting platforms can be done by tweaking the enabled

features list.

IMO a mapping to platforms would be better.

What you transpile today,you will blacklist in two years

Yes, you will be transpilingin two years

Yes, you will be transpilingin five years

Yes, you will be transpilingin ?!!?!?! years

Transpilers are here to stay

3. Aligning Ember’s object model

1. stable 2. a good pattern 3. implemented correctly 4. implemented performantly

Is this feature:

ES Classes

1. class 2. extend 3. super

Three new tools:

1 class Car { 2 constructor(gearCount){ 3 this.gearCount = gearCount; 4 } 5 6 toString() { 7 return `A car with: ${gearCount} gears`; 8 } 9 } 10 11 var car = new Car(3); 12 car.toString(); // A car with 3 gears

1 class Vehicle { 2 constructor(gearCount){ 3 this.gearCount = gearCount; 4 } 5 } 6 class Car extends Vehicle { 7 toString() { 8 return `A car with: ${this.gearCount} gears`; 9 } 10 } 11 12 var car = new Car(3); 13 car.toString(); // A car with 3 gears

1 class Vehicle { 2 constructor(gearCount){ 3 this.gearCount = gearCount; 4 } 5 toString() { 6 return `${this.gearCount} gears`; 7 } 8 } 9 class Car extends Vehicle { 10 toString() { 11 return `A car with: ${super.toString()}`; 12 } 13 }

1 class Vehicle { 2 constructor(gearCount){ 3 this.gearCount = gearCount; 4 } 5 toString() { 6 return `${this.gearCount} gears`; 7 } 8 } 9 class Car extends Vehicle { 10 constructor(...args) { 11 console.log(`Created with ${args[0]}`); 12 super(args); 13 } 14 toString() { 15 return `A car with: ${super.toString()}`; 16 } 17 }

1. new syntax 2. super semantics change 3. mixins

gotachas:

4. setUnknownProperty 5. merged/concat properties 6. transpiler ouput?!

more gotachas:

7. only halfway there

7. only halfway thereES Decorators

1 class Car { 2 +attr('gearsCount') 3 +attr('wheelsCount') 4 5 constructor(gearsCount) { 6 this.gearsCount = gearsCount; 7 } 8 9 -dependsOn('gearsCount') 10 get isModern() { 11 return this.gearsCount > 3; 12 } 13 } 14 15 var car = new Car(3); 16 car.isModern; // false

Aligning

1. provide legacy wrapper 2. use syntax as a carrot 3. private use can start sooner

strategy:

1 import EmberObject from "ember/object"; 2 import computed from "ember/computed"; 3 4 class Car extends EmberObject.extend({ 5 6 init(gearsCount) { 7 this._super(...arguments); 8 this.set('gearsCount', gearsCount); 9 }, 10 11 isModern: computed('gearsCount', function(){ 12 return this.get('gearsCount') > 3; 13 }) 14 }); 15 16 export default Car;

1 import EmberObject from "ember/object"; 2 3 class Car extends EmberObject { 4 5 constructor(gearsCount) { 6 super(...arguments); 7 this.gearsCount = gearsCount; 8 } 9 10 get isModern() { 11 return this.gearsCount > 3; 12 } 13 } 14 15 export default Car;

1 import Component from "ember/component"; 2 3 class Car extends Component { 4 5 get isModern() { 6 return this.attrs.gearsCount > 3; 7 } 8 } 9 10 export default Car;

This is a story of Ember 2.0 -> 3.0

Reminder: Standards are a two-way street

ONE MORE THING

201-created.com/ember-community-survey-2015

@ClimbingNarc

201-created.com/ember-community-survey-2015

201-created.com/ember-community-survey-2015

Thank you, you wonderful people.

@mixonic

Recommended