What's ahead for

(in ember-land)

Frontend-development is a fast moving field

Building apps of the complexity of SMHW was almost-unimaginable 5 years ago

Browsers weren't the amazing app-platforms they are today

git rev-list --max-parents=0 HEAD | xargs git show

Lets look back a bit

$ git rev-list --max-parents=0 HEAD | xargs git show
commit 24b2d93100fda2b412e5f385a218a1c5a49faa48
Author: Tomster <tomster@emberjs.com>
Date:   Sat Mar 21 23:14:28 2015 +0000

    Initial Commit from Ember CLI v0.2.0

                                                            _...,
                                                         ,:^;,...;
                  -+===;.         ,,--++====++-,,,     .:  /.....,
                :::::~+++++#:,+#++++++++++++++++++#*..:   /,......
               (,,,,,,::=+++##++++++++++++++++++++++#.   :....../
                ...,,,,,::++++++++++++++++++++++++++++++*..,...:
                *..+...,#@@@@@@@@@++++++++++++++++++++++#*....*
                  @#,;##############@@@+*+#@@@@@@@@@@#*++#..<
                  *@##@@+,-*^^^*-+@####@@@######@@@#####@@,,,+
                    @#@*            @#@@@@#@@+--*^^*--#@@@@@@#
                    @#@.    @#      @##+++@#,           .@@#@@
                     #@#    @@     +@@++++#@@     @@     :@@
                     :@#*         @#@++++++@#*    #@     @@+
                    :*+@@#;,.__.+@#@+,-^^.++@#          @@++
                   ;*  :*@@@##@@@@;++r._j^.+@##@+,.__,,@@++.
                  /*    ........+++++++++++++#@@@@@###@@#++++,
                ,:       ...,@@@#++===----==@@@####,,....+++++
               .:       ......@@##@\   ;   :@####@,,...... +++.
               ;       .........@###,   ;  ;xx#@;,,.....   *;+,
               |       ........,*;xxxx--^--=xxx,........   :+#;
               ;         ......,,;xxxxxxxxxxxxx;,.....     *+#
                ;          ......,::xxxx;.     ......       +.   .
                 *;            .........  +###  ....       / ,. /:| ,.
                   .+:             ...  ;##++##, .      ,#. (..v..;*./
                      **                ##  ###*    .:*&&&+. \.,....<,
                       #&+**==-..,,__  ;##  ###  :,*+&&&&&&&v+#&,,.._/
                      #&&&&*...,::,,.  ##; ,##* .*****;:&&&&&&&&&
                     ,+*+;~*..*** *.* ### ###* *******    *+#&;*
                                      ##,;##    ****    :,  **
             #####    ##   ###  ###,  ########       .#####   ;##  ##
            #######  ;##  #### ,###.  ##########    ########  ### ####
           ###  ###  ### ##########   ####  ####   ,##   ###  #######*
          ### ,###  ##############:   ##     ###  #### ,##   :#### ###  ##;
      ##########    ########### ##   .##    ,###  #######    ##### :######
        ######    .###### ####  ##   ###    ### ######*    :#####   ####
           #############  ####  ################    ######## ###
            #####*  *#*    #:   :###   *###*         *####    #*
+++ b/bower.json
@@ -0,0 +1,16 @@
+{
+  "name": "smhw-frontend",
+  "dependencies": {
+    "jquery": "^1.11.1",
+    "ember": "1.10.0",
+    "ember-data": "1.0.0-beta.15",
+    "ember-resolver": "~0.1.12",
+    "loader.js": "ember-cli/loader.js#3.2.0",
+    "ember-cli-shims": "ember-cli/ember-cli-shims#0.0.3",
+    "ember-cli-test-loader": "ember-cli-test-loader#0.1.3",
+    "ember-load-initializers": "ember-cli/ember-load-initializers#0.0.2",
+    "ember-qunit": "0.2.8",
+    "ember-qunit-notifications": "0.0.7",
+    "qunit": "~1.17.1"
+  }
+}

+++ b/package.json
@@ -0,0 +1,36 @@
+{
+  "name": "smhw-frontend",
+  "version": "0.0.0",
+  "description": "Small description for smhw-frontend goes here",
+  "scripts": {
+    "start": "ember server",
+    "build": "ember build",
+    "test": "ember test"
+  },
+  "devDependencies": {
+    "broccoli-asset-rev": "^2.0.0",
+    "ember-cli": "0.2.0",
+    "ember-cli-app-version": "0.3.2",
+    "ember-cli-babel": "^4.0.0",
+    "ember-cli-content-security-policy": "0.3.0",
+    "ember-cli-dependency-checker": "0.0.8",
+    "ember-cli-htmlbars": "0.7.4",
+    "ember-cli-ic-ajax": "0.1.1",
+    "ember-cli-inject-live-reload": "^1.3.0",
+    "ember-cli-qunit": "0.3.9",
+    "ember-cli-uglify": "1.0.1",
+    "ember-data": "1.0.0-beta.15",
+    "ember-export-application-global": "^1.0.2"
+  }
+}
+++ b/bower.json
@@ -1,18 +1,16 @@
 {
   "name": "smhw-frontend",
   "dependencies": {
-    "jquery": "^1.11.1",
-    "ember": "1.11.0-beta.5",
-    "ember-data": "1.0.0-beta.16",
-    "ember-resolver": "~0.1.12",
+    "jquery": "^2.1.3",
+    "ember": "1.12.0-beta.1",
+    "ember-data": "components/ember-data#canary",
+    "ember-resolver": "~0.1.15",
     "ember-load-initializers": "ember-cli/ember-load-initializers#0.0.2",
-    "ember-qunit": "0.2.8",
+    "ember-qunit": "0.3.0",
     "ember-qunit-notifications": "0.0.7",
-    "qunit": "~1.17.1",
-    "pretender": "~0.6.0",
-    "ember-inflector": "~1.3.1"
+    "qunit": "~1.17.1"
diff --git a/package.json b/package.json
index 76fa618..a57084f 100644
--- a/package.json
+++ b/package.json
@@ -19,21 +19,29 @@
   "devDependencies": {
-    "broccoli-asset-rev": "^2.0.0",
-    "ember-cli": "0.2.1",
-    "ember-cli-app-version": "0.3.2",
-    "ember-cli-babel": "^4.0.0",
-    "ember-cli-content-security-policy": "0.3.0",
+    "broccoli-asset-rev": "^2.0.2",
+    "ember-cli": "0.2.2",
+    "ember-cli-app-version": "0.3.3",
+    "ember-cli-babel": "^4.1.0",
+    "ember-cli-content-security-policy": "0.4.0",
     "ember-cli-dependency-checker": "0.0.8",
+    "ember-cli-deploy": "^0.4.1",
     "ember-cli-htmlbars": "0.7.4",
+    "ember-cli-i18n": "0.0.5",
     "ember-cli-ic-ajax": "0.1.1",
     "ember-cli-inject-live-reload": "^1.3.0",
-    "ember-cli-mirage": "0.0.23",
     "ember-cli-qunit": "0.3.9",
+    "ember-cli-mirage": "0.0.23",
     "ember-cli-sass": "^3.2.1",
+    "ember-cli-simple-auth": "^0.7.3",
+    "ember-cli-simple-auth-oauth2": "^0.7.3",
+    "ember-cli-simple-auth-testing": "^0.7.3",
     "ember-cli-uglify": "1.0.1",
-    "ember-data": "^1.0.0-beta.16",
+    "ember-data": "git://github.com/emberjs/data.git#master",
+    "ember-deploy-redis": "0.0.2",
+    "ember-deploy-s3": "0.0.3",
     "ember-export-application-global": "^1.0.2",
+    "ember-truth-helpers": "0.0.5",
     "smhw-ui": "https://npm.fury.io/CyQXZg9jSVsypJfpuZWZ/cibernox/smhw-ui/-/latest.tgz"
   }
$ git checkout b6038ca3f831d7d01171c551f5517771b3f061ee   # Sam's first commit
HEAD is now at b6038ca... Getting started pages

$ cloc app/ tests
     903 text files.
     847 unique files.
      66 files ignored.

github.com/AlDanial/cloc v 1.70  T=2.78 s (304.6 files/s, 11694.6 lines/s)
-------------------------------------------------------------------------------
Language                     files          blank        comment           code
-------------------------------------------------------------------------------
JavaScript                     607           2250            692          18910
SASS                            71            515             24           6407
Handlebars                     166            172              2           3456
HTML                             2              6              0             48
-------------------------------------------------------------------------------
SUM:                           846           2943            718          28821
-------------------------------------------------------------------------------

$ git checkout master
Switched to branch 'master'
Your branch is up-to-date with 'origin/master'.

$ cloc app/ tests/
    2335 text files.
    2169 unique files.
     174 files ignored.

github.com/AlDanial/cloc v 1.70  T=7.05 s (307.6 files/s, 21082.8 lines/s)
-------------------------------------------------------------------------------
Language                     files          blank        comment           code
-------------------------------------------------------------------------------
JavaScript                    1417           7662           1125          81260
SASS                           199           2341             45          29558
Handlebars                     548           1215              9          20778
CSS                              2            706             13           3824
HTML                             2             10              1             54
-------------------------------------------------------------------------------
SUM:                          2168          11934           1193         135474
-------------------------------------------------------------------------------
  • Chrome 24 was released with support to VP9 video
     
  • Safari was 6.2.0
     
  • Firefox was 36.0
     
  • Internet explorer had 20% of market share
     
  • Ember was 1.10 and supported IE8

Back then

  • Chrome 53 now uses Blink and has ~60% of share
     
  • Safari 10 has ful ES2016 support
     
  • Firefox is 50.0
     
  • Internet explorer has 9% of market share
     
  • Ember is almost 2.10 and thinking in dropping IE<11 support

Today

We have new challenges and new opportunities ahead

Challenge 1:

export default Ember.Component.extend({
  actions: {
    save(record) {
      this.set('loading', true);
      record
        .save()
        .finally(() => this.set('loading', false));

    }
  }
});

Who can see the problem with this code?

export default Ember.Component.extend({
  actions: {
    save(record) {
      this.set('loading', true);
      record
        .save()
        .finally(() => this.set('loading', false));
        // Error: Assertion Failed: calling set on destroyed object
    }
  }
});
<button {{action "save" record}} disabled={{loading}}>
  {{if loading 'Saving...' 'Save'}}
</button>
export default Ember.Component.extend({
  actions: {
    search(name) {
      return this.store.query('users', { name });
    }
  }
});

And with this?

{{#power-select search=(action "search") selected=student as |s|}}
  {{s.fullName}}
{{/power-select}}

Better async tasks with ember-concurrency

ember-concurrency is a small but powerful library that supplements Ember's existing tools and conventions for handling concurrency and asynchrony.

import { task } from "ember-concurrency";

export default Ember.Component.extend({
  save: task(function* (record) {
    yield record.save();
  }
});
<button {{perform "save" record}} disabled={{save.isRunning}}>
  {{if save.isRunning 'Saving...' 'Save'}}
</button>

Automatic derived state

import { task, timeout } from 'ember-concurrency';

export default Ember.Component.extend({
  search: task(function* (name) {
    yield timeout(500); // wait 500ms
    return this.store.query('users', { name });
  }).restartable();
});

Better primitives

{{#power-select search=(perform "search") selected=student as |s|}}
  {{s.fullName}}
{{/power-select}}

Simpler mindset

import Ember from 'ember';

const {
  Controller
} = Ember;

export default Controller.extend({
  isBooked: false,
  isPaying: false,

  actions: {
    pay(newBookingsPurchase) {
      let { isPaying, isBooked } = this.getProperties('isPaying', 'isBooked');
      if (!isPaying) {
        if (isBooked) {
          this._payForTutor();
        } else {
          newBookingsPurchase.save().then(this._payForTutor.bind(this))
                                    .catch(this._setErrors.bind(this));
        }
      }
    }
  },

  _setErrors(errors) {
    this.set('errors', errors);
  },

  _payForTutor(bookingsPurchase) {
    let payment = this.get('model');
    if (bookingsPurchase) {
      payment.set('bookingsPurchase', bookingsPurchase);
    }
    this.setProperties({
      isBooked: true,
      failMessages: [],
      failure: false,
      payment
    });
    payment.validate().then(({ validations }) => {
      if (validations.get('isValid')) {
        this.set('isPaying', true);
        payment.save().then(this._successfulPayment.bind(this))
                      .catch(this._paymentErrors.bind(this))
                      .finally(this._resetLoadingState.bind(this));
      } else {
        this.set('showErrors', true);
      }
    });
  },

  _successfulPayment() {
    this.transitionToRoute('authenticated.parent.bookings.confirmation');
  },

  _paymentErrors(error) {
    let failMessages = error.errors.map((error) => error.detail);
    this.setProperties({
      failure: true,
      failMessages
    });
  },

  _resetLoadingState() {
    this.set('isPaying', false);
  }
});

payTask: task(function* (newBookingsPurchase) {
  try {
    this.setProperties({ failMessages: [], failure: false });
    if (newBookingsPurchase.get('isNew')) {
      yield newBookingsPurchase.save()
    }
    let payment = this.get('model');
    payment.set('bookingsPurchase', newBookingsPurchase);
    let validations = yield payment.validate();
    if (validations.get('isValid')) {
      yield payment.save();
      this.transitionToRoute('tutor-finder.summary', payment)
    }
  } catch(e) {
    this.setProperties({ failure: true, failMessages: e.errors.mapBy('detail') });
  }
}).drop()

Challenge 2:


Update to Glimmer2

  • Initial render is between 2x and 3x faster.
     
  • Re-render is between 1.5x and 2x faster.
     
  • Templates are 5x smaller and much faster to parse
     
  • Glimmer components will be the way forward in Ember 3.0

Some facts

  • Glimmer2 is less forgiving with slow practices.
     
  • When glimmer components are out, bindings will be one way by default. We'll have to adapt.

Challenge 3:


Tame the scale beast

Let's look back again

$ git checkout b6038ca3f831d7d01171c551f5517771b3f061ee   # Sam's first commit
HEAD is now at b6038ca... Getting started pages

$ cloc app/ tests
     903 text files.
     847 unique files.
      66 files ignored.

github.com/AlDanial/cloc v 1.70  T=2.78 s (304.6 files/s, 11694.6 lines/s)
-------------------------------------------------------------------------------
Language                     files          blank        comment           code
-------------------------------------------------------------------------------
JavaScript                     607           2250            692          18910
SASS                            71            515             24           6407
Handlebars                     166            172              2           3456
HTML                             2              6              0             48
-------------------------------------------------------------------------------
SUM:                           846           2943            718          28821
-------------------------------------------------------------------------------

$ git checkout master
Switched to branch 'master'
Your branch is up-to-date with 'origin/master'.

$ cloc app/ tests/
    2335 text files.
    2169 unique files.
     174 files ignored.

github.com/AlDanial/cloc v 1.70  T=7.05 s (307.6 files/s, 21082.8 lines/s)
-------------------------------------------------------------------------------
Language                     files          blank        comment           code
-------------------------------------------------------------------------------
JavaScript                    1417           7662           1125          81260
SASS                           199           2341             45          29558
Handlebars                     548           1215              9          20778
CSS                              2            706             13           3824
HTML                             2             10              1             54
-------------------------------------------------------------------------------
SUM:                          2168          11934           1193         135474
-------------------------------------------------------------------------------

Our app is BIG

Certainly in the top 10% of biggest Ember apps in the world

Our users experience this

Ember-engines to the rescue

Engines allow multiple logical applications to be composed together into a single application from the user's perspective.

Students

Teachers

Parents

Admin teachers

Schools w/o some features

App skeleton

Public pgs

Shared components and addons

Students

Parents

Teachers

Unique addons

Unique addons

Unique addons

Unique addons

Admin area

Unique addons

More challenges

  • Leverage Service Workers: Precaching, push-notifications, preloading assets
     
  • Ember-animations. Take animations to the next level. Delight our users.
     
  • Great module unification
     
  • Project Svelte
     
  • Track project size over time.

Thanks

What's ahead for SMHW in frontand-land

By Miguel Camba

What's ahead for SMHW in frontand-land

  • 1,342