In his The Elusive, Inclusive Web App talk at An Event Apart in Orlando FL 2014, Scott Jehl talked over building a complex Web application using the principles of progressive enhancement and universal access. Here are my notes from his talk:
- Native apps are exclusive by their nature. They are platform-dependent. Web apps have a distinct advantage because they provide access: the ability to reach as many people as possible.
- Despite this great advantage, we see companies build in more exclusive ways that limit access.
- How can we instead, build inclusively?
- Responsive design is defensive design, it allows you to defend your layouts against various screen and viewport sizes.
- As we try to optimize our code to work well across multiple devices, though, one size hits all. We need to be conscious about what and how we deliver our Web experiences.
Prioritizing Access & Performance
- If you want your app to work everywhere, start with functional HTML.
- To optimize your HTML for initial delivery, you need to consider the critical path: the moment from requesting a page to seeing it render in your browser.
- There's obstacles on the critical path, that we can influence. External references that link out to files, for instance, are blocking.
- Blocking is desirable in some cases and not in others. We want CSS to be blocking so pages get rendered only when the styles are present.
- First, we can lessen the weight of our assets. Minify, concatenate, and Gzip everything you can. This reduces the size of files and the number of requests.
- Webpagetest.org is a great tool for testing the critical path. Look at Start Render to determine when people can actually see a page.
- How can you get elements off the critical path?
- In the first round trip to the browser, we can stuff as much as possible in a 14KB round trip. Web pages load from the top down... load the code the renders the top first.
- What CSS do you need to load in order to render the top part of your page? Start with your original CSS, and extract just the amount that's critical using automatic tools like gruncritical-css.
- Once you have your critical CSS, place in-line in the header of your HTML. Ideally this should be 6-8KB in order to have the room for HTML and Javascript.
- You can also inline your critical Javascript, which may include feature tests, and HTML5 shiv, a file-loading function for additional assets, and conditional logic for loading files. Enhance.js is a workflow designed to progressively enhance sites, grab the file, delete what you don't need, and keep what you do.
- After you load the critical HTML, CSS, and Javascript in one file, you can asynchronously load additional assets to style the rest of the page and bring in additional Javascript.
- Shoestring is a simple DOM toolkit which uses a very small subset of jQuery but with the same syntax.
- Layer interactivity, don't replace it. Start with click, and layer on additional capabilities like touch. Tappy is a script that provides a single place to bind activity: mouse, keyboard, touch, etc.
Making Navigation Seamless
- Transitions between screens are difficult to pull-off on the Web as you need to cover a lot of things that the browser does by default.
- Ember, Backbone, React, and Angular tend to start with empty Body tags to manage the separation of concerns between model, view, and controller. But you can also render your apps on the server so people don't end with up empty content.
- Mustache can be parsed on the server to send an initial payload down to the client including a client-side parsing script. From that point on, you can re-render pages and parts of pages on the client.
- The complete process: API emits data in JSON; server combines JSON + mustache, outputs HTML; functional HTML is delivered to browser; CSS + JS add qualified visual and interactive enhancements; JS fetches all app data + templates; all further updates and navigation can be handled with JS
- Using history pushstate & popstate you can drive the different views to ensure the back button, deep links, all work offline.
- Taking things offline: start with the appcache file and list out the long-term content you want to store like fonts, images, etc. Local storage on the other hand is better for storing dynamic information like user data.