making modern websites

217
Making Modern Websites Patrick Kettner

Upload: patrick-kettner

Post on 19-Feb-2017

277 views

Category:

Software


0 download

TRANSCRIPT

Page 1: Making Modern Websites

Making Modern WebsitesPatrick Kettner

Page 2: Making Modern Websites

@PatrickKettner

Page 3: Making Modern Websites

@PatrickKettner

Page 4: Making Modern Websites

@PatrickKettner

Page 5: Making Modern Websites

@PatrickKettner

Page 6: Making Modern Websites

@PatrickKettner

Page 7: Making Modern Websites

Websites .

@PatrickKettner

Page 8: Making Modern Websites

Making Websites .

@PatrickKettner

Page 9: Making Modern Websites

Making Websites is Hard.

@PatrickKettner

Page 10: Making Modern Websites

srsly.

@PatrickKettner

Page 11: Making Modern Websites
Page 12: Making Modern Websites

Clipboard API

const

Cross-document messaging

Cross-Origin Resource Sharing

crypto.getRandomValues()

CSS Font Loading

CSS.supports() API

CustomEvent

DeviceOrientation & DeviceMotion events

Document Object Model Range

DOM Parsing and Serialization

ECMAScript 5

Element.getBoundingClientRect()

Element.insertAdjacentHTML()

ES6 Number

Fetch

FIDO U2F API

File API

FileReader API

Full Screen API

Gamepad API

Geolocation

getUserMedia/Stream API

Hashchange event

High Resolution Time API

IndexedDB

Input Method Editor API

KeyboardEvent.key

KeyboardEvent.location

MathML

MP3 audio format

MPEG-4/H.264 video format

Node.textContent

Ogg Vorbis audio format

Ogg/Theora video format

Opus

PNG alpha transparency

Public Key Pinning

querySelector/querySelectorAll

Referrer Policy

Resource Hints: dns-prefetch

Resource Hints: preconnect

Resource Hints: prefetch

Resource Hints: prerender

Server Name Indication

Shadow DOM

Strict Transport Security

Upgrade Insecure Requests

WAI-ARIA Accessibility features

Wav audio format

WebM video format

Window.devicePixelRatio

WOFF - Web Open Font Format

WebGL - 3D Canvas graphics

Offline web applications

All HTML5 features

Other

AAC audio file format

asm.js

async attribute for external scripts

autocomplete attribute: on & off values

Brotli Accept-Encoding/Content-Encoding

Client Hints: DPR, Width, Viewport-Width

Content Security Policy 1.0

Content Security Policy Level 2

Data URIs

defer attribute for external scripts

document.head

DOMContentLoaded

ECMAScript 5 Strict Mode

Element.closest()

EventTarget.addEventListener()

EventTarget.dispatchEvent

getComputedStyle

HTTP/2 protocol

JPEG 2000 image format

JPEG XR image format

KeyboardEvent.code

KeyboardEvent.getModifierState()

meter element

Minimum length attribute

Multiple file selection

New semantic elements

Number input type

Pattern attribute for input fields

Picture element

PNG favicons

progress element

Range input type

relList (DOMTokenList)

Reversed attribute of ordered lists

Ruby annotation

sandbox attribute for iframes

Scoped CSS

seamless attribute for iframes

Search input type

Session history management

Spellcheck attribute

srcdoc attribute for iframes

Srcset attribute

Subresource Integrity

Text API for Canvas

Toolbar/context menu

Video element

Video Tracks

wbr (word break opportunity) element

Audio Tracks

Autofocus attribute

Canvas (basic support)

Canvas blend modes

classList (DOMTokenList)

Color input type

contenteditable attribute

Custom Elements

Custom protocol handling

Datalist element

dataset & data-* attributes

Date and time input types

Details & Summary elements

Dialog element

disabled attribute

Download attribute

Drag and Drop

Email, telephone & URL input types

Form attribute

Form validation

getElementsByClassName

hidden attribute

HTML Imports

HTML templates

HTML5 form features

input event

input placeholder attribute

letter-spacing CSS property

Media Queries: interaction media features

Media Queries: resolution feature

rem (root em) units

text-decoration styling

text-emphasis styling

TTF/OTF

Viewport units: vw, vh, vmin, vmax

:placeholder-shown CSS pseudo-class

Crisp edges/pixelated images

Backdrop Filter

Canvas Drawings

Cross-Fade Function

font-smooth

image-set

Logical Properties

Motion Path

pointer-events (for HTML)

position:sticky

Reflections

text-size-adjust

text-stroke

zoom

Improved kerning pairs & ligatures

All CSS features

accept attribute for file input

Audio element

Background-image options

Border images

Border-radius (rounded corners)

Box-shadow

Box-sizing

Colors

Cursors (original values)

Cursors: zoom-in & zoom-out

font-kerning

image-orientation

Media Queries

Multiple backgrounds

Multiple column layout

object-fit/object-position

Opacity

Overflow-wrap

selectors

tab-size

text-align-last

Text-overflow

Text-shadow

Transitions

word-break

OM Scroll-behavior

Flexible Box Layout Module

Font unicode-range subsetting

Intrinsic & Extrinsic Sizing

font-stretch

font-variant-alternates

Generated content

Gradients

Grid Layout

Hyphenation

initial value

inline-block

Masks

min/max-width/height

outline

page-break properties

position:fixed

Regions

Repeating Gradients

resize property

Scroll snap points

Shapes Level 1

Table display

touch-action property

unset value

user-select: none

Variables

will-change property

writing-mode property

2D Transforms

3D Transforms

::first-letter CSS pseudo-element selector

::placeholder CSS pseudo-element

::selection CSS pseudo-element

@font-face Web fonts

Blending of HTML/SVG elements

calc() as CSS unit value

2.1 selectors

all property

Animation

Appearance

background-attachment

background-blend-mode

background-position edge offsets

box-decoration-break

clip-path property

Counter Styles

Counters

currentColor value

Device Adaptation

element() function

Exclusions Level 1

Feature Queries

Filter Effects

filter() function

font-feature-settings

font-size-adjust

WOFF 2.0 - Web Open Font Format

XHTML served as application/xhtml+xml

Animated PNG (APNG)

EOT - Embedded OpenType fonts

KeyboardEvent.charCode

KeyboardEvent.which

Node.innerText

Resource Hints: Lazyload

SPDY protocol

WebP image format

WebVTT - Web Video Text Tracks

XHTML+SMIL animation

All Other features

SVG

Inline SVG in HTML5

SVG (basic support)

SVG effects for HTML

SVG favicons

SVG filters

SVG fonts

SVG fragment identifiers

SVG in CSS backgrounds

SVG in HTML img element

SVG SMIL animation

All SVG features

JS API

Ambient Light API

Arrow functions

Base64 encoding and decoding

Battery Status API

Beacon API

Blob constructing

Blob URLs

BroadcastChannel

Channel messaging

Internationalization API

JSON parsing

let

matches() DOM method

matchMedia

maxlength attribute for input and textarea elements

Media Source Extensions

Mutation Observer

Navigation Timing API

Object RTC (ORTC) API for WebRTC

Online/offline status

Page Visibility

PageTransitionEvent

Pointer events

PointerLock API

Promises

Proximity API

Proxy object

requestAnimationFrame

Resource Timing

Rest parameters

Screen Orientation

Server-sent events

Service Workers

Shared Web Workers

Touch events

Typed Arrays

User Timing API

Vibration API

Web Animations API

Web Audio API

Web Cryptography

Web MIDI API

Web Notifications

Web Sockets

Web Storage - name/value pairs

Web Workers

WebRTC Peer-to-peer connections

XMLHttpRequest advanced features

Basic console logging functions

Document.execCommand()

Efficient Script Yielding: setImmediate()

Filesystem & FileWriter API

Network Information API

Object.observe data binding

Permissions API

Speech Recognition API

Speech Synthesis API

Web SQL Database

Page 13: Making Modern Websites

@PatrickKettner

Page 14: Making Modern Websites

@PatrickKettner

Page 15: Making Modern Websites

tools .

@PatrickKettner

Page 16: Making Modern Websites

@PatrickKettner

Page 17: Making Modern Websites

@PatrickKettner

Page 18: Making Modern Websites

Second most used lib

@PatrickKettner

Page 19: Making Modern Websites

@PatrickKettner

Page 20: Making Modern Websites

@PatrickKettner

Page 21: Making Modern Websites

commit a9a90192ea11dc0ff916431b40227734af9074b6

Author: Patrick Kettner <[email protected]>

Date: Fri Sep 11 18:59:17 2015 -0700

release 3.0

@PatrickKettner

Page 22: Making Modern Websites

@PatrickKettner

Page 23: Making Modern Websites

{{months of work}}

@PatrickKettner

Page 24: Making Modern Websites

@PatrickKettner

Page 25: Making Modern Websites

no one cares.

@PatrickKettner

Page 26: Making Modern Websites

(other than me)

@PatrickKettner

Page 27: Making Modern Websites

at best,we don’t get in the way

@PatrickKettner

Page 28: Making Modern Websites

we are just a pitstop

@PatrickKettner

Page 29: Making Modern Websites

we still need tomake users happy

@PatrickKettner

Page 30: Making Modern Websites

how?

@PatrickKettner

Page 31: Making Modern Websites

make itreally, really fast

@PatrickKettner

Page 32: Making Modern Websites

@PatrickKettner

Page 33: Making Modern Websites

@PatrickKettner

Page 34: Making Modern Websites

@joecritchley

Page 35: Making Modern Websites

@PatrickKettner

Page 36: Making Modern Websites

@font-face

@PatrickKettner

Page 37: Making Modern Websites

@PatrickKettner

Page 38: Making Modern Websites

@PatrickKettner

Page 39: Making Modern Websites

the site works, itjust looks broken

@PatrickKettner

Page 40: Making Modern Websites

@PatrickKettner

Page 41: Making Modern Websites

document.fonts.ready.then(() => { let body = document.body body.classList.toggle("fontzL0ad3d")});

@PatrickKettner

Page 42: Making Modern Websites

body { font-family: 'T0t411y-R4D-Sans', 'Helvetica', 'Sans-Serif'}

@PatrickKettner

Page 43: Making Modern Websites

body { font-family: 'Helvetica', 'Sans-Serif'}

body.fontzL0ad3d { font-family: 'T0t411y-R4D-Sans'}

@PatrickKettner

Page 44: Making Modern Websites

@PatrickKettner

Page 45: Making Modern Websites

@PatrickKettner

Page 46: Making Modern Websites

@PatrickKettner

Page 47: Making Modern Websites

@PatrickKettner

Page 48: Making Modern Websites

FontFaceObserver

@PatrickKettner

github.com/bramstein/fontfaceobserver

Page 49: Making Modern Websites

document.fonts.ready.then(() => { let body = document.body body.classList.toggle("fontzL0ad3d")});

@PatrickKettner

Page 50: Making Modern Websites

@PatrickKettner

let observer = new FontFaceObserver("T0t411y-R4D-Sans");

observer.check().then(() => { let body = document.body body.classList.toggle("fontzL0ad3d")});

Page 51: Making Modern Websites

@PatrickKettner

Page 52: Making Modern Websites

@PatrickKettner

Page 53: Making Modern Websites

December 1, 2015@PatrickKettner

Page 54: Making Modern Websites
Page 55: Making Modern Websites

@PatrickKettner

Page 56: Making Modern Websites

@PatrickKettner

Page 57: Making Modern Websites

@PatrickKettner

Page 58: Making Modern Websites

@PatrickKettner

Page 59: Making Modern Websites

@PatrickKettner

observer.check().then(() => { localStorage.setItem("fontzL0ad3d", true)});

Page 60: Making Modern Websites

if it is cached properly

@PatrickKettner

Page 61: Making Modern Websites

and the user didn’t clear part of the cache

@PatrickKettner

Page 62: Making Modern Websites

and the browser didn’t automatically remove it

@PatrickKettner

Page 63: Making Modern Websites

this was alwaysan educated guess

@PatrickKettner

Page 64: Making Modern Websites

ServiceWorker

@PatrickKettner

Page 65: Making Modern Websites

kindof a big deal...

@PatrickKettner

Page 66: Making Modern Websites

@PatrickKettner

Offline ExperiencesPush NotificationsBackground Syncand much, much more...

Page 67: Making Modern Websites

@PatrickKettner

FetchCache

- Network Proxy- Programmable Cache

Page 68: Making Modern Websites
Page 69: Making Modern Websites

@PatrickKettner

Page 70: Making Modern Websites

259 modules

@PatrickKettner

Page 71: Making Modern Websites

single module =dozens of requests

@PatrickKettner

Page 72: Making Modern Websites

ServiceWorker?

@PatrickKettner

Page 73: Making Modern Websites

navigator.serviceWorker.register('/serviceworker.js')

@PatrickKettner

Page 74: Making Modern Websites

let CURRENT_CACHE = { prefetch: 'prefetch-cache-v1'};

self.addEventListener('install', event => { let prefetch = ['/T0t411y-R4D-Sans'] event.waitUntil(caches.open(CURRENT_CACHE['prefetch']) .then(cache => cache.addAll(prefetch.map((url) => new Request(url, { 'mode': 'no-cors' }) )) ) )})

@PatrickKettner

Page 75: Making Modern Websites

self.addEventListener('fetch', event => { event.respondWith(caches.match(event.request) .then((response) => { if (response) { return response; } return fetch(event.request) .then(response => response); }));});

@PatrickKettner

Page 76: Making Modern Websites

@PatrickKettner

Page 77: Making Modern Websites

:(

@PatrickKettner

Page 78: Making Modern Websites

hero

@PatrickKettner

Page 79: Making Modern Websites

savior

@PatrickKettner

Page 80: Making Modern Websites

douchebag

@PatrickKettner

Page 81: Making Modern Websites

AppCache

@PatrickKettner

Page 82: Making Modern Websites

@JaffaTheCake

Page 83: Making Modern Websites

AppCache

@PatrickKettner

Page 84: Making Modern Websites

ServiceWorker > AppCache

@PatrickKettner

Page 85: Making Modern Websites

@PatrickKettner

Page 86: Making Modern Websites

...but it covers our use

@PatrickKettner

Page 87: Making Modern Websites

CACHE MANIFEST

#__CACHE_VERSION__

//download/css/main.css/img/logo.svg

/js/build.js

__ASSETS__

NETWORK:*

@PatrickKettner

Page 88: Making Modern Websites

<html lang="en" manifest="/offline.appcache"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> ...

@PatrickKettner

Page 89: Making Modern Websites

<html lang="en" manifest="/offline.appcache"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> ...

@PatrickKettner

Page 90: Making Modern Websites

<html lang="en" manifest="/offline.appcache"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> ...

@PatrickKettner

Page 91: Making Modern Websites

ServiceWorker > AppCache

@PatrickKettner

Page 92: Making Modern Websites

if('serviceWorker' in navigator) { navigator.serviceWorker.register('/serviceworker.js')} else if ('applicationCache' in window) { // add AppCache}

@PatrickKettner

Page 93: Making Modern Websites

can’t be added by js

@PatrickKettner

Page 94: Making Modern Websites

let iframe = document.createElement('iframe')iframe.style.display = 'none'iframe.src = '/load-appcache.html'document.body.appendChild(iframe)

@PatrickKettner

Page 95: Making Modern Websites

<html manifest="/offline.appcache"> <head> <title>loading douchebags</title> </head> <body></body></html>

@PatrickKettner

Page 96: Making Modern Websites

20.7 seconds

@PatrickKettner

Page 97: Making Modern Websites

190 milliseconds

@PatrickKettner

Page 98: Making Modern Websites

ServiceWorker > AppCache

@PatrickKettner

Page 99: Making Modern Websites

ServiceWorkers!

@PatrickKettner

Page 100: Making Modern Websites

ServiceWorkers

@PatrickKettner

Page 101: Making Modern Websites

WebWorkers

@PatrickKettner

Page 102: Making Modern Websites

commit 90b52e847359ae902d3f7ce7bc511cadfbc29ea8

Author: Alexey Proskuryakov <[email protected]>

Date: Thu Nov 6 07:04:47 +0000

Implement Worker global object

@PatrickKettner

Page 103: Making Modern Websites

2008!

@PatrickKettner

Page 104: Making Modern Websites

Version 2@PatrickKettner

Page 105: Making Modern Websites

Version 2@PatrickKettner

Page 106: Making Modern Websites

WebWorkers

@PatrickKettner

Page 107: Making Modern Websites

WebWorkers?

@PatrickKettner

Page 108: Making Modern Websites

single threadedby default

@PatrickKettner

Page 109: Making Modern Websites

everything is fighting for CPU time

@PatrickKettner

Page 110: Making Modern Websites

lots of number crunchin’===

hardcore jank

@PatrickKettner

Page 111: Making Modern Websites

Offload tasks to background thread

@PatrickKettner

Page 112: Making Modern Websites

super expensive fnsbecome pretty cheap

@PatrickKettner

Page 113: Making Modern Websites

dynamic filesize calculation

@PatrickKettner

Page 114: Making Modern Websites

@PatrickKettner

Page 115: Making Modern Websites
Page 116: Making Modern Websites
Page 117: Making Modern Websites

100% clientside!

@PatrickKettner

Page 118: Making Modern Websites

if ('Worker' in window) { let gzipWorker = new Worker('/gzip.js');

window.gziper = (config, cb) => { gzipWorker.postMessage(config); gzipWorker.onmessage = (e) => cb(e.data); }}

@PatrickKettner

Page 119: Making Modern Websites

@PatrickKettner

importScripts('/pako_deflate.js’, '/pretty-bytes.js');

onmessage = (msg, cb) => { let build = JSON.parse(msg.data).build; let response = { original: prettyBytes(build.length), compressed: prettyBytes(pako.deflate(build, {

'level’: 6 }).length) };

postMessage(response);}

Page 120: Making Modern Websites

@PatrickKettner

Page 121: Making Modern Websites
Page 122: Making Modern Websites

/downloadif ('Worker' in window) { window.buildWorker = new Worker('/build.js');}

@PatrickKettner

Page 123: Making Modern Websites

/downloadbuildWorker.postMessage(JSON.stringify({config}));

@PatrickKettner

Page 124: Making Modern Websites

@PatrickKettner

/build.jsimportScripts('/r.js', '/modernizr/build.js’); require(['build'],(builder) => { onmessage = (msg) => { let config = JSON.parse(msg.data).config; builder(config, postMessage); }});

Page 125: Making Modern Websites

by the time BUILD is clickedits already built

@PatrickKettner

Page 126: Making Modern Websites

“what if their browser don’t have workers”

@PatrickKettner

Page 127: Making Modern Websites

@PatrickKettner

Page 128: Making Modern Websites

¯\_(ツ )_/¯ nbd

@PatrickKettner

Page 129: Making Modern Websites

we’ll just build then

@PatrickKettner

Page 130: Making Modern Websites
Page 131: Making Modern Websites

@PatrickKettner

Page 132: Making Modern Websites

@PatrickKettner

Page 133: Making Modern Websites

let content = build()...zeroClipboard.on('copy', (e) => { let clipboard = e.clipboardData; clipboard.setData('text/plain', content);});

@PatrickKettner

Page 134: Making Modern Websites

@PatrickKettner

Page 135: Making Modern Websites

:(

@PatrickKettner

Page 136: Making Modern Websites

:(

@PatrickKettner

Page 137: Making Modern Websites

@PatrickKettner

if (Modernizr.flash) { // ZeroClipboard} else { // somethingElse}

Page 138: Making Modern Websites

somethingElse?

@PatrickKettner

Page 139: Making Modern Websites

@PatrickKettner

Page 140: Making Modern Websites

let content = build()...let output = document.querySelector('output')output.innerHTML = buildoutput.style.display = 'block'output.select()

@PatrickKettner

Page 141: Making Modern Websites

@PatrickKettner

Page 142: Making Modern Websites

@PatrickKettner

Page 143: Making Modern Websites

@PatrickKettner

Page 144: Making Modern Websites

Blobs, URL, & [download]

@PatrickKettner

Page 145: Making Modern Websites

let content = build()let blob = new Blob([content], { type: 'text/plain'});let href = URL.createObjectURL(blob)let download = 'modernizr.custom.js'

@PatrickKettner

Page 146: Making Modern Websites

@PatrickKettner

<a href={href} download={download}>DOWNLOAD</a>

Page 147: Making Modern Websites

@PatrickKettner

Page 148: Making Modern Websites

@PatrickKettner

Page 149: Making Modern Websites

@PatrickKettner

Page 150: Making Modern Websites

@PatrickKettner

Page 151: Making Modern Websites

~ 61% :/

@PatrickKettner

Page 152: Making Modern Websites

@PatrickKettner

Page 153: Making Modern Websites

@PatrickKettner

Page 154: Making Modern Websites

Just POST It

@PatrickKettner

Page 155: Making Modern Websites

@PatrickKettner

<a href={href} download={download}>DOWNLOAD</a>

Page 156: Making Modern Websites

@PatrickKettner

if (supportsEurythang) { download = <a href={href} download={download}>DOWNLOAD</a>} else { download = <input type='submit' value='download'/>}

Page 157: Making Modern Websites

Decent Markup

@PatrickKettner

Page 158: Making Modern Websites

@PatrickKettner

Page 159: Making Modern Websites

CSS

@PatrickKettner

Page 160: Making Modern Websites

CSS

@PatrickKettner

Page 161: Making Modern Websites
Page 162: Making Modern Websites

JavaScript

@PatrickKettner

Page 163: Making Modern Websites

JavaScript

@PatrickKettner

Page 164: Making Modern Websites
Page 165: Making Modern Websites

100% clientside!

@PatrickKettner

Page 166: Making Modern Websites

100% clientside!unless it can’t

@PatrickKettner

Page 167: Making Modern Websites

Server Side

@PatrickKettner

Page 168: Making Modern Websites

100% static files

@PatrickKettner

Page 169: Making Modern Websites

@PatrickKettner

let server = new Hapi.Server()

server.routes([{ method: 'GET', path: '/{param*}', handler: { directory: { path: './dist' } }}])

server.start()

Page 170: Making Modern Websites

99.999% static files

@PatrickKettner

Page 171: Making Modern Websites

let buildFromPostedQuery = function(request, reply) { let config = generateConfig(request.payload);

Modernizr.build(config,(build) => { reply(build) .header('Content-Type', 'text/javascript') .header('Content-Disposition', 'attachment; filename=modernizr-custom.js') })}

@PatrickKettner

Page 172: Making Modern Websites

@PatrickKettner

let server = new Hapi.Server()

server.routes([{ method: 'GET', path: '/{param*}', handler: {directory: {path: './dist'}}}, { method: 'POST', path: '/download', handler: buildFromPostedQuery}])

server.start()

Page 173: Making Modern Websites

works for all browsers!

@PatrickKettner

Page 174: Making Modern Websites

srsly.

@PatrickKettner

Page 175: Making Modern Websites

@PatrickKettner

Page 176: Making Modern Websites

@PatrickKettner

Page 177: Making Modern Websites

HTML is cool!

@PatrickKettner

Page 178: Making Modern Websites

no one cares.

@PatrickKettner

Page 179: Making Modern Websites

@PatrickKettner

Page 180: Making Modern Websites

@PatrickKettner

Page 181: Making Modern Websites

“I want to bower install!”

@PatrickKettner

Page 182: Making Modern Websites

“I want to npm install!”

@PatrickKettner

Page 183: Making Modern Websites

“There isn’t a file to install”

@PatrickKettner

Page 184: Making Modern Websites

“...”

@PatrickKettner

Page 185: Making Modern Websites

“I want to npm install!”

@PatrickKettner

Page 186: Making Modern Websites

no one cares.

@PatrickKettner

Page 187: Making Modern Websites

no one cares.

@PatrickKettner

Page 188: Making Modern Websites

can’t publish every combo

@PatrickKettner

Page 189: Making Modern Websites

259 modules

@PatrickKettner

Page 190: Making Modern Websites

259 ^ 259

@PatrickKettner

Page 191: Making Modern Websites

3.2317 x 10616

@PatrickKettner

Page 192: Making Modern Websites

no one cares.

@PatrickKettner

Page 193: Making Modern Websites

Server already buildsfor anything POSTed

@PatrickKettner

Page 194: Making Modern Websites

/*! modernizr 3.2.0 (Custom Build) | MIT * * https://modernizr.com/download/?-csstransforms-csstransforms3d-csstransitions-svg !*/

!function(e,t,n){function r(e,t){return typeof e===t}function o(){var e,t,n,o,i,s,a;for(var l in y)if(y.hasOwnProperty(l)){if(e=[],t=y[l],t.name&&(e.push(t.name.toLowerCase()),t.options&&t.options.aliases&&t.options.aliases.length))for(n=0;n<t.options.aliases.length;n++)e.push(t.options.aliases[n].toLowerCase());for(o=r(t.fn,"function")?t.fn():t.fn,i=0;i<e.length;i++)s=e[i],a=s.split("."),1===a.length?Modernizr[a[0]]=o:(!Modernizr[a[0]]||Modernizr[a[0]]instanceof Boolean||(Modernizr[a[0]]=new Boolean(Modernizr[a[0]])),Modernizr[a[0]][a[1]]=o),C.push((o?"":"no-")+a.join("-"))}}function i(e){var t = E.className,A

@PatrickKettner

Page 195: Making Modern Websites

/*! modernizr 3.2.0 (Custom Build) | MIT * * https://modernizr.com/download/?-csstransforms-csstransforms3d-csstransitions-svg !*/

!function(e,t,n){function r(e,t){return typeof e===t}function o(){var e,t,n,o,i,s,a;for(var l in y)if(y.hasOwnProperty(l)){if(e=[],t=y[l],t.name&&(e.push(t.name.toLowerCase()),t.options&&t.options.aliases&&t.options.aliases.length))for(n=0;n<t.options.aliases.length;n++)e.push(t.options.aliases[n].toLowerCase());for(o=r(t.fn,"function")?t.fn():t.fn,i=0;i<e.length;i++)s=e[i],a=s.split("."),1===a.length?Modernizr[a[0]]=o:(!Modernizr[a[0]]||Modernizr[a[0]]instanceof Boolean||(Modernizr[a[0]]=new Boolean(Modernizr[a[0]])),Modernizr[a[0]][a[1]]=o),C.push((o?"":"no-")+a.join("-"))}}function i(e){var t = E.className,A

@PatrickKettner

Page 196: Making Modern Websites

npm install --save https://modernizr.com/download/?-csstransforms-csstransforms3d-csstransitions-svg

@PatrickKettner

Page 197: Making Modern Websites

let handler = (request, reply) => { if (userAgent.match(/bower/)) { buildForBower(config) } else if (userAgent.match(/npm/)) { buildForNPM(config) } else { reply.view('/download', config); }}

@PatrickKettner

Page 198: Making Modern Websites

let Archiver = require('archiver')let archive = Archiver('tar')let bowerJSON = makeBowerJSONFile()

let buildForBower = (config) => { Modernizr.build(config, (build) => { var module = archive .append(build, {name: bowerJSON.main}) .append(JSON.stringify(bowerJSON), {name: 'bower.json'}) .finalize();

reply(module) .header('Content-disposition', 'attachment; filename=Modernizr.custom.tar') })}

@PatrickKettner

Page 199: Making Modern Websites

let Archiver = require('archiver')let archive = Archiver('tar')let pkg = makePackageJSON()

let buildForNPM = (config) => { Modernizr.build(config, (build) => { var module = archive .append(build, {name: pkgJSON.main}) .append(JSON.stringify(pkgJSON), {name: package.json'}) .finalize();

reply(module) .header('Content-disposition', 'attachment; filename=Modernizr.custom.tar') })}

@PatrickKettner

Page 200: Making Modern Websites
Page 201: Making Modern Websites

“wait…require(‘moderznir’)?”

@PatrickKettner

Page 202: Making Modern Websites

@PatrickKettner

Page 203: Making Modern Websites

require(‘moderznir’) !== modernizr

@PatrickKettner

Page 204: Making Modern Websites

@PatrickKettner

Modernizr.build(config, (build) => { fs.writeFileSync('./modernizr.js’)}

Page 205: Making Modern Websites

very flexible

@PatrickKettner

Page 206: Making Modern Websites

not super friendly

@PatrickKettner

Page 207: Making Modern Websites

we already have ainterface we like...

@PatrickKettner

Page 208: Making Modern Websites

lets reuse it!

@PatrickKettner

Page 209: Making Modern Websites
Page 210: Making Modern Websites

React is cool!

@PatrickKettner

Page 211: Making Modern Websites
Page 212: Making Modern Websites

no one cares.

@PatrickKettner

Page 213: Making Modern Websites

get out of the way,in the best ways possible

@PatrickKettner

Page 214: Making Modern Websites

make awesome stuff.

@PatrickKettner

Page 215: Making Modern Websites

use the new shiny.

@PatrickKettner

Page 216: Making Modern Websites

have a lot of fun.

@PatrickKettner

Page 217: Making Modern Websites

Thanks!

@PatrickKettner