Here is a highlighted overview of the major points from some of my favorite EmberConf 2018 talks:
DAY 1
Opening Keynote - Yehuda Katz, Tom Dale
- Ember turns 7 in April
- 5th anniversary of EmberConf!
- Melanie Sumner is joining the core team
- Huge ecosystem of addons
- Future: Don’t change the fundamentals, just build a better Ember
- This will be the focus of the 3.x series
- Fewer Concepts
- Latest JS
- Optimize of Success
- This will be the focus of the 3.x series
- Ember features
- New file system layout
- Related files colocated (
template.hbs
,component.js
)
- Related files colocated (
- Optional jQuery
- 30kB filesize after minification and gzip
- Drops out of the box Ember size by 1/5
- Simplified testing
-
JS Modules
- Only import the modules you need
- Use codemods to fully automate this conversion process
- Treeshaking
- Editor integration
- Object model
- Computed properties
-
JS classes
-
@decorators
allows us to implement computed properties and services inside JS classes
-
-
JS Class fields
- Declare and initialize properties within the JS class body
- TypeScript
- Fragment components
- Remove the wrapping
<div>
elements on components withouttagName: ''
hack
- Remove the wrapping
- Setters
-
@tracked
properties - Automatically infers dependencies on other Properties
- No more dependent keys
@tracked get slug() { }
-
- Component arguments
this.args
{{@post.body}}
- New file system layout
- All of the above features are on Release, Beta, or Canary channels today!
-
Request for Comments (RFCs)
-
Angle bracket components
- single word component names
-
Named blocks
- Pass in more than 1 block into a single component
-
Angle bracket components
- Ember → GlimmerJS
- LinkedIn created two versions of the list route in Preact and GlimmerJS
- Glimmer performed slightly better
- Improving Glimmer VM
- Binary bytecode:
.hbs
→.gbx
bytecode - SSR (Server Side Rendering)
- Async rendering
- Repairing rehydration Ember Schedule App
- Binary bytecode:
-
WebAssembly (WASM)
- Run code at native speed in browsers
- In the process of converting low level code in Glimmer into WASM
- Ember Schedule App in WASM
- WASM2ASM for continued IE11 support
- Ember has never been more technically advanced than it has been at this moment
Ambitious for All: Accessibility in Ember - Melanie Sumner
- Accessibility: Making your web apps usable by people of all ability levels in the way it was designed to be used
- Web Standards
- WAI-ARIA
-
WCAG
- A, AA, & AAA conformance levels
- #a11y
-
Microsoft Azure video indexer
- Adjust the language model
- Image descriptions
- Ember A11y Project
- “Ship it now and we’ll fix it later”
- Challenges in Ember
- Route transitions
- Modals and popups
- Track the focus within the modal
- Shouldn’t be able to navigate outside of the modal
-
aria-*
attribute support - Click all the things
- Whatever you can do with a click, you should be able to do with a keyboard
- Nested interactive elements
- Passwords
- The “easy” wins
- Use semantic HTML5
- Link vs. Button
- Links for routes
- Buttons for actions
- Keyboard arrow-key navigation
- Color contrast
- Image
alt
attributes
- ember-component-attributes addon if you don’t want to go in and change your existing components
Everything they didn’t tell you about the Ember Community - Jessica Jordan
- Lots of identity around specific sub-cultures we create for ourselves
- The Emberista sub-culture
- Group within the larger JS community, often having beliefs or interests at variance with those of the larger culture
- Ember NPM downloads fairly stable over the last year (~300K/month)
- CLIs in other JS sub-cultures have a larger variance over the last year
- Addons for any use case
- Niche — Ember Pell
- Large scale — Ember Power Select
- RFCs
- Ember helped inspire React to implement RFC in December 2017
- Ember Status Board
- Ember Slack Community
The Next Generation of Testing - Tobias Bieniek
- Async
andThen()
helper is no longer used- 5 years old & unintuitive API
- Replace with the promised based
async
/await
- ember-native-dom-helpers uses native DOM API’s without jQuery
-
ember-native-dom-helpers
→@ember/test-helpers
- Both Mocha and QUnit allow nested modules inside tests
-
Grand Testing Unification
- Scope was initially way too big
- Core team extracted several smaller scoped RFCs out of these core ideas
-
RFC 232
-
moduleFor('x-foo')
andmoduleForComponent('x-foo')
→module('x-foo')
+setupTest(hooks);
-
-
RFC 268
-
moduleForAcceptance('Acceptance | login')
→module('Acceptance | login')
+setupApplicationTest(hooks);
-
- 4 main types of tests
-
Plain QUnit test
- Not Ember specific
-
“Container” tests
- For Controllers, Routes, Services…
- Previously your unit tests
- The ember-qunit
setupTest(hooks)
allows for APIs likethis.owner
inside thetest()
-
Rendering tests
- Previously your component integration tests
-
setupRenderingTest(hooks)
- Actually uses
setupTest(hooks)
under the hood
- Actually uses
-
Application tests
- Previously your Acceptance tests
setupApplicationTest(hooks)
-
Plain QUnit test
-
ember-cli-qunit
>v4.2.0
allows you to use the new APIs - How to migrate all of my tests?
- Migrate to
async
/await
- Use
ember-native-dom-helpers
- ember-qunit-codemod
- Rename
ember-native-dom-helpers
imports →ember/test-helpers
- Migrate to
- Mocking
this.owner.register('service:cookies', Service.extend({}))
this.owner.lookup('service:features')
- Loading States
- First,
let promise = click('.submit')
Notice: noawait click()
- Next,
await waitFor('.loading-spinner')
- Now you can do your assertions
- Finally,
await promise
to finish the click
- First,
- Custom test helpers
- export async function addContact() { await FIllIn(); await click(); }
- Test selectors
- Use data attributes
[data-test-title]
instead ofh2
-
ember-test-selectors
uses AST transform to strip test selectors out of productions builds -
qunit-dom
- Very readable assertions
assert.dom('input').exists({ count: 3 })
- Use data attributes
Say More - Jamie White
- Make your tests say more
- Ember’s testing toolkit is incredible
- Great tools so it’s even more important to ask questions of them
- What if we could impose access via accessibility through our UI testing
-
Rule of least power
- A less powerful and more constrained language
-
fillIn('input[name=title]')
→fillIn('Title')
- Test: Ensure the user wouldn’t have to tab backwards to get to the submit button
- Test: Ensure clicking submit works with a keyboard
-
await click()
→await keyboardClick()
-
- Test: Ensure the application made 1 atomic network request after clicking “Submit”
Who Moved My Cheese? Ember’s New Filesystem Layout - Matthew Beale
- Ember project is pretty good at big changes
- Deprecations
- Codemods
- Optional features
ember install @ember/optional-features ember feature:list ember feature:enable someFeature ember feature:disable someFeature
- How will core ship the new filesystem layout
- RFC → Canary → Feature “Go” → convert addons → convert apps → deprecate
- Module Unification - Ember’s new file system layout
- Co-location for related files
- Improved isolation for single-use components and helpers
- Improved isolation of addon APIs
-
app.js
→main.js
-
app/
→src/
- Tests can be colocated in the file system
src/data/models/user/model-test.js
- Styles can be colocated in the file system
src/ui/routes/sign-in/style.scss
-
src/ui/routes/${name}/route.js
↔src/ui/routes/${name}.js
- Local lookup
- Only able to access certain components for a specific file if they are nested in the file system layout
- Create a private interface
- Great for contextual components
-
Addon Namespaces
{{gadget-tools::gadget-list}} {{gadget-tools::list}} {{! shorthand }} {{gadget-tools}} {{! shorthand with `gadget-tools/src/ui/components/main/` filesystem }}
- double colon symbol means to now reference a helper or component from within the namespace
- Addon migration strategy
- Module Unification addons will play nice with Classic apps
fallback-resolver
-
Must run canary CLI today to generate a new layout application
npm install -g ember-cli/ember-cli MODULE_UNIFICATION=true ember new my-app
- ember-module-migrator to migrate an existing app to the new layout
Mastering the Art of Forms - Danielle Adams
- Forms are everywhere
- Might be the first thing your user will see
- Component Patterns / Data Management / User Experience / Accessibility
- Design questions
- What field type is this?
- Is this required?
- Is it dependent on another component?
- Does it supply functionality, UI elements, or both?
- Component Patterns
- Strategy: Combining your
label
andinput
into a single custom component-
<label>Thing</label><input>
→{{input/text-field}}
- Standardizes your API of the form elements
- Standardizes the UI of the various form elements across the app
-
-
Strategy: Contextual component form group
{{yield (hash questionText=(t 'radio-button-group.feeling-lucky') radioButtonGroup=(component 'radio-button-group options=radioOptions) luckyNumberInput=(component 'input/number-value' id='input.lucky-number' value=model.luckyNumber) ) }}
{{#form-group/lucky-number model=human as |formGroup|}} {{formGroup.questionText}} {{formGroup.radioButtonGroup}} {{formGroup.luckyNumberInput}} {{/form-group/lucky-number}}
- Same benefits as the first Strategy
- Reusable without being bound to their initial layout
- Components should fit together like a game of Tetris
- Strategy: Combining your
- Data Management
- Data required by the view should not hold up a page from rendering
- The component can be responsible for fetching data
willRender()
- Handle retries from the component
- User is able to interact with the app sooner
- Relative data is scoped within the component itself
- Validate data from the component level
- Is the element an
input
? You can probably use 2-way bindings
- User Experience & Web Accessibility
- Always label your inputs with the
for
attribute<label for="foo"><input id="foo">
- Use logical tabbing order
- Always label your inputs with the
How To Build A Bonfire: On Training and Hiring New Devs - Taylor Jones
- Ember isn’t exactly the first thing developers are running towards these days
- Unfortunately, Stability without stagnation doesn’t create a buzz
- How do you convince people outside of our bubble to come join us
- “We’ve gotta hire somebody!!!”
- “Well why don’t you just hire more engineers?”
- It’s not always that easy…
- First takeaway — Start small when developing a culture of teaching and learning
- How do we scale it?
- Foundations vs. Features
- How do we move on to helping our whole team become skilled at Ember?
- Newbies
- Teach JavaScript fundamentals along side Ember fundamentals
- Should be limited in exposure until they actually dive into Ember
- Veterans
- You may have a hard time ushering in Ember’s way of thinking
- Less impressionable and likely more opinionated
- Newbies
-
“But I’m used to React…”
- Emphasize common threads around the ideas of Components and the React Router
- Ember’s design patterns are much more structured
- No more webpack
-
“But I’m used to Angular…”
- Explaining the consistency of Ember vs the drastic deprecations of Angular
- Shared ideas around Controllers, Routers, and Services
-
“Well I used Ember 5 years ago…”
- A lot of Ember has stayed the same but a lot has changed and there are many new best practices
- Can be tempted to fall back on old knowledge of the framework
- The structure and opinions that Ember presents can be really hard for folks to adjust to
- Everyone isn’t going to love Ember as much as you do…and that’s ok!
Living Animation - Edward Faulkner
- Animation is actually kind of hard
- There’s overhead and cost associated with having to animate on-screen elements
- Using animations to teach and help guide your user’s attention
- Software developers are actually all teachers
- Teaching your users how to effectively use your app
- OS X minimization animation
- Ember Concurrency task documentation examples
- You don’t always need a library to animate
- CSS is very expressive for many use cases
- CSS transitions and animations
- liquid-fire
- Looking into “game-engine-inspired” principles
- Strong separation between app logic and animation layers
- Establish rules and let the motions emerge
-
Ember Animated
- “Glimmerization” of Liquid Fire
-
{{#animated-each}}
→{{#animated::each}}
-
{{#animated-if}}
→{{#animated::if}}
{{#animated-value}}
- Asymmetric easing functions
-
easeOut
when moving on screen (decelerate in) -
easeIn
when moving off screen (accelerate out)
-
-
Animated value
{{#animated-container}} {{#animated-value counter rules=rules duration=1000 as |v|}} <span>{{v}}</span> {{/animated-value}} {{/animated-container}}
- Once we get docs, we can go live and push for v1.0
DAY 2
The Future of Data in Ember - Dan Gebhardt
- The future of data in Ember is ____?
- Web standards?
- Ahead of standards?
- Realtime?
- RESTful?
- Graph-based?
- Operational?
- Offline?
- Ember needs to meet you where you are and get you where you need to be
GET /api/v1/contacts GET /api/v1/contacts/:contact:id
- Lets build an app…Original plan:
fetch
+ JSONreturn this.fetch('api/v1/contacts')
- A new requirement comes in… work offline
- Service workers
- ember-service-worker
ember install ember-service-worker ember install ember-service-worker-index ember install ember-service-worker-asset-cache ember install ember-service-worker-cache-fallback
- Offline works now
- Next Step: A new requirement comes in… add admin pages to edit
- Now update data layer to use Ember data
return this.get('store').findAll('contact')
GET /api/v2/contacts/ GET /api/v2/contacts/:contact_id POST /api/v2/contacts/ PATCH /api/v2/contacts/:contact_id DELETE /api/v2/contacts/:contact_id
- Now update data layer to use Ember data
- Final Step: A new requirement comes in… everything needs to work offline
- How do we allow apps to evolve with less friction?
- Augment capabilities incrementally
- Only increase complexity with an increased need for capabilities
-
JSON API
- 50+ client libraries
- 14 languages
- HTTP compliant basic CRUD → compound documents, sparse data sets → operations, local identities, profiles (v1.1)
- Composable, well-defined interfaces
- Monolithic full stack solution → interchangeable components
- Ember Data: Serve the needs of 80% of all Ember apps
- Evergreen behavior
- composability + interchangeability
- Currently — Tight coupling: Store ↔ Model
-
Ember Data Record RFC
- Formalize interface between Store and Model
- Store, models, basic CRUD → partial records, embedded records, changesets → offline, store forking, optimistic UIs
-
Orbit - Data access and synchronization library
- Offline (Optimistic UI)
- Pluggable sources
- Data synchronization
- Editing contexts
- Undo/Redo
- How does Orbit fit with Ember Data?
Orbit : Ember Data :: Glimmer : Ember
- Ember Data can provide Orbit’s capabilities in a convention-driven package
- Orbit and it’s ecosystem can provide a laboratory for experimentation
- Future?
- GraphQL usage will continue to grow… Apollo will continue to innovate
- REST+ solutions, like JSON API v1.1 will also grow
- Static analysis will improve runtime efficiency
- Immutable data structures will see increased internal usage (under the hood)
- Demand for offline PWAs will grow in order to compete with native apps
- Orbit will see continued growth across the frontend and in Node
Smartphone Symphony - Gavin Joyce
- ember-present - addon for creating presentations where the slides are ember components
- bit.ly/emberconf
Deep Dive on Ember Events - Marie Chatfield
- Once works breaks the app
- Only listening for events with Ember
<div {{action "toggle"}}> <div {{action "advanceTour" bubbles=false}}>Toggle Button</div> </div>
- If I add 1 word
onclick
: Now we have a combination of listening for events with Ember and the Native DOM
<div onclick={{action "toggle"}}> <div {{action "advanceTour" bubbles=false}}>Toggle Button</div> </div>
- Event propagation
- Every node’s parent has a chance to handle the bubbled event
-
event.stopPropagation()
on the child node will stop the default bubbling
- Ember Event listeners
{{action "clickMe"}}
- Abstraction on top of the native DOM event listeners
- Ember:
bubbles=false
=== DOM:event.stopPropagation()
- The parent-most element
<div class="ember-application">
is where Ember hooks into its event handlers -
Deep Dive!!!
- Ember’s event_dispatcher.js has the complete list of it’s default events
- Ember’s
setupHandler(rootElement, event, eventName, viewRegistry)
function call
for (event in events) { if (events.hasOwnProperty(event)) { this.setupHandler(rootElement, event, events[event], viewRegistry); } }
rootElement.on('${event}.ember', '.ember-view', function(event) { })
- So for example:
rootElement.on('click', '.ember-view', function() {})
will setup delegated event listeners on each.ember-view
in the DOM tree - Delegated event listener
- When an event happens on any children for the parent node, then the event will propograte up through the DOM tree to the delegated parent
- Allows us to reuse the same event handler throughout the lifecycle of our app
- Ember event listeners cannot
event.stopPropagation()
to DOM event listeners because the DOM event listeners have already been triggered by the time Ember has a chance to fire it’s handlers - Quick examples:
{{! DOM event listener (closure action) }} <div onclick={{action "handleClick"}}></div> {{! Ember event listener }} <div {{action "handleclick"}}></div> {{! Ember event listener }} {{some-component click=(action "handleClick")}}
- Pick one event listener strategy API and stick with it
- Ember events use more memory but have less overall DOM event listeners because of delegation
- DOM events use less memory but have more overall DOM event listeners due to no delegation
- Overall, speed is about the same for both
- Optionally add a listener?
- Does not work:
<div {{if isActive (action "handleClick")}}>
- Just use semantic HTML:
<button {{action "handleClick"}} disabled={{isInactive}}>
- Could also just use a DOM event listener
<div onclick={{if isActive (action "handleClick")}}>
- Does not work:
- DOM Event listeners always fire before Ember event listeners!
- Consistency and predictability are the most important things when handling events in Ember
Prying Open the Black Box - Godfrey Chan
- Stack Trace:
TypeError: Cannot read property 'get' of undefined
- Should be read top → bottom
- Clicking to the file in the stack trace, the browser will take you directly to the line where the error occurred
- “Pause on Exceptions” button will freeze the stack at a moment in time
- Allows us to use the console and sources tab to inspect at the exact moment an issue occurred
-
debugger;
snippet allows you to pause execution and inspect the state of your app- “Step Over” button allows you to go forward in time within the current stack frame
- “Step Into” button allows you to drill down into the implementation of the currently highlighted function
- “Step Out” button allows you to pop back up into the previous stack frame
- “Resume” button advances time until the next breakpoint
- Ember will often have a lot of items in the stack because it’s handling lots of things behind the scenes (like managing the run loop)
-
“Blackbox Script” Right click on any frame you don’t want to see, you will end up directly inside the super class implementation
- Great for bypassing specific internal Ember code within the stack trace
- Breakpoints
- Conditional breakpoints
- XHR/fetch breakpoints
- URL contains
foo.json
- URL contains
- Right click: “Continue to here”
- Right click: “Never pause here”
-
import { assert debug } from '@ember/debug';
- Stripped from production builds
-
{{debugger}}
in your templates - Ember inspector:
$E
sends the object to your console - Right click: “Show function definition”
-
$0
shows the currently highlighted element inside the console - Right click element: Break on > subtree modifications
EmberConf MiniTalks
- Thanks to all of the community contributors!
- Lightning deploy strategy with ember-cli-deploy
- ember-cli-deploy-lightning-pack
- Build → Deploy (Assets to S3/
index.html
blob to Redis) → Activate
- How can we share our documentation?
- ember-cli-addon-docs
- Goal: No-brainer for every addon author to use
-
broccoli-static-site-json
- Parse markdown and output JSON files
- ember-learn/deprecation-app
Creating fluid app-like experiences with Ember - Nick Schot
- Goal: Create an Ember app in the browser that performs as close to Native as possible
-
{{mobile-bar isLocked=false}}
- follows downward touch scroll
- collapses the top header on scroll down, reappears on scroll up
- Transitions with ember-animated
- Enhance perceived performance
- User experience
{{mobile-page}}
{{top-toolbar}}
- Managing scroll state
- Get restored when navigating up the route hierarchy
- Get reset when navigating back down the route hierarchy
- Responsiveness
-
ember-responsive
{{#if media.isMobile}}
- CSS Media Queries
- Use ember-responsive to disable or modify mobile transitions on Desktop
-
ember-responsive
- Progressive Web App enhancements
- Hybrid apps
- Keeping (perceived) performance up
- Async model hooks
- Use ember-concurrency to make model hook async
- Use loader component
- Async model hooks
- Svelte list rendering
- Demo App
- ember-mobile-bar
- ember-mobile-pane
- ember-mobile-menu
- ember-mobile-core