`You might not need
${framework}`
A Case for Vanilla
in the Browser
and micro-libraries
Let's Talk
Terms
first,
platform: whatever pre-existing environment a piece of computer software or code object is designed to run within, obeying its constraints, and making use of its facilities
bloat: a program being perceptibly slower, using more memory, disk space or processing power, or have higher hardware requirements than needed—whilst making only dubious user-perceptible improvements
cargo-culting: the ritual inclusion of code or program structures that serve no real purpose. …Copy some program code from one place to another with little or no understanding of how it works or whether it is required in its new position.
user-centric design: optimize the product around how users can, want, or need to use the product, rather than forcing the users to change their behavior to accommodate the product.
Do we ever cargo-cult code into new projects which contains bloat and that provides no end-user value?
Why Vanilla?
Let's Pretend....
- The web is the platform of accessibility
- We work for a global organization
- We need to reach ALL people
- Bandwidth costs money
- There are [mb]illions of people without fast Internet
- Success is measured by end-user experience
- Our products aren't super complex
- We have to work within end-user budgets
What value does `${framework}` provide?
- Quick and Easy Development *
- Abstract away browser complexities**
- Tested
- A common development platform***
- Other things end-user doesn't care about?
*restrictions apply (to every project ever)
value provided to developer, not end-user
**introduces tribal complexities instead
***if only there was already a platform...
So are `${frameworks}` bad?
No
But do you ALWAYS need one?
And do they come at a cost?
Budgets
end-user
Bandwidth Costs Money
Average Cost / Page
http://whatdoesmysitecost.com/
According to the August 15, 2015 run of HTTP Archive, the average site now weighs 2169kb
How do we compare?
Performance Budgets
https://developers.google.com/web/tools/profile-performance/evaluate-performance/rail?hl=en
- Response - 100ms to respond to user input before they notice a lag
- Animation - render frames every 16ms
- Idle - Use idle time to complete deferred work.
- Load - deliver content under 1000ms
The RAIL Performance Model
a user-centric performance model.
How much of your load budget does `${framework}` use?
Page Load Times -- One Page with:
no images / media, limited markup, just the core files of the following -- gzipped and minified
simulating 3G ~ 1MB/s, macbook pro, chrome
`${framework}` | load time -- no cache (% budget) |
load time -- cache (% budget) |
---|---|---|
jQuery | 364ms | 107ms |
Bootstrap JS | 143ms | 49ms |
Bootstrap CSS | 304ms | 77ms |
Bootstrap Glyphs | 135ms | 85ms |
Page | 747ms (74%) | 261ms (26%) |
`${framework}` | load time -- no cache (% budget) |
load time -- cache (% budget) |
---|---|---|
jQuery | 553ms | 65ms |
Bootstrap JS | 400ms | 69ms |
Bootstrap CSS | 400ms | 62ms |
Bootstrap Glyphs | 272ms | 50ms |
Angular Core | 733ms | 79ms |
Page | 847ms (85%) | 319ms (32%) |
Page Load Times -- One Page With:
no images / media, limited markup, just the core files of the following -- gzipped and minified
simulating 3G ~ 1MB/s, macbook pro, chrome
YMMV
- powerful "desktop" hardware
- in Chrome
- emulating "Good 3G"
- lab conditions
- no content
Platforms?
Browser (HTML, CSS, JavaScript, etc)
jQuery Core
jQuery Extensions
Bootstrap.JS
used code
bloat
Browser (HTML, CSS, JavaScript, etc)
Bootstrap Core CSS
Bootstrap Theme
used code
bloat
Browser (HTML, CSS, JavaScript, etc)
Angular Core
Angular Modules
used code
bloat
Browser (HTML, CSS, JavaScript, etc)
jQuery
jQ Plugin
jQ Plugin
jQ Plugin
jQ UI
Bootstrap JS
Angular
NG Module
NG Module
NG Module
NG Module
BS CSS
BS Theme
BS Glyphs
What's Missing?
Browser (HTML, CSS, JavaScript, etc)
jQuery
jQ Plugin
jQ Plugin
jQ Plugin
jQ UI
Bootstrap JS
Angular
NG Module
NG Module
NG Module
NG Module
BS CSS
BS Theme
BS Glyphs
my-app.js
my-app.css
app assets
Content
Browser (HTML, CSS, JavaScript, etc)
my-app.js
my-app.css
app assets
Content
so, is this possible?
Browser (HTML, CSS, JavaScript, etc)
my-app.js
my-app.css
app assets
Content
Is
this
really that bad...
jQuery
jQ Plugin
jQ Plugin
jQ Plugin
jQ UI
Bootstrap JS
Angular
NG Module
NG Module
NG Module
NG Module
BS CSS
BS Theme
BS Glyphs
...that we have to put all this in between?
"Blah Blah Browser Support"
Oh, you mean IE?
https://en.wikipedia.org/wiki/Usage_share_of_web_browsers
specifically old IE?
http://www.w3counter.com/globalstats.php?year=2015&month=8
Answer 1: Polyfills
How are Polyfills different than my `${framework}`?
freshness in TTRs (tm)
app lifecycle in days
dhtml
angular 1
polyfill
How fresh for an app released today (9/23/15)?
- DHTML
- NG1
- Native w/ Polyfill
TTR: time 'til refactor
Answer 2: maybe the game has changed?
Everything is Evergreen
Global Explosion of Smartphone / Mobile Usage
[imagine fancy chart]
ppl have modern devices with weak infrastucture
https://en.wikipedia.org/wiki/Global_Internet_usage
maybe infrastructure is
the new IE6?
statistically speaking
But... But... Content Editors
They're just gonna upload 30MB .tif files anyway
So why bother?
penny-pinching
just like IRL budgets, getting ahead is mostly about discipline &
unfortunately
not lottery-winning
How Vanilla?
1) The Basics
vs
Polyfill Loader
but first:
Hands On
https://ymnnf.app.lds.org/hands-on/polyfill/
https://ymnnf.app.lds.org/hands-on/polyfill/all.html
Basic Loader
function polyfill(isNeeded, src) {
if(isNeeded) {
var script = document.createElement('script');
script.setAttribute('src', src);
document.head.appendChild(script);
}
}
polyfill(typeof window.CustomEvent !== "function", 'polyfills/customevent.min.js');
$(someFunction);
aka: execute when the DOM is ready but before window.load
document.addEventListener('DOMContentLoaded', someFunction);
$('.selector')
Hands On
https://ymnnf.app.lds.org/hands-on/query-selector/
https://ymnnf.app.lds.org/hands-on/query-selector-all/
querySelector
- document.querySelectorAll('.selector) returns a NodeList
- get into habit of coercing it into Array
- Available on document and each element
- Returns first matching Element or null
- Always check if truthy before operating on results
- Available on document and each element
querySelectorAll
Support
Polyfill
IE6+
modern browsers & IE8+
References
https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector
https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelectorAll
https://developer.mozilla.org/en-US/docs/Web/API/element
.addClass()
.removeClass()
.toggleClass()
element.classList.add()
element.classList.remove()
element.classList.toggle()
Hands On
https://ymnnf.app.lds.org/hands-on/class-list/
Support
Polyfill
IE8+
modern browsers & IE10+
https://developer.mozilla.org/en-US/docs/Web/API/Element/classList
References
Bulk manipulation
jQuery's default behavior after $('.selector'). Also .each()
Also, how about item filtering?
jQuery's .filter(), .is(), eq(), etc.
Use built-in Array methods
[].map
[].filter
[].reduce
If you don't know them, then you're overdue...
https://feddlers.ldschurch.org/donuts.js/js/javascript/arrays/2015/03/17/javascript-fundementals-arrays-pt-2.html
https://feddlers.ldschurch.org/donuts.js/js/javascript/arrays/2015/02/25/javascript-fundementals-arrays-pt-1.html
Support
Polyfill
*
modern browsers & IE9+
Learn More
https://feddlers.ldschurch.org/donuts.js/js/javascript/arrays/2015/03/17/javascript-fundementals-arrays-pt-2.html
https://feddlers.ldschurch.org/donuts.js/js/javascript/arrays/2015/02/25/javascript-fundementals-arrays-pt-1.html
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array
.hide()
.show()
toggle()
.fadeIn()
Etc.
aka: toggling / animating item visibility
Hands On
https://ymnnf.app.lds.org/hands-on/item-visibility/
JavaScript: trigger state changes.
CSS: style states & transitions between them
Support
Polyfill
modern browsers & IE10+
IE8+
.on('ev', fn)
.addEventListener('ev', fn);
.trigger('custom', [data])
Hands On
https://ymnnf.app.lds.org/hands-on/custom-event/
new CustomEvent('custom', {detail: data})*
.dispatchEvent(customEvObj);*
+
*unless you want to know the internal workings, you should abstract away the details
Support
Polyfill
modern browsers
IE9+ with Polyfill*
IE9+
https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent
deferred & promise
Native Promise
Polyfill
All & IE9+
https://github.com/jakearchibald/es6-promise
$.get()
$.getJSON
Other AJAX
window.fetch()
Built-in Support
Polyfill*
Must Also Polyfill Promise
$.extend()
Object.assign()
Support
Polyfill
* with a little more effort, can be polyfilled further back as well
References
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
Much More
http://youmightnotneedjquery.com/
http://youmightnotneedjqueryplugins.com/
http://microjs.com/#
More to come...
- ES6/ES7 syntax & features
- Native Web Components
- Object.observe
Vanilla vs NG?
`You might not need${framework}`
By Jared Anderson
`You might not need${framework}`
- 1,527