Ember-CLI as Compiler
What does that mean?
A bit about me
On the Ember Learning Team
When I'm not working, I'm often playing with my three sons
David Baker
@acorncom
Run an Ember consultancy in town
Some questions I hear regularly
Why are we doing a new folder structure?
When are we getting ES6 modules?
Why all the work on GlimmerJS?
Is Ember-CLI needed? Why not Webpack?
When are routable components coming?
Because Ember-CLI is becoming
a compiler for Ember apps
A compiler is computer software that ... translate[s] source code from a high-level programming language to a lower level language (e.g., assembly language, object code, or machine code) to create an executable program - Wikipedia
module.exports = {
browsers: [
'ie 9',
'last 1 Chrome versions',
'last 1 Firefox versions',
'last 1 Safari versions'
]
};
config/targets.js
// snipped ...
e.args=t.namedArgsSnapshot(),e.didUpdate()}getDestructor(t){return t.component}}
class ar extends Xi{}var or={
"component:/glimmer-testing/components/glimmer-testing":ar,
"template:/glimmer-testing/components/glimmer-testing":{
id:"Q5a4YIKw",
block:'{"symbols":[],"statements":[[6,"div"],[7],[6,"h1"],[7],[0,"Welcome to Glimmer!"],[8],[8],[0,"\\n"]],"hasEval":false}',
meta:{specifier:"template:/glimmer-testing/components/glimmer-testing"}
}
},
lr={app:{
name:"glimmer-testing",rootName:"glimmer-testing"},
types:{
application:{
definitiveCollection:"main"
},
component:{
definitiveCollection:"components"
},
"component-test":{unresolvable:!0},
helper:{definitiveCollection:"components"},
// snipped ...
<div><h1>Welcome to Glimmer!</h1></div>
Do we really need a compiler?
Code-splitting
app
├── controllers
| └── login.js
├── routes
| └── login.js
└── templates
└── login.hbs
Let's say we wanted to split this login route out separately ahead of time (AoT). How do we do it?
Files
app.js
Split
login.js
import Ember from 'ember';
import { task } from 'ember-concurrency';
export default Ember.Controller.extend({
session: Ember.inject.service(),
email: '',
password: '',
login: task(function * () {
// login using simple-auth
})
});
<form onsubmit=(perform login)>
<div>
{{input type="email" value=email}}
</div>
<div>
{{input type="password" value=password}}
</div>
{{snazzy-addon-component}}
<button type="submit">Login</button>
</form>
controller.js
Entire framework
template.hbs
Dynamically looked up
More dynamic lookups
"An SDK for the web"
- New folder structure
- ES6 Modules
- Glimmer
Projects in-flight
Disclaimer
Looking at tea-leaves, fortune telling is a dubious science (much like weather forecasting)
New app layout
aka new pods, new folder structure or module unification
src/ui
└── routes
├── application
│ └── template.hbs
├── index
| ├── controller.js
| ├── route.js
| └── template.hbs
└── posts
├── -components
│ ├── -utils
│ │ └── strings.js
│ ├── capitalize.js
│ └── titleize.js
└── post
└── -components
└── post-viewer
├── component.js
└── template.hbs
App benefits
- Now
- Co-located files/pods
- "local" components
- Future
- co-located tests
- co-located styles?
Framework benefits
- Now
- Stop using old/inefficient resolver
- Agree on formal rules for resolver as community
- Rules allow for a module map for framework use (more on this later)
- Later
- automated code-splitting by route
- other ideas I don't know about 😀
API changes cost a community
- Components
- Key Benefit: easier to reason about, cleaner API
- Cost: rewrite into components from views
- Long-term: avoiding rope to hang devs, more rigor for framework folks, clearer what could access
- Ember-CLI
- Key Benefit: add-ons, testing, Babel, ES6
- Cost: shift from globals -> modules
- Long-term: shift to shared tools as community
App devs | Framework devs | Long term | |
---|---|---|---|
New pods | Better organization | Agreed on file locations | ?? |
Key Benefit for
Big Picture
ES6 Modules
Can we get separate bundles like React/Webpack?
import Ember from 'ember';
export default Ember.Route.extend({
customService: Ember.inject.service(),
model() {
// normally Ember Data store
return this.get('customService').findPosts();
}
});
Currently
app/routes/index.js
ES6 module?
import Route from '@ember/routing/route';
import { inject as service } from '@ember/service';
export default Route.extend({
customService: service(),
model() {
// normally Ember Data store
return this.get('customService').findPosts();
}
});
Coming in 2.16
app/routes/index.js
True ES6 module
But how will this "shake"?
¯\_(ツ)_/¯ Some thoughts here, but not ironed out yet
App devs | Framework devs | |
---|---|---|
New pods | Better organization | Agreed on file locations |
Benefit for
Big Picture
import { default as __ui_components_my_app_component__ } from '../ui/components/my-app/component';
import { default as __ui_components_my_app_page_banner_component__ } from '../ui/components/my-app/page-banner/component';
import { default as __ui_components_my_app_page_banner_template__ } from '../ui/components/my-app/page-banner/template';
import { default as __ui_components_my_app_page_banner_titleize__ } from '../ui/components/my-app/page-banner/titleize';
import { default as __ui_components_my_app_template__ } from '../ui/components/my-app/template';
export default {
'component:/my-app/components/my-app': __ui_components_my_app_component__,
'component:/my-app/components/my-app/page-banner': __ui_components_my_app_page_banner_component__,
'template:/my-app/components/my-app/page-banner': __ui_components_my_app_page_banner_template__,
'component:/my-app/components/my-app/page-banner/titleize': __ui_components_my_app_page_banner_titleize__,
'template:/my-app/components/my-app': __ui_components_my_app_template__
};
App devs | Framework devs | |
---|---|---|
New pods | Better organization | Agreed on file locations |
Named imports | Clearer APIs | Statically analyze app |
Benefit for
Big Picture
Unlocks other options
- Per Route strategy
- https://github.com/ember-cli/rfcs/pull/110
- Other items in future?
Glimmer / GlimmerJS
These guys are really geeking out on the Comp Sci stuff, aren't they?
Warning: we're about to get into some Computer Science terms ...
What exactly are they doing?
What is Glimmer?
- GlimmerJS (view library)
- Glimmer (template compiler)
VM Compiler
Handlebars Template
AST (Abstract Syntax Tree)
IR (Intermediate Representation)
Bytecode (different forms, .gbx)
We iterate down from a high level to a very low-
level format that is more
efficient to pass around.
How does it run?
Compile time (CLI)
- Handlebars
- AST
- IR
Runtime (browser)
- IR JSON -> compiler ->app
Part of it built ahead of time (AoT) using Ember-CLI
- Pass the IR
- additional compiler
Part of it built up at runtime in the browser
The work we've been doing has been about putting in place requirements for staticness that, if met, mean we can
do linking at buildtime - @tomdale
How does it run?
Compile time (CLI)
- Handlebars
- AST
- IR
Runtime (browser)
- IR JSON -> app
Part of it built ahead of time (AoT) using Ember-CLI
- Pass the IR
- additional compiler
Part of it built up at runtime in the browser
In the Future
Compile time (CLI)
- Handlebars
- AST
- IR -> .gbx
Runtime (browser)
- .gbx -> app
Pass the .gbx file
We can now just run instead of doing a "linking" step in the browser first. Faster and smaller
There's one more thing ...
Caution: future-looking thoughts ahead
Rendering currently
Compile time (CLI)
- Handlebars
- AST
- IR -> .gbx
Runtime (browser)
- .gbx
- do an initial render
- shift to re-render/append mode
Pass the .gbx file
In the future
Compile time (CLI)
- Handlebars
- AST
- IR -> .gbx
Runtime (browser)
- .gbx file -> load app from HTML
- start in re-render/append mode
.gbx file
With Fastboot
Fastboot
- .gbx / app JS files
- do initial render to HTML
- send HTML / .gbx file? to browser
.gbx file?
HTML
References:
- https://twitter.com/chadhietala/status/908534322222764032
- https://github.com/glimmerjs/glimmer-vm/pull/631
- https://github.com/glimmerjs/glimmer-vm/pull/549
- https://twitter.com/tomdale/status/905479299964313604
The work we've been doing has been about putting in place requirements for staticness that, if met, mean we can do linking at buildtime - @tomdale
App devs | Framework devs | |
---|---|---|
New pods | Better organization | Agreed on file locations |
Named imports | Clearer APIs | Statically analyze app |
Glimmer improvements | Angle bracket components? | Unlock Glimmer optimizations? |
Benefit for
Big Picture
Code-splitting
app/src
└── ui
└── routes
└── login
├── controller.js
├── route.js
└── template.hbs
Let's say we wanted to split this login route out separately
Files
ES6 modules
login.js
Glimmer
Code-splitting
import Controller from '@ember/controller';
import { task } from 'ember-concurrency';
export default Controller.extend({
session: service(),
email: '',
password: '',
login: task(function * () {
// login using simple-auth
})
});
<form onsubmit=(perform login)>
<div>
{{input type="email" value=email}}
</div>
<div>
{{input type="password" value=password}}
</div>
{{snazzy-addon-component}}
<button type="submit">Login</button>
</form>
controller.js
ES6 module
template.hbs
Assume handled (details fuzzy for now)
Trouble
Code-splitting
Files
Glimmer
login.js
ES6 modules
Code-splitting
import Controller from '@ember/controller';
import { task } from 'ember-concurrency';
export default Controller.extend({
session: service(),
email: '',
password: '',
login: task(function * () {
// login using simple-auth
})
});
<form onsubmit=(perform login)>
<div>
{{input type="email" value=email}}
</div>
<div>
{{input type="password" value=password}}
</div>
{{snazzy-addon-component}}
<button type="submit">Login</button>
</form>
controller.js
template.hbs
Note we need these
And this
Ember-CLI's job
- Handles bookkeeping between steps
- Helps ensure static requirements met
- Helps get our app where we want it
Shifting toward static?
- Ember community's background in Ruby
- Objective C -> Swift
Ember-CLI: our secret weapon
- New folder structure
- ES6 modules
- Glimmer
Questions?
Ember-CLI as Compiler: what on earth does that mean?
By David Baker
Ember-CLI as Compiler: what on earth does that mean?
The Ember core team increasingly talks about Ember-CLI being a compiler. But what are they talking about and why? We'll look at a some key shifts in Ember-land that unlock some very interesting optimizations down the road.
- 765