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,490