PLAIN WRONG?
$(foo)
$(foo)
"Is this PHP?"
The tri-arrow function
The tri-arrow function (AKA “the gun rack”), executes three times.
⇶
const booms = (boom = 'boom') ⇶ boom += ' ' + boom console.log(`${booms()} (I want you in my room)`)
(British Broadcasting Company)
I am not a JavaScript engineer.
But I don't have to be to write JavaScript.
PLAIN?
JQuery
JQuery
React
JQuery
React
Angular
JQuery
React
Angular
Vanilla?
vanilla == plain // true
UNCOMPOSED?
const a = document.querySelector(a);
const b = document.querySelector(b);
const c = document.querySelector(c);
const d = document.querySelector(d);
const e = document.querySelector(e);
const Ꮂ = n => document.querySelector(n)
Ꮂ('body').onclick = () => alert('wow!')
Honey and Candied Thyme?
const Ꮂ = n => document.querySelector(n)
Ꮂ('body').onclick = () => alert('wow!')
Helper
functions
Libraries /
frameworks
(that you copy/pasted from Stack Overflow)
(that you installed with npm)
INDEPENDENT!
Great for
interaction design
consultants
(like me!)
{{<demo>}}
<button aria-pressed="false">Toggle Me</button>
<style>
button {
border-width: 0 .25rem .25rem 0;
}
[aria-pressed="true"] {
border-width: .25rem 0 0 .25rem;
}
</style>
<script>
const toggle = document.querySelector('[aria-pressed]')
toggle.onclick = function () {
var pressed = this.getAttribute('aria-pressed') === 'true'
this.setAttribute('aria-pressed', !pressed)
}
</script>
{{</demo>}}
<button :aria-pressed="theState">Toggle me</button>
<button aria-pressed={theState}>Toggle me</button>
<button :aria-pressed="theState">Toggle me</button>
<button aria-pressed={theState}>Toggle me</button>
# Component name ## Recommended markup ## Recommended layout ## Recommended behavior ## Reference implementation
React
Design
System
React stuff only :-(
WEB COMPONENTS!
(plain / native)
<button is="toggle-button">Toggle me</button>
A universal toggle button...
import Toggle from '../components/Toggle.js'
<button
is="toggle-button"
pressed={foo}
ontoggle={bar}>
Toggle me!
</button>
<button
is="toggle-button"
:pressed="foo"
v-on:toggle="bar">
Toggle me!
</button>
<script src="js/components.js" type="module">
# Markdown
<%template%>
<html>
BEST PRACTICES
- Mirror attributes and props
- Emit custom events
get pressed() {
return this.hasAttribute('pressed')
}
set pressed(val) {
if (val) {
this.setAttribute('pressed', 'pressed')
this.setAttribute('aria-pressed', 'true')
} else {
this.removeAttribute('pressed')
this.setAttribute('aria-pressed', 'false')
}
}
get and set
Observed state
static get observedAttributes() {
return ['pressed']
}
attributeChangedCallback(name) {
if (name === 'pressed') {
const event = new Event('toggle')
this.dispatchEvent(event)
}
}
onToggle="console.log(this.pressed)"
elem.pressed = true
elem.setAttribute('pressed', 'pressed')
DO A LOT
WITH A LITTLE
JavaScript increase:
2011
2018
109 KB → 399 KB
- Transmission
- Decompression
- Parsing
- Compiling
(1MB median)
“As much as I love JavaScript, it’s always the most expensive part of your site.”
— Addy Osmani, Google
- Custom elements
- Native imports
- Vanilla CSS
(with custom properties + a bit of houdini)
"dependencies": {},
"devDependencies": {}
package.json 😱
"dependencies": {},
"devDependencies": {}
package.json 😱
demo?
Approx 35kb payload
- Not the JS bundle; everything
- Not initial; total
- Includes 24 web components
- Includes template parser
CLI | "Empty" production build |
---|---|
Vue CLI | 106KB |
Preact CLI | 37.5KB |
AI?
Drawing library?
probability(fraction) {
return Math.random() <= fraction
}
// TODO: A couple of for loops
Statefulness
function mutilator(obj, name = "m", context = window) {
const mutilated = {}
for (let prop in obj) {
let ref = `m-${prop}`
mutilated[ref] = obj[prop]
Object.defineProperty(mutilated, prop, {
set: function(v) {
this[ref] = v
context.dispatchEvent(
new CustomEvent(`${name}:${prop}`, {
detail: { value: v }
})
);
},
get: function() {
return this[ref]
}
});
}
return mutilated;
}
const mutable = mutilator({
string: 'foo',
num: 6,
etc: 'etc'
})
const mutable = mutilator({
string: 'foo',
num: 6,
etc: 'etc'
})
context.addEventListener('m:string', function(e) {
console.log(e.detail.value);
})
START WITH
NO JS
Progressive enhancement:
“Do stuff with JavaScript
if it's available”
“Do stuff with JavaScript
if it's available
AND YOU FUCKING NEED IT ”
Progressive enhancement:
<button is="toggle-button">Toggle me</button>
customElements.define(
'toggle-button',
ToggleButton,
{extends: 'button'}
);
HTMLButtonElement
Native buttons
already have:
- Implicit button role
- Focus capability
- Key bindings
- The disabled prop
- etc
Smooth scrolling with...
youscroll.js
fluid-scroll.js
Scroll.js
pfSmoothScroll.js
smoothScroll.js
js-navbar-scroll.js
moveTo.js
AnimateScroll.js
scrollmenu.js
scrollToAnchor.js
body {
scroll-behavior: smooth;
}
Or...
body {
scroll-behavior: smooth;
}
Unrecognized?
Just skipped over
Or...
Meanwhile: JavaScript's error handling
JavaScript
JengaScript
All
JS??
Just for this?
Static SSR >
SSR + Rehydration
Rendering On The Web
— Addy Osmani & Jason Miller
Can see the thing
Can actually use the thing
START
As long as 14 seconds!
Approx 200b IIFE, embedded: "Critical JavaScript"
interstitials
trackers
scrolljacking
self-rotating
carousels
Retweeted by... Brendan Eich
Inventor Of JavaScript
Thank you!
With special thanks to Tim Holman, Rob Dodson, Jason Miller, Nick Colley, Jen Simmons, Adam Silver, Christian Schaefer, Chris Ferdinandi, and Andy Bell for inspiration.
plain
By heydon
plain
- 2,165