EmberConf 2018 Notes

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 :birthday:
    • 5th anniversary of EmberConf!
  • Melanie Sumner is joining the core team :star:
  • Huge ecosystem of addons
  • Future: Don’t change the fundamentals, just build a better Ember :construction_worker:
    • This will be the focus of the 3.x series
      • Fewer Concepts
      • Latest JS
      • Optimize of Success
  • Ember features :sparkles:
    • New file system layout
      • Related files colocated (template.hbs, component.js)
    • Optional jQuery
      • 30kB filesize after minification and gzip
      • Drops out of the box Ember size by 1/5 :fire:
    • Simplified testing
      • async and await
      • Use custom codemods to fully automate the heavy lifting for the conversion
      • Mocha integration 1st class
    • 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 without tagName: '' hack
    • Setters
      • @tracked properties
      • Automatically infers dependencies on other Properties
      • No more dependent keys @tracked get slug() { }
    • Component arguments
      • this.args
      • {{@post.body}}
  • All of the above features are on Release, Beta, or Canary channels today! :trophy:
  • Request for Comments (RFCs) :speech_balloon:
  • 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
  • WebAssembly (WASM)
  • Ember has never been more technically advanced than it has been at this moment :zap:

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” :no_entry_sign:
  • Challenges in Ember :suspect:
    • 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
    • Passwords
  • The “easy” wins
    • Use semantic HTML5
    • Link vs. Button
      • Links for routes
      • Buttons for actions
    • Keyboard arrow-key navigation :arrow_up: :arrow_down: :arrow_left: :arrow_right:
    • 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 :family:
  • The Emberista sub-culture :hamster:
    • 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
  • RFCs :speech_balloon:
  • Ember Status Board
  • Ember Slack Community

The Next Generation of Testing - Tobias Bieniek

  • Async andThen() helper is no longer used :x:
    • 5 years old & unintuitive API
    • Replace with the promised based async / await :fire:
  • 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') and moduleForComponent('x-foo')module('x-foo') + setupTest(hooks);
    • RFC 268
      • moduleForAcceptance('Acceptance | login')module('Acceptance | login') + setupApplicationTest(hooks);
  • 4 main types of tests
    • :one: Plain QUnit test
      • Not Ember specific
    • :two: “Container” tests
      • For Controllers, Routes, Services…
      • Previously your unit tests
      • The ember-qunit setupTest(hooks) allows for APIs like this.owner inside the test()
    • :three: Rendering tests
      • Previously your component integration tests
      • setupRenderingTest(hooks)
        • Actually uses setupTest(hooks) under the hood
    • :four: Application tests
      • Previously your Acceptance tests
      • setupApplicationTest(hooks)
  • ember-cli-qunit > v4.2.0 allows you to use the new APIs
  • How to migrate all of my tests?
  • Mocking
  this.owner.register('service:cookies', Service.extend({}))
  this.owner.lookup('service:features')
  • Loading States
    • First, let promise = click('.submit') Notice: no await click()
    • Next, await waitFor('.loading-spinner')
      • Now you can do your assertions
    • Finally, await promise to finish the click
  • Custom test helpers
    • export async function addContact() { await FIllIn(); await click(); }
  • Test selectors
    • Use data attributes [data-test-title] instead of h2
    • 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 })

Say More - Jamie White

  • Make your tests say more :mega:
  • 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 :star2:
    • 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 :question:
    • RFC → Canary → Feature “Go” → convert addons → convert apps → deprecate
  • Module Unification - Ember’s new file system layout :sparkles:
    • Co-location for related files
    • Improved isolation for single-use components and helpers
    • Improved isolation of addon APIs
  • app.jsmain.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.jssrc/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 :page_facing_up:
  • Might be the first thing your user will see
  • Component Patterns / Data Management / User Experience / Accessibility
  • Design questions :question:
    • 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 and input 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
  • Data Management :bar_chart:
    • 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 :computer:
    • Always label your inputs with the for attribute <label for="foo"><input id="foo">
    • Use logical tabbing order

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 :snowflake:
  • 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!!!” :cold_sweat:
    • :raising_hand: “Well why don’t you just hire more engineers?”
    • It’s not always that easy… :no_good:
  • 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
  • :raising_hand: “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
  • :raising_hand: “But I’m used to Angular…”
    • Explaining the consistency of Ember vs the drastic deprecations of Angular
    • Shared ideas around Controllers, Routers, and Services
  • :raising_hand: “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 :rage2:
  • 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 :mortar_board:
    • 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 ____? :confused:
    • 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 :star2:
    GET /api/v1/contacts
    GET /api/v1/contacts/:contact:id
    
  • Lets build an app…Original plan: fetch + JSON
    • return this.fetch('api/v1/contacts')
  • A new requirement comes in… work offline
    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
      
  • 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 :electric_plug:
    • Data synchronization :arrows_counterclockwise:
    • Editing contexts
    • Undo/Redo
  • How does Orbit fit with Ember Data? :worried:
    • 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? :alien:
    • 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

Deep Dive on Ember Events - Marie Chatfield

  • Once works breaks the app :cold_sweat:
    • 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
  • :warning: Deep Dive!!! :warning:
    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 :exclamation:
  • 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? :confused:
    • Does not work: <div {{if isActive (action "handleClick")}}> :x:
    • Just use semantic HTML: <button {{action "handleClick"}} disabled={{isInactive}}> :white_check_mark:
    • Could also just use a DOM event listener <div onclick={{if isActive (action "handleClick")}}>:white_check_mark:
  • DOM Event listeners always fire before Ember event listeners! :exclamation:
  • Consistency and predictability are the most important things when handling events in Ember :exclamation:

Prying Open the Black Box - Godfrey Chan

  • Stack Trace: TypeError: Cannot read property 'get' of undefined :rotating_light:
  • Should be read top → bottom :arrow_double_down:
  • 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 :leftwards_arrow_with_hook:
    • “Step Into” button allows you to drill down into the implementation of the currently highlighted function :arrow_heading_down:
    • “Step Out” button allows you to pop back up into the previous stack frame :arrow_heading_up:
    • “Resume” button advances time until the next breakpoint :arrow_forward:
  • 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 :no_entry:
    • Great for bypassing specific internal Ember code within the stack trace
  • Breakpoints
    • Conditional breakpoints
    • XHR/fetch breakpoints
      • URL contains foo.json
    • 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

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 :boom:
  • {{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
  • Progressive Web App enhancements
  • Hybrid apps
  • Keeping (perceived) performance up :dash:
    • Async model hooks
      • Use ember-concurrency to make model hook async
      • Use loader component
  • Svelte list rendering
  • Demo App
  • ember-mobile-bar
  • ember-mobile-pane
  • ember-mobile-menu
  • ember-mobile-core