Here is a highlighted overview of the major points from some of my favorite EmberConf 2020 talks:

DAY 1

Opening Keynote โ€“ Yehuda Katz, Jen Weber, Godfrey Chan

  • First ever all-virtual EmberConf ๐Ÿ’ป โšก ๐ŸŽ‰
  • There’s more to software than the number of lines of code you write
  • Value sustainability
  • Innovating on Community ๐Ÿค ๐Ÿ‘ช
  • Ember 1.13 had a large number of deprecations
    • Technically followed SemVer, but created lots of chaos…๐Ÿ˜ฐ
    • SemVer doesn’t tell the whole story of ecosystem stability
  • RFC Process (Started 2014 ๐Ÿ“…)
    • Driven by the community
    • Aid the core team with many perspectives
    • Collect constraints
    • Build relationships
    • Provide structure for implementation
    • Record history and rationale
  • RFC: Slack โ†’ Discord ๐ŸŒŸ
  • RFC: Website Redesign โœจ
  • Core teams โ†’ Diverse leadership
  • Togetherโ„ข
  • 2017: Ember framework began to feel like it was falling behind
  • Surviving the Framework Hype Cycle by Brandon Hays ๐Ÿ“บ
    • Settlers and Pioneers
    • Shipping features as low-level primitives and let the pioneers finalize the APIs
    • But when do settlers adopt?
  • 2019: Ember Editions
    • Collection of features
    • …and the settlers keep on working
  • Ember Octane
    • Fresh look for a new user ๐ŸŽŠ
      • 1️⃣ HTML-First Framework
        • Core of Ember is HTML and CSS
        • No special Ember-specific tweaks…Just copy paste ✂️
        • Components can simply be a natural extension of HTML โ†’ Driven by HTML and Templates
          • Template only components (Improved performance, no this in template) ๐ŸŽ๏ธ
      • 2️⃣ Integrating JavaScript
        • Old: Managing DOM ๐Ÿ˜ญ ๐Ÿ‘Ž โ†’ New: Managing Data ๐Ÿ˜† ๐Ÿ‘
        • JS file co-located next to your existing Template
        • Native JS syntax and idioms
        • this.args
        • get shareURL() { //... } โ†’ {{this.shareURL}} (JustWorksโ„ข in the template)
          • Autotracking: Auto-updates the getter if any passed-in this.args properties used in shareURL change
            • @tracked properties
            • Even works on Native JS classes
      • 3️⃣ Working with the DOM
        <button {{on "click" this.toggleSize}}></button>
        
        {{#if this.isLarge}}
          Large code...
        {{else}}
          Small code...
        {{/if}}
        
        import Component from '@glimmer/component';
        import { tracked } from '@glimmer/tracking';
        
        export default class MyComponent extends Component {
          @tracked isLarge = true;
        
          @action toggleSize() {
            this.isLarge = !this.isLarge;
          }
        }
        
        • Powerful, intuitive
        <input {{autofocus}} />
        
        export default class AutofocusModifier extends Modifier {
          didInstall() {
            this.element.focus();
          }
        }
        
    • Syntax and mental model overhaul
      • Shipped Dec 2019
      • Don’t have to rewrite apps to begin using features
      • Linting out of the box
      • Updated defaults when generating apps
      • Zero config builds
      • Refreshed guides
    • Create a new app โ†’ ember new
    • Paste in HTML and CSS โ†’ application.hbs
    • Fast deploy โ†’ Netlify
    • Incrementalism
    • Backwards compatibility
    • Interoperability between new and old paradigms
    • Codemods
    • Ember 2019-2020 Roadmap RFC
      • Invest in Octane
      • Modernize build system
      • Better accessibility by default
      • Share Octane outside our community
    • Building Ember Together ๐Ÿค
    • ember-inspector - Octane certified ๐Ÿฅ‡
    • Ember Twiddle - Octane certified ๐Ÿฅ‡

FastFlood: The Story of a Massive Memory Leak in FastBoot Land โ€“ Sergio Arbeo

  • Fastboot: Render Ember apps on the server
  • Memory leak: piece of data which should have been garbage collected โ™ป๏ธ
  • But Whyโ“
    • A reference is being kept somewhere
  • Chrome Developer tools ๐Ÿ› ๏ธ
    • Object memory graph - All objects in memory ๐Ÿ“Š
      • Distance - Distance from GC root
      • Shallow size - Size of the object itself
      • Retained size - Size we would free if we freed the object reference
    • Heap profile - Capture memory state at a point in time
      • Three snapshot technique to find the problem areas
        • 1️⃣ Warmup the application - Create baseline objects
        • 2️⃣ First snapshot
          • Now, do the suspected memory leak action
        • 3️⃣ Second snapshot
          • Now, repeat the action
        • 4️⃣ Third snapshot
  • Timeline tool
  • Step 0: Reproduce locally on a production-ish build (no uglification)
  • Step 1: Find the leak ๐Ÿ”Ž
    • Run the server with debugging enabled
    • Make one request
    • Start timeline
    • Make a few requests
    • Inspect
      class LeakDetect {
        constructor() {
          Object.assign(this, attrs);
        }
      }
      
  • Step 2: Find the dominator (retainer we need to remove so the leak is gone) ๐Ÿ”Ž
  • Container: used to instantiate and cache objects, associated with a Registry
  • Look for Owner leaking (public API of the Container)
  • Problem:
    export default Adapter.extend({
      headers: computed(function() {
        return {
          Authorization: `Bearer ${something.here}`;
        }
      })
    })
    
  • Fix:
    export default Adapter.extend({
      get headers() {
        return {
          Authorization: `Bearer ${something.here}`;
        }
      }
    })
    

Octane: A Paradigm shift in EmberJS โ€“ Suchita Doshi

  • The Journey of Ember ๐Ÿƒโ€โ™€๏ธ
    • Ember 1.x
      • Convention over configuration
      • Built-in routing
      • Ember Data
      • View driven architecture
      • Two way bindings ๐Ÿ”
      • Attribute bindings
    • Ember 2.x
      • Component driven architecture
      • Glimmer rendering engine adoption
      • Better binding with properties
      • Improved template scoping
      • “Data Down, Actions Up” approach
      • Roadmap for further improvements
    • Ember 3.x
      • Road to Octane
      • Cleanup
      • Remove IE9, IE10, PhantomJS and Bower
      • Native Classes
      • Angle Brackets
      • Lots of documentation
  • Evolution of Ember
  • Edition: Shift in programming model due to new framework features โœจ
  • Native Classes
    • Increased performance
    • Smooth learning curve
    • More aligned with JS community
  • Glimmer Components
    • Simple, Ergonomic, Declarative ๐Ÿ’ช
    • Fewer lifecycle hooks and properties to learn
    • Removed the implicit component wrapper
    • Namespaced arguments
  • Templating in Octane
      {{!-- Old --}}
      {{employee-details
        name=employeeName
        empId=employeeId
        addEmployee=(action "addEmployee")}}
    
      {{!-- New --}}
      <EmployeeDetails
        @name={{this.employeeName}}
        @empId={{@employeeId}}
        @addEmployee={{this.addEmployee}}
      />
    
  • Tracked Properties
    • No more this.set()
    • Reduce complexity
  • Modifiers and Decorators
  • ember-codemods
  • Ember Atlas

AST: the Secret Weapon to Transform a Codebase โ€“ Sophia Wang

  • How do I bulk edit syntax at scale?
    • Example: Wrap all requests with a global error handler
    • But we have a problem… Hundreds of requests scattered around the codebase
      • Update manually? ๐Ÿค”๐Ÿ˜ข Tedious and time consuming
      • Update with RegEx? ๐Ÿค”๐Ÿ˜ข Too inefficient for so many unique changes
      • Update with Codemods? ๐Ÿค”๐Ÿ˜†
  • Understanding the grammar behind a language
    • Apple === Noun
  • 1️⃣ Tools ๐Ÿ› ๏ธ
    • ESLint
      • Disallow unreachable code
        function foo() {
          let retVal = 1;
          return retVale;
          returnValue = 2; // <-- Unreachable code detected ts(7027)
        }
        
    • Codemod: Bulk edit syntax
    • Babel Transpiler: Write modern JS โ†’ Transpile โ†’ Run in any browser
      // Convert this
      [1, 2, 3].map((n) => n + 1);
      
      // To this
      [1, 2, 3].map(function(n) {
        return n + 1;
      });
      
  • 2️⃣ What is an Abstract Syntax Tree (AST)? ๐ŸŒณ
    • A Tree structure highlights the most important syntax of a language
    • Tree: Nodes connected by Edges
    • Heap Tree
    • Parse Tree
    • AST: Best parts of a Parse Tree (Structure) but only highlights the most important information
      • Remove extraneous information, Simpler
  • 3️⃣ How does syntax transformation work?
    • Parsing
      • Lexical analysis (Scanning/Tokenization)
      • Syntax analysis - AST Explorer (Includes Glimmer parser โœจ)
    • Transformation
    • Code Generation

Taming the Beast: Managing a really ambitious codebase โ€“ Luke Deniston

  • But this time I will build things the right way…
  • The Beast === Complexity
  • When we write code, we’re telling a story
    • Audience: Developers, Computers
  • Strategies for dealing with complexity
    • Abstracting
    • Subdividing (Systems โ†’ Subsystems)
  • Codebase v1: Coffeescript, Rails, Ember ๐Ÿ˜‘
    • Regressions with each upgrade
    • Performance degradation
  • Codebase v2: Shared addon and micro front ends ๐Ÿ˜‘
    • Solved some issues but full page refreshes when navigating from app to app
    • In-repo engines? Repo-mageddon
    • Fix bug in shared addon โ†’ 5-6 different cascading pull requests
  • Codebase v3: Mono repo - yarn workspaces with Ember Engines ๐Ÿฅณ
    • Workspaces: 1 repo, many packages
      • Packages can import each other
        {
          "private": true,
          "workspaces": ["packages/*"]
        }
        
      • Pro tip: Make individual package folder with the same name as the package.json name field
    • Engines: Mini application, built and booted by the host application
      • Optional lazy loading
      • Code isolation
      • Routable engine
        Router.map(function() {
          this.mount('super-blog');
        })
        
      • Routeless engine
        {{mount "super-blog"}}
        
      • Tests: Use the correct resolver ember-engines/test-support/engine-resolver-for
      • Sharing services
  • Controversial Tipsโ‰๏ธ
    • Replace this with your real tests โ†’ Treat this as a bug!
    • Use the last argument in tests .assert() to describe the test
    • Use Prettier and ESLint
    • Be careful with Addons (Actively maintained? File size bloat?)
    • Use TypeScript
    • Use Tailwind

Lessons Learned from Changing Careers โ€“ Kara Luton

  • Your past experiences make you the developer you are today ๐Ÿฅ‡
  • A non-traditional background is a feature, not a bug
  • What did I want in a new career?
  • Codecademy
  • Get a CS degree, self teach or go to a bootcamp?
  • The Iron Yard bootcamp
  • Overwhelming amount of information about HTML, CSS, and JS
  • Job rejections โ†’ Judged for not having experience ๐Ÿ˜ฉ
  • Lessons learned along the way (Ballerina โ†’ Music Publicist โ†’ Developer) ๐Ÿ‘ฉโ€๐ŸŽ“
    • Practice doesn’t make perfect, it makes progress ๐Ÿ“ˆโฌ†๏ธ
    • Pay attention to the small details
    • Accepting feedback and not taking it personally
    • My writing skills โ†’ Code commenting! ๐Ÿ’ช
    • How to work well with others
    • How to stand out amongst the crowd
    • Interviewing skills
  • Community is important
  • 37.6% of developer who have a college degree did NOT major in Computer Science
  • Look back on your own past experiences

Ember as Song โ€“ James C. Davis

  • How best to compare building an app with composing a song?
  • Programming and Songwriting are very similar ๐ŸŽถ โŒจ๏ธ
  • Song: composed of sections
  • Section: composed of instruments, notes, parts, measures, phrases
    • Section โ†’ Route
    • Instrument โ†’ Service
    • Part โ†’ Component
    • Notes โ†’ Contextual Components
  • Other globals: tempo, master volume, playing state, where are we in the timeline
  • Web Audio API: Powerful but low level. Provides primitives for making sounds
  • Tone.js: Built on top of the Web Audio API. Provides primitives for making music
  • Scale: string of notes, one after another

Democratizing Frameworks Through Developer Experience โ€“ Sarah Yu

  • Reach: Engineering apprenticeship program at LinkedIn
  • ember-m3: alternative model implementation to DS.model
  • What is developer experience (DX)?
    • Things that make developers’ lives easier
  • DX is often not prioritized ๐Ÿ˜ž
    • Involves people ๐Ÿ‘ฉโ€๐Ÿฆฐ๐Ÿ‘จโ€๐Ÿฆฐ
    • Metrics can be hard to measure ๐Ÿ“
    • Much easier to just say you reduced the build size by n Bytes
  • It’s a bug it that happens -Yehuda Katz
  • When should you contribute to DX?
    • Beginner: Getting started guides
    • Intermediate: Advanced APIs
    • Advanced: Self-documenting source code
  • Where can you contribute?
    • README.md
    • Ember Learning
    • Debugging tools
    • Source code comments

Why JS is Coming to Ember Templates โ€“ Matthew Beale

  • “No more unification RFCs” ๐Ÿ˜จ
  • <Welcome /> could live anywhere since resolvers are a runtime concern
  • Local maximum โ†’ Global maximum
  • Matt’s resolving Ember Microlib
    const template = [
      [0, 'To you I say:'],
      [1, 'welcome']
    ]
    setup();
    render(template);
    
  • rollup.js
  • terser
  • Dynamic resolution vs. static linking
    import { welcome } from './components'
    const template = [
      [0, 'To you I say:'],
      [1, welcome]
    ]
    render(template);
    
  • How can we bring the benefits of a statically linked system into Ember โ“
  • Handlebars Strict Mode ๐Ÿ’ช
  • What are the constraints in strict mode?
    • No implicit this fallback
    • No resolution. {{foo-bar}} is only ever a variable
    • No dynamic resolution. {{component foo}}
    • No partials
  • Need a static solution for getting other components into template scope.
  • createTemplateFactory({ "scope": () => [OtherComponent] })
  • Template imports
    • You can import a default of named export into your template
    • The right side of an import, the path, works just like it does in any system using Node.js resolution.
    • Adopt ES Modules syntax module syntax into templates
      ---
      import Quote from './quote';
      import { titleize} from '@ember/template-helpers';
      import { animatedEach } from 'ember-animated/helpers';
      ---
      {{#animatedEach @greetings as |myGreeting|}}
        To {{titleize this.subjectName}} I say: <Quote>{{myGreeting}}</Quote>
      {{/animatedEach}}
      
  • Next steps:
    • Get Handlebars Strict Mode into Final RFC and land the primitives
    • Build an addon for template imports so we can experiment
    • Start a design for what the ES module API is for built-ins like <LinkTo> or <Input>
  • Performance + Payload size benefits
  • Explicit templates
  • Strict mode for templates RFC

Solving Problems for African Soil โ€“ Ridhwana Khan

  • Kasi Maths
  • Why should you care?
  • Outline of challenges
    • Power/Electricity: Loadshedding and power outages (Rolling blackouts) ๐Ÿ”Œ
      • Plant breakdowns ๐Ÿญ
      • Poor cellphone reception
    • Basic digital literacy ๐Ÿ’ป
      • Reduced access to computers in public school and at home
    • High data costs ๐Ÿ’ฐ
    • Low end smartphones
    • Bandwidth speed
  • First Paint (Is it happening?) โ†’ First Contentful Paint โ†’ First Meaningful Paint (Is it useful?) โ†’ Time to Interactive (Is it usable?)
  • How can I help?

Shift Left โ€“ Melanie Sumner

  • Where did you start: Hobbyist? Computer Scientist degree? Coding Bootcamp? Self-taught?
  • Change is the constant we can rely on ๐Ÿ‘ˆ
  • Continuous learning is a must
  • Assistive technology is not included is most curriculums
  • Find your niche and grow
  • Think beyond
    • Enjoyable UX
    • No vision
    • Keyboard-only
    • Low vision
    • Accessibility settings
    • High contrast mode
  • What does a typical pattern look like? ๐Ÿงฉ
    • Basic examples
    • Variations
    • Rendered code
    • Copy & paste
  • Too many DOM nodes can crash screen readers
  • Patterns should also include anti-patterns
  • ember-template-lint
  • ember-a11y-testing
  • It’s ok to not know everything. Lean on tooling
  • Shift Left mindset: Intent matters
    • Accessible interfaces can used the way they were intended to be used
  • Don’t wait for the audit, move accessibility into the design workflow
  • Elevate the quality of your code
  • Technical Accessibility Issues for New Ember Apps RFC

DAY 2

Autotracking: Reactivity and State in Modern Ember โ€“ Chris Garrett

  • Reactivity: How apps update when things change
  • Autotracking is a form of reactivity
  • TodoMVC
  • How do we let the template know to when to update?
    • this.rerender() ๐Ÿ˜ญ
    • this.rerenderItem() ๐Ÿ˜ญ
  • Annotation overhead: All the extra thought that has to go into doing things the way the framework wants you to do them
    • Grows combinatorially with the size of our application ๐Ÿ˜จ๐Ÿ˜จ
    • jQuery
  • Reactivity can solve this by linearly increasing rate instead of exponentially increasing rate
  • Declarative programming model for updating based on changes to state
  • Declarative: “What, not how” โ—
    • HTML (Derived State)
  • State: All the things that can change in your app
    • Variables
    • Properties
    • User inputs
  • Root State
    firstName = 'Liz';
    
  • Derived State
    get fullName() {
      return `${this.firstName} ${this.lastName}`;
    }
    
  • Observable - RxJs
    • Observable โ†’ Events โ†’ Transform โ†’ Subscriber (Push-based)
    • Similar to classic Ember - set(), pushObject()
      allTodos = Observable.of([
        {
          title: 'Code',
          completed: false
        },
        {
          title: 'Plan EmberConf talk',
          completed: true
        }
      ]);
      
    • Performance++ / Ergonomics–
  • Virtual DOM - React
    • “Where did the state change occur?” (Pull-based)
    • Tree: Dirty โ†’ Rerender
    • Class based components
      state = {
        allTodos: [
          {
            title: 'Code',
            completed: false
          },
          {
            title: 'Plan EmberConf talk',
            completed: true
          }
        ]
      }
      
      this.setState({ allTodos }); // Specifically communicates "What" to the framework
      
    • Hooks
      let [allTodos, setTodos] = useState({
        allTodos: [
          {
            title: 'Code',
            completed: false
          },
          {
            title: 'Plan EmberConf talk',
            completed: true
          }
        ]
      });
      
      this.setState({ allTodos }); // Specifically communicates "What" to the framework
      
    • Performance–
    • useMemo / shouldComponentUpdate (manual optimization) โ†’ Scalability โฌ‡๏ธ โ†’ Complexity โฌ†๏ธ
  • Can we bend the curve? Performance++ and Annotation overhead–
  • Autotracking: Use the JS state model (Pull-based)
    • Focus on root state: Push to array, Add to object
      allTodos = new TrackedArray([
        {
          title: 'Code',
          completed: false
        },
        {
          title: 'Plan EmberConf talk',
          completed: true
        }
      ]);
      @tracked displaying = 'all';
      
    • Performance++ / Ergonomics++
    • Root State โ†’ Output
    • Memoization: Return a previously computed value if nothing changed
      memoizedRender(...args) {
        if (deepEqual(lastArgs, args)) {
          return lastResult;
        }
      
        lastResult = render(...args);
        lastArgs = args;
      
        return lastResult;
      }
      
    • Clock: state v0 โ†’ state v1 … โ†’ … state v15156;
    • Did the clock increment? Update
    • Tag: myClass.trackedProp โ†” state v15156 (last known clock when this was changed)
    • Simple / Performant
      • Dirty: Increment a number
      • Validate: Array.map + Math.max
      • Lazy (only checked on demand)
      • Only need to annotate root state
    • This is what bending the curve looks like
    • What’s next? ๐Ÿ”ฎ
      • Libraries, patterns, common abstractions - tracked-built-ins
      • Tooling - Ember Inspector state timeline
      • Extract to be used anywhere

An Octane-Powered JAM Stack โ€“ Chris Manson

  • JAM? JavaScript, APIs, Markup
  • Fast sites delivered by prerendering files and serving from CDN (Serverless)
  • Created by Netlify
  • Evolution of some of the things we were already doing
  • JAM Spectrum ๐Ÿ“
  • Server-side Rendering ๐ŸŽ๏ธ
  • Pre-rendering: Prember
  • JAM Lifecycle: Serve HTML โ†’ Load JS
  • Gatsby - $15M Funding ๐Ÿ’ฐ
  • VuePress
  • Empress
  • empress-blog Architecture
    • Host App (Ember) โ†” empress-blog (Broccoli) + empress-blog-template (Handlebars/CSS)
      npm uninstall empress-blog-casper-template
      npm install empress-blog-attila-template
      

A11y First and Everyone Wins โ€“ Ava Wroten

  • Adding Functionality with Composable Components
  • Equitable & Discoverable UX
  • Automation Testing
  • 15% of the world lives with some form on disability ๐ŸŒ
  • Degrees of disabilities ๐Ÿ•โ€๐Ÿฆบ
    • Limited mobility, Muscle slowness, Tremors, Low vision, Color blindness, Partial hearing loss
  • W3C Pattern Rearrangable Listbox
  • ember-sortable
    • <SortableGroup> โ†’ <SortableGroupAccessible> (wrapper)
    • <SortableItem> โ†’ <SortableItemAccessible> (wrapper)
  • Splattributes
    <SortableGroupAccessible
      tabIndex="0"
      class="border focus:border-teal-400"
    />
    
    <div ...attributes>
      {{yield}}
    </div>
    
  • Modifiers
    <div {{key-up this.handleArrowUp key="ArrowUp"}}></div>
    
  • @ember/test-helpers
    • triggerEvent and triggerKeyEvent
    • Test reordering and key events ๐Ÿ™Œ
    test('it can listen for specific key up events', async function() {
      this.keyUp = ({ key }) => {
        assert.equal(key, 'Enter');
        assert.step('key up');
      }
      await render(hbs`
        <div {{key-up this.keyUp data-test-id="keyup"}}></div>
      `)
      let selector = '[data-test-id=keyup]';
      await triggerKeyEvent(selector, 'keyup', 'Enter');
      assert.verifySteps(['key up']);
    });
    
    assert.dom(findAll('[data-test-id=item]')[0]).hasText('Item 1');
    assert.dom(findAll('[data-test-id=item]')[1]).hasText('Item 2');
    
    // Reorder
    await triggerEvent('[data-test-id=group]', 'focus');
    await click('[data-test-id=sort-down]');
    
    assert.dom(findAll('[data-test-id=item]')[0]).hasText('Item 2');
    assert.dom(findAll('[data-test-id=item]')[1]).hasText('Item 1');
    
  • Quick feedback loop

EmberQuest: Building an Octane Role Playing Game โ€“ Dan Monroe

  • ember new emberquest ๐ŸŽฎ
  • Hex tiles
  • Pathfinding
  • WebGL
  • Canvas
  • Web Audio
  • ember-concurrency
    @task 
    *reloadHealth() {
      // ...
    }
    
  • Phaser ๐Ÿ•น๏ธ
  • ember-phaser
    • ember install ember-phaser
    • ember generate phaser-scene tomster
    • ember generate service game
    • ember generate component gameboard

An Ember Dev’s Guide to CSS Grid โ€“ James Steinbach

  • Grid: Responsive CSS-only layout method
  • Column / Row / Gap control ๐Ÿค
  • Grid properties & values: grid-template-columns, grid-template-rows, fr, max-content, grid ๐Ÿ˜ฑ๐Ÿ˜จ
      display: grid;
      grid-template-columns: 1fr 40em 20em 1fr;
      grid-template-areas:
        "header header header  header"
        ".      body   sidebar .     "
        "footer footer footer  footer";
      gap: 12px 16px;
    
  • grid-template-columns: Set the proportions for tracks along the inline axis of the grid container
    • 30% 150px 30%;
  • grid-template-rows: Set the proportions for tracks along the block axis of the grid container
    • 50px repeat(10, 100px);
  • ๐Ÿšจ Warning ๐Ÿšจ Fixed heights cause overflow
    • Better: auto, min-content, max-content
  • Logical properties
    • inline: start to end of a line of text in the block
    • block: start to end of the block of text
  • dir=rtl and writing-mode: vertical-lr support for free
  • grid-template-areas: assign names to grid areas
    • One rectangle, adjacent cells, strings (not integers)
  • grid-template: assign rows, columns, and areas as a shorthand
    • Every row ends with its height
    • Every column ends with its width
      grid-template:
        "header header header  header" auto
        ".      body   sidebar .     " auto
        "footer footer footer  footer" auto /
        1fr     40em   20em    1fr;
    
  • gap: Creates gaps between columns and rows
  • Grid container values
    • fr: 1 fraction of the grids free space
      • Calculated after non-fr space is used
      • Based on the total number of fr in the row or column
    • repeat(<count>, <length>)
    • repeat(12, 1fr) === 12 column Bootstrap
  • grid-area: A grid-template-areas name from the parent
  • Center an item
      display: grid;
      justify-content: center;
      align-items: center;
    
  • Gotchas
    • Images sizes: img obeys a the grid-cell size โ†’ object-fit: cover
    • Animating grids: Some browsers animate, can’t animate between areas
    • IE 11 ๐Ÿ˜จ

Stronger App Architecture Using Maps โ€“ Matt Gardner

  • GIS (Geographic Information System) Mapping technology
  • NYC Planning ๐Ÿ“
  • Changing expectation about how governments deliver digital services
  • We use maps every day ๐Ÿ—บ๏ธ
  • ZoLa
    • Making data easy to consume
    • Where can we build Housing?
  • A brief history of maps
  • Basemap: Static data, always present
  • Data Layers: Polygons, Lines, Points
  • Enter…The Tile: Avoid triggering a fullpage reload when navigating
  • Dynamic interactions ๐Ÿ–ฑ๏ธ
  • How are tiles made?
    • Cylindrical map projection
    • Assume that the world is a square ๐ŸŸฆ
  • GeoJSON: Opinionated JSON format for storing spatial data
    • Best for most use cases
  • Leaflet
  • ember-leaflet
  • mapbox-gl-accessibility
  • ember-mapbox-gl
  • Test Stubs โ†’ Dependency Injection
  • How to lie with maps ๐Ÿคฅ
    • “Map users seldom, if ever, question these authorities, and they often fail to appreciate the map’s power as a tool of deliberate falsification or subtle propaganda.”
    • Spatial correlation !== Meaningful data relationship

The Power of Debugging โ€“ Samanta de Barros

  • Challenges
    • 1️⃣ Dev vs Prod
      • Sources tab
      • Breakpoints
      • Pretty print formatting for minified JS
    • 2️⃣ External Libraries
      • Stack trace โ›”
      • Don’t be afraid to step in ๐Ÿšถโ€โ™€๏ธ
      • Addon vs NPM library code location
    • 3️⃣ Not My Code
      • Use the Ember Inspector
      • Find the function location

Talking to Your Dog with Ember โ€“ Robert Wagner

  • wuf.plus ๐Ÿถ
  • Web Audio API
    • fftSize (Fast Fourier Transform) and frequencyBinCount
    • getByteFrequencyData()
    • getByteTimeDomainData()
  • Determining dog bark types ๐Ÿ•
    • ~1000-2000 Hz range and between ~80-90 dB (decibels)
    • Finding db spikes
    • Types: Alert, Greeting/Playful, Distress
  • Deciphering audio data ๐Ÿ”Š
      @action
      async startRecording() {
        const stream = await navigator.mediaDevices.getUserMedia({
          audio: true,
          video: false
        });
        const options = { mimeType: 'audio/webm' };
        this.mediaRecorder = new MediaRecorder(stream, options);
    
        this.mediaRecorder.addEventListener('dataavailable', e => {
          this.args.uploadAudioVideo({ blob: e.data });
        });
    
        this.mediaRecorder.start();
      }
    
  • Integration with Ember ๐Ÿน
  • Future work
    • Add more bark types
    • Refine frequency ranges
    • Add “Talk Back” feature

The Moderate Programmer โ€“ Derek Gavey

  • Moderate: Avoiding extremes of behavior
  • The moderate programmer names things appropriately
    • 3 words or less
    • Avoid jargon and metaphors factory, object, class
    • Use plurals where appropriate
    • For booleans, prefix with is, has, can
    • For functions, user a verb then noun
  • The moderate programmer writes small functions
    • Function does one thing
    • Beware of flags in arguments
    • Beware of too many arguments
    • Components are functions too
  • The moderate programmer writes tests
    • Write your tests immediately (or you won’t write them)
    • Integration tests are your best bet
    • You have diminishing returns after n% code coverage
  • The moderate programmer refactors
  • The moderate programmer gives up
    • Give up and ask for help
    • Give up and take a break ๐Ÿง˜
    • Give up and throw out your code…it’s ok

Why Contributing Seems Scary โ€“ Anne-Greeth van Herwijnen

  • Contributing ๐Ÿ™‹โ€โ™‚๏ธ
    • Everyone sees this differently
    • Add / Remove code
    • Setting up a meetup
    • Code review
    • Ideas
  • Motivation โ†’ Social Norms โ†’ Community
  • Motivation: Intrinsic / Extrinsic
  • Social Norms: Ask โ‰๏ธ โ†” Encouragement ๐Ÿ˜†
  • Community: Psychological sense of community โ†’ Commitment
  • What can we learn?
    • Thank every contributor ๐Ÿค—๐Ÿป
    • Ask people to contribute where their strengths are

Octane Octopus: The Multi-Faceted Migration โ€“ Jordan Hawker

  • Why is the migration experience important?
    • Past migration pains
    • Stability
    • Productivity
  • Can continue building new Octane feature while you’re migrating
  • Unlock new features quickly
  • Reduce manual refactoring costs
  • Minimize overhead of learning new patterns
  • Many features are polyfilled and stable back to 3.8
  • Recommendations
    • Phase 1: Upgrade to Ember 3.16 LTS
    • Phase 2: Codemods
    • Phase 3: Prepare for Glimmer
    • Phase 4: Adopt Glimmer
      • Preliminary component refactors
        • Empty tagName
        • Migrate classNames, classNameBindings, attributeBindings
        • {{on "click" (fn this.foo 'bar')}} event handlers
        • Modifiers
      • Finish Glimmer conversion
        • computed() / this.set() โ†’ @tracked
        • Convert lifecycle hooks
  • Classic vs Octane Cheat Sheet
  • Ember Atlas Recommended Migration Order