Everything is a Polyfill

2,369 views
2,199 views

Published on

Published in: Technology
0 Comments
6 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
2,369
On SlideShare
0
From Embeds
0
Number of Embeds
3
Actions
Shares
0
Downloads
0
Comments
0
Likes
6
Embeds 0
No embeds

No notes for slide

Everything is a Polyfill

  1. 1. " Everything is a Polyfill: Automating a Maintainable Front End
  2. 2. " bit.ly/almost-everything
  3. 3. Emily Nakashima @eanakashima
  4. 4. Rachel Myers @rachelmyers
  5. 5. working together #
  6. 6. $ /* fixed it! */ ! { position: fixed }
  7. 7. $ document. getElementsByClassName ! // Fixed it! !
  8. 8. $/* Looks great!!! */ ! { background: linear-gradient(…) }
  9. 9. $ ! because BROWSERS :(
  10. 10. $ie 7 safari 5 firefox 3
  11. 11. storage polyfill by Joshua Bell storage polyfill by Remy Sharp sessionstorage by Andrea Giammarchi Amplify.js by appendTo YUI3 CacheOffline by YUI team textStorage.js by sofish Using localStorage API, fallback for IE6+ ssw by Matthias Schäfer $.store by Rodney Rehm lawnchair by Brian Leroux store.js by MarcusWestin PersistJS by Paul Duncan Squirrel.js by Aaron Gustafson html5shiv by afarkas, Jon Neal & community innerShiv by Joe Bartlett html5media mediaelement.js by John Dyer SublimeVideo video.js by Zencoder LeanBack Player - HTML5 audio/video media player video for everybody by Kroc Camen (orig.) videosub JSCaptions by Daniel Davis Captionator by Christopher Giffard playr by JulienVilletorte Range Input Webshims Lib by Alexander Farkas H5F by Ryan Seddon webforms2 byWeston Ruter Rangy byTim Down insertAdjacentHTML.js by Eli Grey outerHTML.js by Eli Grey DOMParser by Eli Grey js-xpath wicked-good-xpath Array.prototype.slice Array Generics Array.prototype: indexOf, lastIndexOf, forEach, every, filter, some, map, reduce, reduceRight es5-shim by Kris Kowal,Tom Robinson, community. Xccessors by Eli Grey getters and setters by the IE team. json2.js by Douglas Crockford json3.js by Kit Cambridge ddr-ecma5 by David de Rosier augment.js by Oliver Nightingale String.js by Brett Zamir es6-shim by Paul Miller WeakMap, Map, Set, HashMap by Brandon Benvie ES6 Map Shim by EricWendelin ECMAScript 6 polyfil by Alexander Guinness Function.create by BjarkeWalling String.prototype.contains by Robert Kowalski Object.observe() shim by Kap IT ES6 shim by inexorabletash ES6 Map, Set, WeakMap by EliSnow es6-promise cssFx by Ivan Malopinsky Make it work everywhere!
  12. 12. gallery-html5-forms YUI3 gallery module by Matt Snider jscolor Polyfill by Johannes J. Schmidt HTML5 Form Shim by Dmitry Sheiko jQuery form shim by Andrew Dodson selectedOptions multiple <select> shim by Brett Zamir better-dateinput-polyfill by Maksim Chemerisuk better-timeinput-polyfill by Maksim Chemerisuk oninput event shim by Ben Alpert Placeholder by James Brumond Placeholder jQuery plugin by Mathias Bynens Placeholder Enhanced by Denis Ciccale jquery-placeholder by Brian Reavis (doesn't set input's value) jquery.HTML5Support (supports placeholder and autofocus) by Amiel Martin jquery.placeholder.js by Paul Serby Placeholders.js by James Allardice placeholder-augment by Jethro Larson better-placeholder-polyfill by Maksim Chemerisuk Placeholdr by Shane Carr HTML5 placeholder polyfill by Dirk Ginader accessifyhtml5.js SockJS by Marek Majkowski socket.io by Guillermo Rauch kaazing websocket gateway web-socket-js atmosphere jQuery plugin GracefulWebSocket jQuery plugin by David Lindkvist Portal by Donghwan Kim DataChannel polyfill by Jesús Leganés Combarro "Piranna" Webshims Lib by Alexander Farkas geolocation polyfill by Joshua Bell geolocation shim by Paul Irish geo-location-javascript Geolocation-API-Polyfill by Manuel Bieh html5-gears by Brad Neuberg offline-event.js by Remy Sharp heyoffline.js by oskarkrawczyk History.js by Benjamin Lupton CSS3 REM Unit conversion by Chuck Carpenter and Lucas Serven Units by Grady Kuhnline vminpoly by Sebastian Ferreyra Prefixfree by LeaVerou cssMinMax by Russ Porosky jQuery.object-fit.js by SteveWorkman / Simon Schmid object-fit.js by Anselm Hannemann (and Christian Schaefer) image-set on img elements by FabianTollenaar CSS3 PIE by Jason Johnston jQueryText Overflow plugin by Devon Govett, Andrew A. Kononykhin, Micky Hulse borderBoxModel by Alberto Gasparin box-sizing-polyfill by Christian "Schepp" Schaefer Borderbox for Compass by Richard Herrera css3-mediaqueries-js Respond by Scott Jehl mediatizr by Aurélien Delogu matchMedia by Scott Jehl, Paul Irish, Nicholas Zakas jQuery Media Helpers by Scott Jehl pointeraccuracy.js by n-fuse CSS.supports polyfill by Егор Халимоненко @supports polyfill by Krystian Jarmicki jQueryText Shadow by heygrady fontloader by Bram Stein CSS3 - Multi Column Updated for HTML5 tags Flexie by Richard Herrera Grid Layout Polyfill by Han Lin Yap CSSTemplate Layout jQuery plug-in by Alexis Deveria CSS Regions Polyfill - by Mihai Corlan & Razvan Caliman Transformie by Paul Bakaus CSS Sandpaper by Zoltan Hawryluk Polyfilter - a CSS Filters Polyfill by Christian "Schepp" Schaefer microdatajs by Philip Jägenstedt Microdata-JS by Егор Халимоненко notification.js by Andrew Dodson desktop-notify byTsvetanTsvetkov so many
  13. 13. Polyfills!%
  14. 14. Ideal Browser Ideal HTML Ideal CSS Ideal JavaScript
  15. 15. Actual HTML Actual CSS Actual JavaScript
  16. 16. Safari Chrome Mobile Safari Actual HTML Actual CSS Actual JavaScript
  17. 17. Where are we now?!
  18. 18. Performance all the things&
  19. 19. 1. configuration for performance 2. refactor bottlenecks 3. performance-minded development 4. repeat 3 for as long as you can before going back to 1 & 2 Stages of Performance Optimization
  20. 20. Performance all the things&
  21. 21. // indexof_polyfill.js ! if (!Array.prototype.indexOf) { Array.prototype.indexOf = function (searchElement, fromIndex) { if ( this === undefined || this === null ) { throw new TypeError( '"this" is null or not defined' ); } var length = this.length >>> 0; // convert object.length to a UInt32 fromIndex = +fromIndex || 0; if (Math.abs(fromIndex) === Infinity) { fromIndex = 0; } if (fromIndex < 0) { fromIndex += length; if (fromIndex < 0) { fromIndex = 0; } } for (fromIndex < length; fromIndex++) { if (this[fromIndex] === searchElement) { return fromIndex; } } return -1; }; }
  22. 22. // Returns 3 Everywhere ! “browsers".indexOf("w") ! // Returns 3 almost everywhere, except in IE8, // where it returns `TypeError: Object [object Array] // has no method 'indexOf'` ! ["b","r","o","w","s","e","r","s"].indexOf("w")
  23. 23. // indexof_polyfill.js ! if (!Array.prototype.indexOf) { Array.prototype.indexOf = function (searchElement, fromIndex) { if ( this === undefined || this === null ) { throw new TypeError( '"this" is null or not defined' ); } var length = this.length >>> 0; // convert object.length to a UInt32 fromIndex = +fromIndex || 0; if (Math.abs(fromIndex) === Infinity) { fromIndex = 0; } if (fromIndex < 0) { fromIndex += length; if (fromIndex < 0) { fromIndex = 0; } } for (fromIndex < length; fromIndex++) { if (this[fromIndex] === searchElement) { return fromIndex; } } return -1; }; }
  24. 24. // in datepicker.js // … ! var el = document.getElementById('datepicker') if (window.CustomEvent) { var event = new CustomEvent(‘date-changed’, {detail: {some: 'data'}}); } else { var event = document.createEvent('CustomEvent'); event.initCustomEvent(‘date-changed', true, true, {some: 'data'}); } ! el.dispatchEvent(event); ! // …
  25. 25. // in datepicker.js // … ! var el = document.getElementById('datepicker') if (window.CustomEvent) { var event = new CustomEvent(‘date-changed’, {detail: {some: 'data'}}); } else { var event = document.createEvent('CustomEvent'); event.initCustomEvent(‘date-changed', true, true, {some: 'data'}); } ! el.dispatchEvent(event); ! // …
  26. 26. some possible improvements'
  27. 27. // indexof_polyfill.js // // Delete this file when we drop support for IE8. ! if (!Array.prototype.indexOf) { Array.prototype.indexOf = function (searchElement, fromIndex) { if ( this === undefined || this === null ) { throw new TypeError( '"this" is null or not defined' ); } var length = this.length >>> 0; // convert object.length to a UInt32 fromIndex = +fromIndex || 0; if (Math.abs(fromIndex) === Infinity) { fromIndex = 0; } if (fromIndex < 0) { fromIndex += length; if (fromIndex < 0) { fromIndex = 0; } } for (fromIndex < length; fromIndex++) { if (this[fromIndex] === searchElement) { return fromIndex; } } return -1; }; }
  28. 28. // indexof_polyfill.js ! Modernizr.load({ test: Modernizr.arrayindexof, yep : ‘’, // do nothing nope: ‘indexof_polyfill.js' });
  29. 29. // standard require.js pattern // dependencies are a list of string IDs ! define([‘date_utils’,’indexof’], function(date,i) { return function(){ … } });
  30. 30. // calculate dependencies for datepicker.js ! var dependencies = [‘date_utils’] if (polyfilled.indexOf) dependencies.push(‘indexof’); ! define(dependencies, function(date,i) { return function(){ … } });
  31. 31. One Giant Module
  32. 32. https://github.com/ drag_and_drop_image_uploa datepicker.js emojipicker.js issue_label_widget.js add_a_team_widget.js datepicker_dependency_1.js datepicker_dependency_2.js datepicker_dependency_3.js datepicker_dependency_4.js datepicker_nested_dependen cy_1.jsdatepicker_nested_dependen cy_2.jsdatepicker_nested_dependen cy_3.js (dramatized) waterfall chart using require.js
  33. 33. https://github.com/ drag_and_drop_image_uploa datepicker.js emojipicker.js issue_label_widget.js add_a_team_widget.js datepicker_dependency_1.js datepicker_dependency_2.js datepicker_dependency_3.js datepicker_dependency_4.js datepicker_nested_dependen cy_1.jsdatepicker_nested_dependen cy_2.jsdatepicker_nested_dependen cy_3.js (dramatized) waterfall chart using require.js
  34. 34. https://github.com/ drag_and_drop_image_uploa datepicker.js emojipicker.js issue_label_widget.js add_a_team_widget.js datepicker_dependency_1.js datepicker_dependency_2.js datepicker_dependency_3.js datepicker_dependency_4.js datepicker_nested_dependen cy_1.jsdatepicker_nested_dependen cy_2.jsdatepicker_nested_dependen cy_3.js (dramatized) waterfall chart using require.js
  35. 35. # # # # # # #
  36. 36. #### ### # # # # # # #
  37. 37. this code is overhead
  38. 38. how we fix it(
  39. 39. // check our browser analytics on these dates ! browserSupport = { “safari-5.0": "June 01 2014", “ie-8": "June 01 2014", “ie-9": "January 01 2015" }
  40. 40. ! // browser support ! test( “indexOf polyfill", function() { var browserSupport = polyfill.browserSupport; var today = new Date(); var iE8Sunset = Date.parse(browserSupport[‘ie-8’]); ! if (today < iE8Sunset) { ok(polyfilled.indexOf); } else { ok(!polyfilled.indexOf); } }); !
  41. 41. ! // A/B test testing ! test( “homepage banner a/b test“, function() { var today = new Date(); var testEndDate = Date.parse(“2014-04-19”); ! if (today < testEndDate) { ok(activeABTests.homepage); } else { ok(!activeABTests.homepage); } }); !
  42. 42. // browser support ! test( “indexOf polyfill", function() { var browserSupport = polyfill.browserSupport; var today = new Date(); var iE8Sunset = Date.parse(browserSupport[‘ie-8’]); ! if (today < iE8Sunset) { ok(polyfilled.indexOf); } else { ok(!polyfilled.indexOf); } });
  43. 43. Helps Users (reduces content sent over the wire / gets it there quickly) Code Com m ents ScriptLoaders SunsetTests
  44. 44. HelpsDevelopers (tellsuswhencodeisbeingused) Helps Users (reduces content sent over the wire / gets it there quickly) Code Com m ents ScriptLoaders SunsetTests
  45. 45. HelpsDevelopers (tellsuswhencodeisbeingused) Helps Users (reduces content sent over the wire / gets it there quickly) Code Com m ents ScriptLoaders SunsetTests
  46. 46. where this fits in)
  47. 47. // css ! #topnav ul li .home { width: 200px; height… #topnav ul li a { display: inline-block… ! .sidebar p { margin: 10px; } <— unused? ! // template ! <div id=‘topnav’> <ul> <li class=‘home’>… <li class=‘cat-furniture’>… </ul> <div id=‘sidebar’> <p>…
  48. 48. 1 month of css 1 month of js
  49. 49. ! // test for unused vendor prefixes ! test "stylesheets have un-used vendor prefixes" do supportSafari4 = Time.now() < @br_support[‘safari4’] ! unless supportSafari4 ! `grep -R “-webkit-border-radius” assets/css`. lines.each do |line| flunk line end ! end end !
  50. 50. shouldn’t there be a tool for this??
  51. 51. why this is becoming more important*
  52. 52. HTTP/2
  53. 53. $Minimize http requests!!!
  54. 54. SPDY
  55. 55. you can’t test for everything+
  56. 56. Implementations don’t always converge.
  57. 57. adapter pattern for the web,
  58. 58. HTML CSS JavaScript Browsers
  59. 59. Polyfills HTML CSS JavaScript Browsers
  60. 60. ! // test for expired compatibility code ! test “js has CustomEvent workaround for IE8" do supportIE8 = Time.now() < @br_support[‘ie-8’] ! unless supportIE8 ! `grep -R ‘createEvent(“CustomEvent”)’ assets/js`. lines.each do |line| flunk line end ! end end !
  61. 61. jQuery 1.x jQuery 2.x polyfill ~80kb ~70kb
  62. 62. ! // test for expired compatibility code ! test “js has CustomEvent workaround for IE8" do supportIE8 = Time.now() < @br_support[‘ie-8’] ! unless supportIE8 ! `grep -R ‘createEvent(“CustomEvent”)’ assets/js`. lines.each do |line| flunk line end ! end end !
  63. 63. dimensions ~1kb offset ~1kb wrap ~1kb event aliases ~1kb core ~70kb Sizzle ~5 kb ajax ~10 kb effects ~5kb css ~10 kb deprecated ~1kb jQuery from jQuery Builder
  64. 64. Performance all the things&
  65. 65. " Checklist-
  66. 66. ☑ know what browsers you support
  67. 67. ☑ know what browsers you support ☑ enforce expiration dates in code
  68. 68. ☑ know what browsers you support ☑ enforce expiration dates in code ☑ look for the missing layer as you go
  69. 69. Credits Feedback: ! Code Inspiration: ! Octocats/Octicons:
  70. 70. Thank you! ! @rachelmyers @eanakashima ! bit.ly/almost-everything

×