Upgrade to Pro — share decks privately, control downloads, hide ads and more …

EmberFest: Building HackerNews.io as a Progress...

EmberFest: Building HackerNews.io as a Progressive Web App

High-performance Ember tuning with the HackerNews.io PWA.

Ivan Vanderbyl

October 12, 2017
Tweet

More Decks by Ivan Vanderbyl

Other Decks in Programming

Transcript

  1. Ember Fest new | show | ask | jobs |

    submit 1. Building the Progressive Web App for HackerNews.io in Ember (hackernews.io) 1337 points by ivanvanderbyl 41 minutes ago | flag | hide | 18 comments
  2. Talk Outline • Progressive Web App fundamentals • HackerNews PWA

    • Optimising the first view experience • Tips and tricks
  3. 1. Hacker News Top Stories, New Stories, Show HN, Ask

    HN, Jobs & threaded Comments. 2. Each of these should use routing to enable shareability. 3. App must display 30 items per-page for story list views 4. App must be a Progressive Web App 5. App must score over a 90/100 using Lighthouse 6. App must aim to be interactive in under 5 seconds on a Moto G4 7. App must use the Application Shell pattern 8. App is responsive on desktop and mobile 9. App must do its best to work cross-browser
  4. Reliable: Load instantly and never show the Downasaur, even in

    uncertain network conditions. Fast: Respond quickly to user interactions with silky smooth animations and no janky scrolling. Engaging: Feel like a natural app on the device, with an immersive user experience. Progressive Web App https://developers.google.com/web/progressive-web-apps/
  5. 1. Site is served over HTTPS 2. Pages are responsive

    on tablets & mobile devices 3. All app URLs load while offline 4. Metadata provided for Add to Home screen 5. First load fast even on 3G 6. Site works cross-browser 7. Page transitions don't feel like they block on the network 8. Each page has a URL https://developers.google.com/web/progressive-web-apps/checklist
  6. Service Workers + Metadata ember-cli-service-worker + ember-web-app All app URLs

    load while offline Metadata provided for Add to Home screen Pages are responsive on tablets & mobile devices, Site works cross-browser Each page has a URL, Page transitions don't feel like they block on the network Postcss + Browser Targets ember-cli-postcss + autoprefixer Ember Routing
  7. // app/models/item.js +export default Model.extend({ + by: attr(), + kids:

    attr(), + parent: attr(), + text: attr(), + time: attr(), + type: attr() +}); Building a working app, first pass // app/router.js Router.map(function() { + this.route('new'); + this.route('show'); + this.route('ask'); + this.route('jobs'); + this.route('about'); + this.route('item', { path: 'item/:item_id' }); });
  8. // app/route/index.js + model() { + let config = {

    + databaseURL: 'https://hacker-news.firebaseio.com' + }; + firebase.initializeApp(config); + + return new RSVP.Promise((resolve) => { + firebase.database().ref('v0/topstories').once('value', (snap) => { + let ids = snap.val(); + + resolve(RSVP.all(ids.slice(0, 20).map((id, index) => { + return new RSVP.Promise((resolve) => { + firebase.database().ref(`v0/item/${id}`).once('value', (snap) => { + let item = snap.val(); + item.position = index + 1; + resolve(item); + }); + }); + }))); + }); + }); + },
  9. The other components tl;dr • Date formatting: moment.js • Data

    loading: Ember Data + Firebase • Service Workers ◦ ember-cli-service-worker ◦ ember-service-worker-asset-cache ◦ Ember-service-worker-index • App Manifest: ember-web-app
  10. The point at which layout has stabilized, key webfonts are

    visible, and the main thread is available enough to handle user input developers.google.com/web/tools/lighthouse/audits/time-to-interactive
  11. Ember HN ? WebPageTest.com score for Time To Interactive “TTI”

    on a Moto G4/3G Connection — (Chrome with device emulation at 4x slowdown) React HN 4.1s
  12. Ember HN 12.5s WebPageTest.com score for Time To Interactive “TTI”

    on a Moto G4/3G Connection — (Chrome with device emulation at 4x slowdown) React HN 4.1s
  13. Ember HN 4.1s WebPageTest.com score for Time To Interactive “TTI”

    on a Moto G4/3G Connection — (Chrome with device emulation at 4x slowdown) React HN 4.1s
  14. How to remove jQuery: 1. Nullify vendorFiles.jquery 2. Delete “ember-ajax”

    from package.json 3. Install: ember-native-dom-event-dispatcher 4. Install ember-native-dom-helpers (for easier testing) 5. Install ember-fetch (to replace ember-ajax) 6. Optional: Run ember-native-dom-helpers-codemod which will fix all your codez.
  15. GET https://node-hnapi.herokuapp.com/news [ { "id": 15426983, "title": "Thoughts on Microsoft's

    Time-Travel Debugger", "points": 63, "user": "JoshTriplett", "time": 1507437139, "time_ago": "4 hours ago", "comments_count": 19, "type": "link", "url": "http://robert.ocallahan.org/2017/10/thoughts-on-microsofts-time-travel.html", "domain": "robert.ocallahan.org" }, ... ]
  16. import Ember from 'ember' import fetch from 'fetch' export default

    Ember.Route.extend({ apiHost: 'https://node-hnapi.herokuapp.com', page: 'news', model() { let pageUrl = `${this.get('apiHost')}/${this.get('page')}` return fetch(pageUrl).then(response => response.json()) }, setupController(controller, items) { controller.setProperties({ items }) } }
  17. Fundamental Truths about browsers • Single threaded execution • Maximum

    6-8 concurrent connections per domain on HTTP/1.1, virtually unlimited with H2. • Resources have priority • Script Streamer Thread • Service Workers • Tricks to change resource priority
  18. Main Thread DNS Connect TLS Download Parse Compile Execute Time

    Normal load order Script Streamer Thread Main Thread DNS Connect TLS Download Parse Compile Execute With async / defer attribute
  19. Main Thread Connect TLS Download With rel=dns-prefetch meta link DNS

    Main Thread DNS Connect TLS Download Normal request Main Thread Connect TLS Download With rel=preconnect meta link DNS Main Thread Connect TLS Download With rel=preload or rel=prefetch meta link DNS
  20. CSS is a render blocking resource. Get it to the

    client as soon and as quickly as possible to optimize the time to first render. https://developers.google.com/web/fundamentals/performance/critical-rendering-path/render-blocking-css
  21. Add a CDN (Content Delivery Network) A few good options:

    • S3 + CloudFront (what we use) • S3 + Cloudflare • S3 + fastly • Google Storage + Google CDN • Firebase Hosting + Google CDN
  22. Quick Recap 1. ember-cli-service-worker + ember-web-app 2. Use async and

    concat your assets, move parsing to separate Script Streamer Thread, 3. Preconnect or preload if possible 4. Inline your critical CSS 5. Inline service worker registration 6. Use a CDN 7. You can’t improve anything you can’t measure!
  23. Looking forward... 1. Glimmer binary templates and other rendering improvements

    already give you TTI in ≤5s on mobile, 2. Glimmer SSR + Rehydration should reduce the amount of time SSR has on TTFB, 3. Future Ember should automatically remove unused modules during compilation, 4. Will future Ember drop jQuery? 5. Sprite maps might help reduce asset requests,
  24. Ember HN 4.1s WebPageTest.com score for Time To Continuously Interactive

    “TTCI” on a Moto G4/3G Connection — (Chrome with device emulation at 4x slowdown) Glimmer HN 3.1s