Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Future-Proofing Your JavaScript Framework Decision

121 views

Published on

Choosing a JavaScript framework is both exciting and stressful. The decision will have a large impact on both your development team and your customers for the foreseeable future, so how can you effectively decide with all of that pressure?

The best way to approach this decision is to actually take a step back and plan the architecture of your single-page web app in a way that minimizes the reliance on a web framework while still providing all the benefits of a framework.

This case study from Comcast walks through what that single-page web app architecture looks like, as well as the decision making process their web engineering teams follow when making technology decisions such as choosing a JavaScript framework, so you can successfully apply the same blueprint.

Published in: Technology
  • Be the first to comment

  • Be the first to like this

Future-Proofing Your JavaScript Framework Decision

  1. 1. FUTURE-PROOFING YOUR JAVASCRIPT FRAMEWORK DECISIONApril 5, 2019 JOHN RIVIELLO @JohnRiv
  2. 2. 2 ?
  3. 3. GOAL: Position your team so the eventual transition off the framework will involve the least amount of friction
  4. 4. Future-Proofing Your JavaScript Framework Decision - @JohnRiv4 “BEACH SAND” BY JOSH SORENSON LICENSED BY PEXELS.COM
  5. 5. Future-Proofing Your JavaScript Framework Decision - @JohnRiv5 “SACRIFICIAL ARCHITECTURE” https://martinfowler.com/bliki/SacrificialArchitecture.html “Thinking now about things that can make it easier to replace when the time comes.” - MARTIN FOWLER
  6. 6. Future-Proofing Your JavaScript Framework Decision - @JohnRiv6 1.REDUX 2.PERPETUAL CSS 3.DEMO PAGES 4.A FRAMEWORK FOR CHOOSING YOUR FRAMEWORK PATTERNS & TOOLS
  7. 7. REDUX
  8. 8. Future-Proofing Your JavaScript Framework Decision - @JohnRiv8 UNIDIRECTIONAL DATA FLOWhttps://redux.js.org/basics/data-flow
  9. 9. Future-Proofing Your JavaScript Framework Decision - @JohnRiv9 PREDICTABLE STATE MUTATIONShttps://redux.js.org/introduction/motivation
  10. 10. Future-Proofing Your JavaScript Framework Decision - @JohnRiv1 0
  11. 11. Future-Proofing Your JavaScript Framework Decision - @JohnRiv1 1
  12. 12. Future-Proofing Your JavaScript Framework Decision - @JohnRiv1 2
  13. 13. Future-Proofing Your JavaScript Framework Decision - @JohnRiv1 3 { type: 'OPEN_MODAL', payload: { type: 'PAUSE_PERSON' id: 'ABC1234', } }
  14. 14. Future-Proofing Your JavaScript Framework Decision - @JohnRiv1 4 { type: 'OPEN_MODAL', payload: { type: 'PAUSE_PERSON' id: 'ABC1234', } }
  15. 15. Future-Proofing Your JavaScript Framework Decision - @JohnRiv1 5 { type: 'OPEN_MODAL', payload: { type: 'PAUSE_PERSON' id: 'ABC1234', } }
  16. 16. Future-Proofing Your JavaScript Framework Decision - @JohnRiv1 6 { type: 'OPEN_MODAL', payload: { type: 'PAUSE_PERSON' id: 'ABC1234', } }
  17. 17. Future-Proofing Your JavaScript Framework Decision - @JohnRiv1 7 { type: 'OPEN_MODAL', payload: { type: 'PAUSE_PERSON' id: 'ABC1234', } }
  18. 18. Future-Proofing Your JavaScript Framework Decision - @JohnRiv1 8 { type: 'OPEN_MODAL', payload: { type: 'PAUSE_PERSON' id: 'ABC1234', } }
  19. 19. Future-Proofing Your JavaScript Framework Decision - @JohnRiv1 9 { type: 'OPEN_MODAL', payload: { type: 'PAUSE_PERSON' id: 'ABC1234', } }
  20. 20. Future-Proofing Your JavaScript Framework Decision - @JohnRiv2 0 { type: 'OPEN_MODAL', payload: { type: 'PAUSE_PERSON' id: 'ABC1234', } }
  21. 21. Future-Proofing Your JavaScript Framework Decision - @JohnRiv2 1 { type: 'OPEN_MODAL', payload: { type: 'PAUSE_PERSON' id: 'ABC1234', } }
  22. 22. Future-Proofing Your JavaScript Framework Decision - @JohnRiv2 2 { type: 'OPEN_MODAL', payload: { type: 'PAUSE_PERSON' id: 'ABC1234', } } log('OPEN_MODAL',
 'PAUSE_PERSON',
 'ABC1234');
  23. 23. Future-Proofing Your JavaScript Framework Decision - @JohnRiv2 3 { type: 'OPEN_MODAL', payload: { type: 'PAUSE_PERSON' id: 'ABC1234', } }
  24. 24. Future-Proofing Your JavaScript Framework Decision - @JohnRiv2 4 { type: 'OPEN_MODAL', payload: { type: 'PAUSE_PERSON' id: 'ABC1234', } }
  25. 25. Future-Proofing Your JavaScript Framework Decision - @JohnRiv2 5 { type: 'OPEN_MODAL', payload: { type: 'PAUSE_PERSON' id: 'ABC1234', } }
  26. 26. Future-Proofing Your JavaScript Framework Decision - @JohnRiv2 6 { type: 'OPEN_MODAL', payload: { type: 'PAUSE_PERSON' id: 'ABC1234', } }
  27. 27. Future-Proofing Your JavaScript Framework Decision - @JohnRiv2 7 { type: 'OPEN_MODAL', payload: { type: 'PAUSE_PERSON' id: 'ABC1234', } } { … modal: { isOpen: false, } … }
  28. 28. Future-Proofing Your JavaScript Framework Decision - @JohnRiv2 8 { type: 'OPEN_MODAL', payload: { type: 'PAUSE_PERSON' id: 'ABC1234', } } { … modal: { isOpen: true, type: 'PAUSE_PERSON', } … }
  29. 29. Future-Proofing Your JavaScript Framework Decision - @JohnRiv2 9 { type: 'OPEN_MODAL', payload: { type: 'PAUSE_PERSON' id: 'ABC1234', } }
  30. 30. Future-Proofing Your JavaScript Framework Decision - @JohnRiv3 0 { type: 'OPEN_MODAL', payload: { type: 'PAUSE_PERSON' id: 'ABC1234', } }
  31. 31. Future-Proofing Your JavaScript Framework Decision - @JohnRiv3 1 { type: 'OPEN_MODAL', payload: { type: 'PAUSE_PERSON' id: 'ABC1234', } }
  32. 32. Future-Proofing Your JavaScript Framework Decision - @JohnRiv3 2 { type: 'OPEN_MODAL', payload: { type: 'PAUSE_PERSON' id: 'ABC1234', } }
  33. 33. Future-Proofing Your JavaScript Framework Decision - @JohnRiv3 3 { type: 'OPEN_MODAL', payload: { type: 'PAUSE_PERSON' id: 'ABC1234', } }
  34. 34. Future-Proofing Your JavaScript Framework Decision - @JohnRiv3 4 { type: 'OPEN_MODAL', payload: { type: 'PAUSE_PERSON' id: 'ABC1234', } } { viewState: { modal: { isOpen: true, type: 'PAUSE_PERSON', displayName: 'Max', } } … }
  35. 35. Future-Proofing Your JavaScript Framework Decision - @JohnRiv3 5 { type: 'OPEN_MODAL', payload: { type: 'PAUSE_PERSON' id: 'ABC1234', } }
  36. 36. Future-Proofing Your JavaScript Framework Decision - @JohnRiv3 6 { type: 'OPEN_MODAL', payload: { type: 'PAUSE_PERSON' id: 'ABC1234', } }
  37. 37. Future-Proofing Your JavaScript Framework Decision - @JohnRiv3 7 { type: 'OPEN_MODAL', payload: { type: 'PAUSE_PERSON' id: 'ABC1234', } }
  38. 38. Future-Proofing Your JavaScript Framework Decision - @JohnRiv3 8
  39. 39. Future-Proofing Your JavaScript Framework Decision - @JohnRiv3 9
  40. 40. Future-Proofing Your JavaScript Framework Decision - @JohnRiv4 0 { type: 'MODAL_SUBMIT', payload: { … } }
  41. 41. Future-Proofing Your JavaScript Framework Decision - @JohnRiv4 1 { type: 'MODAL_SUBMIT', payload: { … } }
  42. 42. Future-Proofing Your JavaScript Framework Decision - @JohnRiv4 2 { type: 'MODAL_SUBMIT', payload: { … } }
  43. 43. Future-Proofing Your JavaScript Framework Decision - @JohnRiv4 3 { type: 'MODAL_SUBMIT', payload: { … } }
  44. 44. Future-Proofing Your JavaScript Framework Decision - @JohnRiv4 4 { type: 'MODAL_SUBMIT', payload: { … } }
  45. 45. Future-Proofing Your JavaScript Framework Decision - @JohnRiv4 5 { type: 'MODAL_SUBMIT', payload: { … } }
  46. 46. Future-Proofing Your JavaScript Framework Decision - @JohnRiv4 6 { type: 'MODAL_SUBMIT', payload: { … } }
  47. 47. Future-Proofing Your JavaScript Framework Decision - @JohnRiv4 7 { type: 'MODAL_SUBMIT', payload: { … } }
  48. 48. Future-Proofing Your JavaScript Framework Decision - @JohnRiv4 8 { type: 'MODAL_SUBMIT', payload: { … } }
  49. 49. Future-Proofing Your JavaScript Framework Decision - @JohnRiv4 9 { type: 'MODAL_SUBMIT', payload: { … } } POST /pause/ABC1234
  50. 50. Future-Proofing Your JavaScript Framework Decision - @JohnRiv5 0 { type: 'MODAL_SUBMIT', payload: { … } } log('MODAL_SUBMIT',
 'PAUSE_PERSON',
 'ABC1234');
  51. 51. Future-Proofing Your JavaScript Framework Decision - @JohnRiv5 1 { type: 'MODAL_SUBMIT', payload: { … } }
  52. 52. Future-Proofing Your JavaScript Framework Decision - @JohnRiv5 2 { type: 'MODAL_SUBMIT', payload: { … } }
  53. 53. Future-Proofing Your JavaScript Framework Decision - @JohnRiv5 3 { type: 'MODAL_SUBMIT', payload: { … } }
  54. 54. Future-Proofing Your JavaScript Framework Decision - @JohnRiv5 4 { type: 'MODAL_SUBMIT', payload: { … } }
  55. 55. Future-Proofing Your JavaScript Framework Decision - @JohnRiv5 5 { type: 'MODAL_SUBMIT', payload: { … } } { … modal: { isOpen: true, type: 'PAUSE_PERSON',
 status: 'READY', } … }
  56. 56. Future-Proofing Your JavaScript Framework Decision - @JohnRiv5 6 { type: 'MODAL_SUBMIT', payload: { … } } { … modal: { isOpen: true, type: 'PAUSE_PERSON',
 status: 'BUSY', } … }
  57. 57. Future-Proofing Your JavaScript Framework Decision - @JohnRiv5 7 { type: 'MODAL_SUBMIT', payload: { … } }
  58. 58. Future-Proofing Your JavaScript Framework Decision - @JohnRiv5 8 { type: 'MODAL_SUBMIT', payload: { … } }
  59. 59. Future-Proofing Your JavaScript Framework Decision - @JohnRiv5 9 { type: 'MODAL_SUBMIT', payload: { … } }
  60. 60. Future-Proofing Your JavaScript Framework Decision - @JohnRiv6 0 { type: 'MODAL_SUBMIT', payload: { … } }
  61. 61. Future-Proofing Your JavaScript Framework Decision - @JohnRiv6 1 { type: 'MODAL_SUBMIT', payload: { … } }
  62. 62. Future-Proofing Your JavaScript Framework Decision - @JohnRiv6 2 { type: 'MODAL_SUBMIT', payload: { … } } { viewState: { modal: { isOpen: true, type: 'PAUSE_PERSON', status: 'BUSY', } } … }
  63. 63. Future-Proofing Your JavaScript Framework Decision - @JohnRiv6 3 { type: 'MODAL_SUBMIT', payload: { … } }
  64. 64. Future-Proofing Your JavaScript Framework Decision - @JohnRiv6 4 { type: 'MODAL_SUBMIT', payload: { … } }
  65. 65. Future-Proofing Your JavaScript Framework Decision - @JohnRiv6 5 { type: 'MODAL_SUBMIT', payload: { … } }
  66. 66. Future-Proofing Your JavaScript Framework Decision - @JohnRiv6 6
  67. 67. Future-Proofing Your JavaScript Framework Decision - @JohnRiv6 7 POST /pause/ABC1234 200 OK { … data … }
  68. 68. Future-Proofing Your JavaScript Framework Decision - @JohnRiv6 8 POST /pause/ABC1234 200 OK { … data … }
  69. 69. Future-Proofing Your JavaScript Framework Decision - @JohnRiv6 9 POST /pause/ABC1234 200 OK { … data … }
  70. 70. Future-Proofing Your JavaScript Framework Decision - @JohnRiv7 0 POST /pause/ABC1234 200 OK { … data … }
  71. 71. Future-Proofing Your JavaScript Framework Decision - @JohnRiv7 1 POST /pause/ABC1234 200 OK { … data … }
  72. 72. Future-Proofing Your JavaScript Framework Decision - @JohnRiv7 2 POST /pause/ABC1234 200 OK { … data … }
  73. 73. Future-Proofing Your JavaScript Framework Decision - @JohnRiv7 3 POST /pause/ABC1234 200 OK { … data … }
  74. 74. Future-Proofing Your JavaScript Framework Decision - @JohnRiv7 4 POST /pause/ABC1234 200 OK { … data … }
  75. 75. Future-Proofing Your JavaScript Framework Decision - @JohnRiv7 5 POST /pause/ABC1234 200 OK { … data … }
  76. 76. Future-Proofing Your JavaScript Framework Decision - @JohnRiv7 6 POST /pause/ABC1234 200 OK { … data … }
  77. 77. Future-Proofing Your JavaScript Framework Decision - @JohnRiv7 7 POST /pause/ABC1234 200 OK { … data … } log('MODAL_SUCCESS',
 'PAUSE_PERSON',
 'ABC1234');
  78. 78. Future-Proofing Your JavaScript Framework Decision - @JohnRiv7 8 POST /pause/ABC1234 200 OK { … data … }
  79. 79. Future-Proofing Your JavaScript Framework Decision - @JohnRiv7 9 POST /pause/ABC1234 200 OK { … data … }
  80. 80. Future-Proofing Your JavaScript Framework Decision - @JohnRiv8 0 POST /pause/ABC1234 200 OK { … data … }
  81. 81. Future-Proofing Your JavaScript Framework Decision - @JohnRiv8 1 POST /pause/ABC1234 200 OK { … data … }
  82. 82. Future-Proofing Your JavaScript Framework Decision - @JohnRiv8 2 POST /pause/ABC1234 200 OK { … data … } { … modal: { isOpen: true, type: 'PAUSE_PERSON',
 status: 'BUSY', } … }
  83. 83. Future-Proofing Your JavaScript Framework Decision - @JohnRiv8 3 POST /pause/ABC1234 200 OK { … data … } { … modal: { isOpen: true, type: 'PAUSE_PERSON',
 status: 'SUCCESS', } … }
  84. 84. Future-Proofing Your JavaScript Framework Decision - @JohnRiv8 4 POST /pause/ABC1234 200 OK { … data … }
  85. 85. Future-Proofing Your JavaScript Framework Decision - @JohnRiv8 5 POST /pause/ABC1234 200 OK { … data … }
  86. 86. Future-Proofing Your JavaScript Framework Decision - @JohnRiv8 6 POST /pause/ABC1234 200 OK { … data … }
  87. 87. Future-Proofing Your JavaScript Framework Decision - @JohnRiv8 7 POST /pause/ABC1234 200 OK { … data … }
  88. 88. Future-Proofing Your JavaScript Framework Decision - @JohnRiv8 8 POST /pause/ABC1234 200 OK { … data … }
  89. 89. Future-Proofing Your JavaScript Framework Decision - @JohnRiv8 9 POST /pause/ABC1234 200 OK { … data … } { viewState: { modal: { isOpen: true, type: 'PAUSE_PERSON', status: 'SUCCESS', } } … }
  90. 90. Future-Proofing Your JavaScript Framework Decision - @JohnRiv9 0 POST /pause/ABC1234 200 OK { … data … }
  91. 91. Future-Proofing Your JavaScript Framework Decision - @JohnRiv9 1 POST /pause/ABC1234 200 OK { … data … }
  92. 92. Future-Proofing Your JavaScript Framework Decision - @JohnRiv9 2 POST /pause/ABC1234 200 OK { … data … }
  93. 93. Future-Proofing Your JavaScript Framework Decision - @JohnRiv9 3
  94. 94. Future-Proofing Your JavaScript Framework Decision - @JohnRiv9 4
  95. 95. Future-Proofing Your JavaScript Framework Decision - @JohnRiv9 5
  96. 96. Future-Proofing Your JavaScript Framework Decision - @JohnRiv9 6
  97. 97. Future-Proofing Your JavaScript Framework Decision - @JohnRiv9 7 client-core src/ actions/ constants/ data/ epics/ helpers/ middleware/ reducers/ selectors/ store/ index.js dist/ es5-client-core.js
  98. 98. Future-Proofing Your JavaScript Framework Decision - @JohnRiv src/ actions/ constants/ data/ epics/ helpers/ middleware/ reducers/ selectors/ store/ index.js dist/ es5-client-core.js 9 8 client-core src/actions/index.js export { default as account } from './account'; export { default as app } from './app'; ... account.js app.js … index.js … src/actions/account.js export function functionOne({ ... return { /* object */ }; } export function functionTwo({ ... return { /* object */ }; } ... export default { functionOne, functionTwo, ... };
  99. 99. Future-Proofing Your JavaScript Framework Decision - @JohnRiv9 9 client-core src/ actions/ constants/ data/ epics/ helpers/ middleware/ reducers/ selectors/ store/ index.js dist/ es5-client-core.js index.js import * as _actions from './src/actions'; import * as _constants from './src/constants'; import * as _data from './src/data'; import * as _epics from './src/epics'; import * as _helpers from './src/helpers'; import * as _middleware from './src/middleware'; import * as _reducer from './src/reducers'; import * as _selectors from './src/selectors'; import * as _store from './src/store'; export const actions = _actions; export const constants = _constants; export const data = _data; export const epics = _epics; export const helpers = _helpers; export const middleware = _middleware; export const reducers = _reducer; export const selectors = _selectors; export const store = _store; src/actions/index.js export { default as account } from './account'; export { default as app } from './app'; ... src/actions/account.js export function functionOne({ ... return { /* object */ }; } export function functionTwo({ ... return { /* object */ }; } ... export default { functionOne,
  100. 100. Future-Proofing Your JavaScript Framework Decision - @JohnRiv src/actions/account.js export function functionOne({ ... return { /* object */ }; } export function functionTwo({ ... return { /* object */ }; } ... export default { functionOne, 1 0 0 client-core src/ actions/ constants/ data/ epics/ helpers/ middleware/ reducers/ selectors/ store/ index.js dist/ es5-client-core.js index.js import * as _actions from './src/actions'; import * as _constants from './src/constants'; import * as _data from './src/data'; import * as _epics from './src/epics'; import * as _helpers from './src/helpers'; import * as _middleware from './src/middleware'; import * as _reducer from './src/reducers'; import * as _selectors from './src/selectors'; import * as _store from './src/store'; export const actions = _actions; export const constants = _constants; export const data = _data; export const epics = _epics; export const helpers = _helpers; export const middleware = _middleware; export const reducers = _reducer; export const selectors = _selectors; export const store = _store; src/actions/index.js export { default as account } from './account'; export { default as app } from './app'; ... import clientCore from 'client-core' import {actions as coreActions} from 'client-core' import {account as accountActions} from 'client-core/actions' import {functionOne as f1} from 'client-core/actions/account' Allows for multiple ways to import the code
  101. 101. Future-Proofing Your JavaScript Framework Decision - @JohnRiv src/actions/account.js export function functionOne({ ... return { /* object */ }; } export function functionTwo({ ... return { /* object */ }; } ... export default { functionOne, src/ actions/ constants/ data/ epics/ helpers/ middleware/ reducers/ selectors/ store/ index.js dist/ es5-client-core.js 1 0 1 client-core index.js import * as _actions from './src/actions'; import * as _constants from './src/constants'; import * as _data from './src/data'; import * as _epics from './src/epics'; import * as _helpers from './src/helpers'; import * as _middleware from './src/middleware'; import * as _reducer from './src/reducers'; import * as _selectors from './src/selectors'; import * as _store from './src/store'; export const actions = _actions; export const constants = _constants; export const data = _data; export const epics = _epics; export const helpers = _helpers; export const middleware = _middleware; export const reducers = _reducer; export const selectors = _selectors; export const store = _store; src/actions/index.js export { default as account } from './account'; export { default as app } from ‘./app'; ... import clientCore from 'client-core' import {actions as coreActions} from 'client-core' import {account as accountActions} from 'client-core/actions' import {functionOne as f1} from 'client-core/actions/account' Allows for multiple ways to import the code = UMD Module+
  102. 102. Future-Proofing Your JavaScript Framework Decision - @JohnRiv1 0 2 YOU MIGHT NOT NEED REDUX ¯_ _/¯
  103. 103. git clone --depth 1 -b template-no-redux —single-branch https://github.com/Polymer/pwa-starter-kit my-app https://pwa-starter-kit.polymer-project.org/ NO-REDUX TEMPLATE: git clone --depth 1 -b template-no-redux —single-branch https://github.com/Polymer/pwa-starter-kit my-app
  104. 104. PERPETUAL CSS
  105. 105. Future-Proofing Your JavaScript Framework Decision - @JohnRiv1 0 5 CSS: SO MANY OPTIONS COMPONENT-SPECIFIC •CSS-in-JS •Shadow DOM REUSABLE CLASSES •OOCSS •SMACSS •BEM THEMING WITH VARIABLES •Sass / Less / Stylus •Post CSS •CSS Custom Properties •CSS Shadow Parts UTILITY CLASSES / FUNCTIONAL CSS / ATOMIC CSS •Atomizer •Tachyons •Tailwind
  106. 106. Future-Proofing Your JavaScript Framework Decision - @JohnRiv1 0 6 STANDARD APPROACH VS UTILITY CLASSES .standard { color: red; float: left; } <div class="standard"> Standard Approach </div> .text-red { color: red; } .float-left { float: left; } <div class="text-red float-left"> Utility Classes Approach </div>
  107. 107. Future-Proofing Your JavaScript Framework Decision - @JohnRiv1 0 7 Example adapted from https://tailwindcss.com/docs/what-is-tailwind/ <div class="bg-white mx-auto max-w-sm shadow-lg rounded-lg overflow-hidden"> <div class="sm:flex sm:items-center px-6 py-4"> <img class="block h-16 sm:h-24 rounded-full mx-auto mb-4 sm:mb-0 sm:mr-4 sm:ml-0" src="johnriv.jpg" alt=""> <div class="text-center sm:text-left sm:flex-grow"> <div class="mb-4"> <p class="text-xl leading-tight">John Riviello</p> <p class="text-sm leading-tight text-grey-dark">Maker of web things</p> </div> <div> <button class="text-xs font-semibold rounded-full px-4 py-1 leading-normal bg- white border border-purple text-purple hover:bg-purple hover:text-white">Message</ button></div></div></div></div>
  108. 108. 😱
  109. 109. Future-Proofing Your JavaScript Framework Decision - @JohnRiv1 0 9 Tweet source: https://twitter.com/sindresorhus/status/1089075390327316480
  110. 110. © JOHN RIVIELLO
  111. 111. © JOHN RIVIELLO
  112. 112. Future-Proofing Your JavaScript Framework Decision - @JohnRiv1 1 2 “MAN SITTING ON GRASS FIELD” BY PIXABAY LICENSED BY CC0
  113. 113. Future-Proofing Your JavaScript Framework Decision - @JohnRiv1 1 3 Tweet source: https://twitter.com/dan_abramov/status/1089208929572319232
  114. 114. Future-Proofing Your JavaScript Framework Decision - @JohnRiv1 1 4 “WHITE AND GREY KITTEN SMELLING WHITE DAISY FLOWER” BY ALEX BARGAIN LICENSED BY PEXELS.COM
  115. 115. Future-Proofing Your JavaScript Framework Decision - @JohnRiv1 1 5 CSS: 😁 Easy to add 📈 😬 Hard to remove SOLUTION? TAILWIND AND…
  116. 116. Future-Proofing Your JavaScript Framework Decision - @JohnRiv1 1 6 Purgecss https://www.purgecss.com
  117. 117. Future-Proofing Your JavaScript Framework Decision - @JohnRiv1 1 7 CSSSTATS.COM RESULTS Current Web App Tailwind + PurgeCSS RULES 6,260 289 SELECTORS 8,422 336 DECLARATIONS 29,100 440 PROPERTIES 171 129 FONT-SIZE 1,939 13 WIDTH 682 20 HEIGHT 578 12 COLOR 2,322 44
  118. 118. 🤔
  119. 119. Future-Proofing Your JavaScript Framework Decision - @JohnRiv1 1 9 USING TAILWIND “HELLO WORLD” npm install tailwindcss --save-dev styles.css: @tailwind base; /* Collection of CSS Reset rules */ @tailwind components; /* Container Styles */ @tailwind utilities; /* Classes you’ll use */ npx tailwind build styles.css -o output.css
  120. 120. Future-Proofing Your JavaScript Framework Decision - @JohnRiv1 2 0 USING TAILWIND OUTPUT.CSS FROM @TAILWIND COMPONENTS: .container { width: 100%; } @media (min-width: 640px) { .container { max-width: 640px; } } @media (min-width: 768px) { .container { max-width: 768px; } } @media (min-width: 1024px) { .container { max-width: 1024px; } } @media (min-width: 1280px) { .container { max-width: 1280px; } }
  121. 121. Future-Proofing Your JavaScript Framework Decision - @JohnRiv1 2 1 USING TAILWIND OUTPUT.CSS FROM @TAILWIND COMPONENTS: .container { width: 100%; } @media (min-width: 640px) { .container { max-width: 640px; } } @media (min-width: 768px) { .container { max-width: 768px; } } @media (min-width: 1024px) { .container { max-width: 1024px; } } @media (min-width: 1280px) { .container { max-width: 1280px; } } Markup in your HTML: <div class="container"> container content </div> container content
  122. 122. Future-Proofing Your JavaScript Framework Decision - @JohnRiv1 2 2 USING TAILWIND OUTPUT.CSS FROM @TAILWIND COMPONENTS: .container { width: 100%; } @media (min-width: 640px) { .container { max-width: 640px; } } @media (min-width: 768px) { .container { max-width: 768px; } } @media (min-width: 1024px) { .container { max-width: 1024px; } } @media (min-width: 1280px) { .container { max-width: 1280px; } } Markup in your HTML: <div class="container mx-auto"> container content </div> container content
  123. 123. Future-Proofing Your JavaScript Framework Decision - @JohnRiv1 2 3 USING TAILWIND OUTPUT.CSS FROM @TAILWIND COMPONENTS: .container { width: 100%; } @media (min-width: 640px) { .container { max-width: 640px; } } @media (min-width: 768px) { .container { max-width: 768px; } } @media (min-width: 1024px) { .container { max-width: 1024px; } } @media (min-width: 1280px) { .container { max-width: 1280px; } } Markup in your HTML: <div class="container mx-auto px-8"> container content </div> container content
  124. 124. Future-Proofing Your JavaScript Framework Decision - @JohnRiv Markup in your HTML: <div class="container"> container content </div> OUTPUT.CSS FROM @TAILWIND COMPONENTS: .container { width: 100%; margin-right: auto; margin-left: auto; padding-right: 2rem; padding-left: 2rem; } @media (min-width: 640px) { .container { max-width: 640px; } } @media (min-width: 768px) { .container { max-width: 768px; } } @media (min-width: 1024px) { .container { max-width: 1024px; } } ... 1 2 4 USING TAILWIND container content tailwind.config.js: module.exports = { theme: { container: { center: true, padding: '2rem', }, } } OR SET IN CONFIGURATION:
  125. 125. Future-Proofing Your JavaScript Framework Decision - @JohnRiv1 2 5 USING TAILWIND OUTPUT.CSS FROM @TAILWIND UTILITIES: .appearance-none { -webkit-appearance: none; -moz-appearance: none; appearance: none; } .bg-fixed { background-attachment: fixed; } .bg-local { background-attachment: local; } .bg-scroll { background-attachment: scroll; } .bg-bottom { background-position: bottom; } .bg-center { background-position: center; } .bg-left { background-position: left; } .bg-left-bottom { background-position: left bottom; } .bg-left-top { background-position: left top; } .bg-right { background-position: right; } .bg-right-bottom { background-position: right bottom; } .bg-right-top { background-position: right top; } .bg-top { background-position: top; } .bg-repeat { background-repeat: repeat; } .bg-no-repeat { background-repeat: no-repeat; } .bg-repeat-x { background-repeat: repeat-x; } .bg-repeat-y { background-repeat: repeat-y; } ...
  126. 126. Future-Proofing Your JavaScript Framework Decision - @JohnRiv1 2 6 USING TAILWIND OUTPUT.CSS FROM @TAILWIND UTILITIES - RESPONSIVE VARIANTS: @media (min-width: 640px) { .sm:appearance-none { -webkit-appearance: none; -moz-appearance: none; appearance: none; } .sm:bg-fixed { background-attachment: fixed; } .sm:bg-local { background-attachment: local; } .sm:bg-scroll { background-attachment: scroll; } .sm:bg-bottom { background-position: bottom; } .sm:bg-center { background-position: center; } .sm:bg-left { background-position: left; } .sm:bg-left-bottom { background-position: left bottom; } .sm:bg-left-top { background-position: left top; } .sm:bg-right { background-position: right; } .sm:bg-right-bottom { background-position: right bottom; } .sm:bg-right-top { background-position: right top; } .sm:bg-top { background-position: top; } .sm:bg-repeat { background-repeat: repeat; } .sm:bg-no-repeat { background-repeat: no-repeat; } .sm:bg-repeat-x { background-repeat: repeat-x; } .sm:bg-repeat-y { background-repeat: repeat-y; } ...
  127. 127. Future-Proofing Your JavaScript Framework Decision - @JohnRiv1 2 7 USING TAILWIND OUTPUT.CSS FROM @TAILWIND UTILITIES - RESPONSIVE VARIANTS: @media (min-width: 640px) { .sm:appearance-none { -webkit-appearance: none; -moz-appearance: none; appearance: none; } .sm:bg-fixed { background-attachment: fixed; } .sm:bg-local { background-attachment: local; } .sm:bg-scroll { background-attachment: scroll; } .sm:bg-bottom { background-position: bottom; } .tablet:bg-center { background-position: center; } .sm:bg-left { background-position: left; } .sm:bg-left-bottom { background-position: left bottom; } .sm:bg-left-top { background-position: left top; } .sm:bg-right { background-position: right; } .sm:bg-right-bottom { background-position: right bottom; } .tablet:bg-right-top { background-position: right top; } .tablet:bg-top { background-position: top; } .tablet:bg-repeat { background-repeat: repeat; } .tablet:bg-no-repeat { background-repeat: no-repeat; } .tablet:bg-repeat-x { background-repeat: repeat-x; } .tablet:bg-repeat-y { background-repeat: repeat-y; } ... tailwind.config.js: module.exports = { theme: { screens: { 'tablet': '640px', // => @media (min-width: 640px) { ... } 'laptop': '1024px', // => @media (min-width: 1024px) { ... } 'desktop': '1280px', // => @media (min-width: 1280px) { ... } } } } CAN MODIFY IN CONFIGURATION:
  128. 128. Future-Proofing Your JavaScript Framework Decision - @JohnRiv1 2 8 USING TAILWIND OUTPUT.CSS FROM @TAILWIND UTILITIES - DEFAULT COLOR PALETTE: .bg-transparent { background-color: transparent; } .bg-black { background-color: #000; } .bg-white { background-color: #fff; } .bg-gray-100 { background-color: #f7fafc; } .bg-gray-200 { background-color: #edf2f7; } .bg-gray-300 { background-color: #e2e8f0; } .bg-gray-400 { background-color: #cbd5e0; } .bg-gray-500 { background-color: #a0aec0; } .bg-gray-600 { background-color: #718096; } .bg-gray-700 { background-color: #4a5568; } .bg-gray-800 { background-color: #2d3748; } .bg-gray-900 { background-color: #1a202c; } .bg-red-100 { background-color: #fff5f5; } .bg-red-200 { background-color: #fed7d7; } .bg-red-300 { background-color: #feb2b2; } .bg-red-400 { background-color: #fc8181; } .bg-red-500 { background-color: #f56565; } .bg-red-600 { background-color: #e53e3e; } ... MANY, MANY MORE!
  129. 129. Future-Proofing Your JavaScript Framework Decision - @JohnRiv1 2 9 USING TAILWIND OUTPUT.CSS FROM @TAILWIND UTILITIES - CUSTOMIZED COLOR PALETTE: .bg-transparent { background-color: transparent; } .bg-black { background-color: #000; } .bg-white { background-color: #fff; } .bg-gray-100 { background-color: #f7fafc; } .bg-gray-200 { background-color: #edf2f7; } .bg-gray-300 { background-color: #e2e8f0; } .bg-indigo { background-color: #5c6ac4; } .bg-blue { background-color: #007ace; } .bg-red { background-color: #de3618; } tailwind.config.js: module.exports = { theme: { colors: { indigo: '#5c6ac4', blue: '#007ace', red: '#de3618', } } } CAN MODIFY IN CONFIGURATION:
  130. 130. Future-Proofing Your JavaScript Framework Decision - @JohnRiv1 3 0 USING TAILWIND OUTPUT.CSS FROM @TAILWIND UTILITIES - STATE VARIANTS: .bg-transparent { background-color: transparent; } .bg-black { background-color: #000; } .bg-white { background-color: #fff; } .bg-gray-100 { background-color: #f7fafc; } .bg-gray-200 { background-color: #edf2f7; } .bg-gray-300 { background-color: #e2e8f0; } .bg-indigo { background-color: #5c6ac4; } .bg-blue { background-color: #007ace; } .bg-red { background-color: #de3618; } .hover:bg-indigo:hover { background-color: #5c6ac4; } .hover:bg-blue:hover { background-color: #007ace; } .hover:bg-red:hover { background-color: #de3618; } .focus:bg-indigo:focus { background-color: #5c6ac4; } .focus:bg-blue:focus { background-color: #007ace; } .focus:bg-red:focus { background-color: #de3618; } tailwind.config.js: module.exports = { theme: { colors: { indigo: '#5c6ac4', blue: '#007ace', red: '#de3618', } } } CAN MODIFY IN CONFIGURATION:
  131. 131. Future-Proofing Your JavaScript Framework Decision - @JohnRiv OUTPUT.CSS FROM @TAILWIND UTILITIES - STATE VARIANTS: .bg-transparent { background-color: transparent; } .bg-black { background-color: #000; } .bg-white { background-color: #fff; } .bg-gray-100 { background-color: #f7fafc; } .bg-gray-200 { background-color: #edf2f7; } .bg-gray-300 { background-color: #e2e8f0; } Ooh pretty colors! 1 3 1 USING TAILWIND .bg-indigo { background-color: #5c6ac4; } .bg-blue { background-color: #007ace; } .bg-red { background-color: #de3618; } .hover:bg-indigo:hover { background-color: #5c6ac4; } .hover:bg-blue:hover { background-color: #007ace; } .hover:bg-red:hover { background-color: #de3618; } .focus:bg-indigo:focus { background-color: #5c6ac4; } .focus:bg-blue:focus { background-color: #007ace; } .focus:bg-red:focus { background-color: #de3618; } tailwind.config.js: module.exports = { theme: { colors: { indigo: '#5c6ac4', blue: '#007ace', red: '#de3618', } } } CAN MODIFY IN CONFIGURATION: Markup in your HTML: <button class="bg-indigo hover:bg-blue focus:bg-red"> Ooh pretty colors! </button>
  132. 132. Future-Proofing Your JavaScript Framework Decision - @JohnRiv OUTPUT.CSS FROM @TAILWIND UTILITIES - STATE VARIANTS: .bg-transparent { background-color: transparent; } .bg-black { background-color: #000; } .bg-white { background-color: #fff; } .bg-gray-100 { background-color: #f7fafc; } .bg-gray-200 { background-color: #edf2f7; } .bg-gray-300 { background-color: #e2e8f0; } Ooh pretty colors! 1 3 2 USING TAILWIND .bg-indigo { background-color: #5c6ac4; } .bg-blue { background-color: #007ace; } .bg-red { background-color: #de3618; } .hover:bg-indigo:hover { background-color: #5c6ac4; } .hover:bg-blue:hover { background-color: #007ace; } .hover:bg-red:hover { background-color: #de3618; } .focus:bg-indigo:focus { background-color: #5c6ac4; } .focus:bg-blue:focus { background-color: #007ace; } .focus:bg-red:focus { background-color: #de3618; } tailwind.config.js: module.exports = { theme: { colors: { indigo: '#5c6ac4', blue: '#007ace', red: '#de3618', } } } CAN MODIFY IN CONFIGURATION: Markup in your HTML: <button class="bg-indigo hover:bg-blue focus:bg-red"> Ooh pretty colors! </button>
  133. 133. Future-Proofing Your JavaScript Framework Decision - @JohnRiv OUTPUT.CSS FROM @TAILWIND UTILITIES - STATE VARIANTS: .bg-transparent { background-color: transparent; } .bg-black { background-color: #000; } .bg-white { background-color: #fff; } .bg-gray-100 { background-color: #f7fafc; } .bg-gray-200 { background-color: #edf2f7; } .bg-gray-300 { background-color: #e2e8f0; } Ooh pretty colors! 1 3 3 USING TAILWIND .bg-indigo { background-color: #5c6ac4; } .bg-blue { background-color: #007ace; } .bg-red { background-color: #de3618; } .hover:bg-indigo:hover { background-color: #5c6ac4; } .hover:bg-blue:hover { background-color: #007ace; } .hover:bg-red:hover { background-color: #de3618; } .focus:bg-indigo:focus { background-color: #5c6ac4; } .focus:bg-blue:focus { background-color: #007ace; } .focus:bg-red:focus { background-color: #de3618; } tailwind.config.js: module.exports = { theme: { colors: { indigo: '#5c6ac4', blue: '#007ace', red: '#de3618', } } } CAN MODIFY IN CONFIGURATION: Markup in your HTML: <button class="bg-indigo hover:bg-blue focus:bg-red"> Ooh pretty colors! </button>
  134. 134. Future-Proofing Your JavaScript Framework Decision - @JohnRiv YOUR CSS FUTURE? 1 3 4 Purgecss =+ LINKS • Tailwind Docs: https://next.tailwindcss.com/ • PurgeCSS: https://www.purgecss.com/ • Tailwind Container: https://next.tailwindcss.com/docs/container/ • Tailwind Configuration: https://next.tailwindcss.com/docs/configuration • Tailwind Responsive Design: https://next.tailwindcss.com/docs/responsive-design • Tailwind Colors: https://next.tailwindcss.com/docs/colors • Tailwind State Variants: https://next.tailwindcss.com/docs/state-variants/ 📉
  135. 135. DEMO PAGES
  136. 136. DDD
  137. 137. DEMO DRIVEN DEVELOPMENT
  138. 138. Future-Proofing Your JavaScript Framework Decision - @JohnRiv1 3 8 https://react-styleguidist.js.org/examples/basic/
  139. 139. Future-Proofing Your JavaScript Framework Decision - @JohnRiv1 3 9 https://react-styleguidist.js.org/docs/documenting.html
  140. 140. A FRAMEWORK FOR CHOOSING YOUR FRAMEWORK
  141. 141. Future-Proofing Your JavaScript Framework Decision - @JohnRiv1 4 1 “LANDSCAPE PHOTOGRAPHY OF FACTORY” BY PIXABAY LICENSED BY CC0
  142. 142. Future-Proofing Your JavaScript Framework Decision - @JohnRiv1 4 2 ANALYTIC HIERARCHY PROCESS by Thomas L. Saaty
  143. 143. Future-Proofing Your JavaScript Framework Decision - @JohnRiv1 4 3 ANALYTIC HIERARCHY PROCESS (AHP) Goal: Criteria: Alternatives: CHOOSE THE MOST SUITABLE LEADER CHARISMA RAMÓN EDUCATIONEXPERIENCE INTEGRITY KATE PAUL
  144. 144. Future-Proofing Your JavaScript Framework Decision - @JohnRiv1 4 4 ANALYTIC HIERARCHY PROCESS (AHP) Goal: Criteria: Alternatives: CHOOSE THE MOST SUITABLE LEADER CHARISMA RAMÓN EDUCATIONEXPERIENCE INTEGRITY KATE PAUL
  145. 145. Future-Proofing Your JavaScript Framework Decision - @JohnRiv1 4 5 AHP FUNDAMENTAL SCALE FOR PAIRWISE COMPARISONS Intensity of Importance Definition Explanation 1 Equal importance Two elements contribute equally to the objective 3 Moderate importance Experience and judgement moderately favor one element over another 5 Strong importance Experience and judgement strongly favor one element over another 7 Very strong importance One element is favored very strongly over another; its dominance is demonstrated in practice 9 Extreme importance The evidence favoring one element 
 over another is of the highest possible order of affirmation https://en.wikipedia.org/wiki/Analytic_hierarchy_process_–_leader_example#Pairwise_comparisons Intensities of 2, 4, 6, and 8 can be used to express intermediate values. 1.1, 1.2, 1.3, etc. can be used for elements that are very close in importance.
  146. 146. Future-Proofing Your JavaScript Framework Decision - @JohnRiv1 4 6 AHP PAIRWISE SCORING https://en.wikipedia.org/wiki/Analytic_hierarchy_process_–_leader_example#Alternatives_vs._criteria Alternatives compared with respect to EXPERIENCE RAMÓN 1 KATE 4 RAMÓN 4 PAUL 1 KATE 9 PAUL 1
  147. 147. Future-Proofing Your JavaScript Framework Decision - @JohnRiv1 4 7 AHP RECIPROCAL SCORING EXPERIENCE RAMÓN KATE PAUL RAMÓN 1 1/4 4 KATE 4 1 9 PAUL 1/4 1/9 1 https://en.wikipedia.org/wiki/Analytic_hierarchy_process_–_leader_example#Alternatives_vs._criteria
  148. 148. Future-Proofing Your JavaScript Framework Decision - @JohnRiv1 4 8 AHP MATRIX PRIORITY CALCULATIONS EXPERIENCE RAMÓN KATE PAUL PRIORITY RAMÓN 1 1/4 4 0.2 1 7 KATE 4 1 9 0.7 1 7 PAUL 1/4 1/9 1 0.066 https://en.wikipedia.org/wiki/Analytic_hierarchy_process_–_leader_example#Alternatives_vs._criteria
  149. 149. Future-Proofing Your JavaScript Framework Decision - @JohnRiv1 4 9 AHP MATRIX PRIORITY CALCULATIONS EXPERIENCE RAMÓN KATE PAUL PRIORITY RAMÓN 1 1/4 4 0.2 1 7 KATE 4 1 9 0.7 1 7 PAUL 1/4 1/9 1 0.066 https://en.wikipedia.org/wiki/Analytic_hierarchy_process_–_leader_example#Alternatives_vs._criteria
  150. 150. Future-Proofing Your JavaScript Framework Decision - @JohnRiv1 5 0 ANALYTIC HIERARCHY PROCESS (AHP) Goal: Criteria: Alternatives: CHOOSE THE MOST SUITABLE LEADER CHARISMA RAMÓN EDUCATIONEXPERIENCE INTEGRITY KATE PAUL 0.217 0.717 0.066
  151. 151. Future-Proofing Your JavaScript Framework Decision - @JohnRiv1 5 1 ANALYTIC HIERARCHY PROCESS (AHP) Goal: Criteria: Alternatives: CHOOSE THE MOST SUITABLE LEADER CHARISMA RAMÓN EDUCATIONEXPERIENCE INTEGRITY KATE PAUL
  152. 152. Future-Proofing Your JavaScript Framework Decision - @JohnRiv1 5 2 ANALYTIC HIERARCHY PROCESS (AHP) Goal: Criteria: Alternatives: CHOOSE THE MOST SUITABLE LEADER EDUCATIONEXPERIENCE INTEGRITYCHARISMA RAMÓN KATE PAUL
  153. 153. Future-Proofing Your JavaScript Framework Decision - @JohnRiv1 5 3 ANALYTIC HIERARCHY PROCESS (AHP) Goal: Criteria: Alternatives: CHOOSE THE MOST SUITABLE LEADER CHARISMAEDUCATIONEXPERIENCE RAMÓN INTEGRITY KATE PAUL
  154. 154. Future-Proofing Your JavaScript Framework Decision - @JohnRiv1 5 4 ANALYTIC HIERARCHY PROCESS (AHP) Goal: Criteria: Alternatives: CHOOSE THE MOST SUITABLE LEADER CHARISMAEDUCATIONEXPERIENCE RAMÓN INTEGRITY KATE PAUL
  155. 155. Future-Proofing Your JavaScript Framework Decision - @JohnRiv1 5 5 AHP MATRIX PRIORITY CALCULATIONS CRITERIA EXPERIENCE EDUCATION CHARISMA INTEGRITY PRIORITY EXPERIENCE 1 4 3 7 0.547 EDUCATION 1/4 1 1/3 3 0.127 CHARISMA 1/3 3 1 5 0.270 INTEGRITY 1/7 1/3 1/5 1 0.056 https://en.wikipedia.org/wiki/Analytic_hierarchy_process_–_leader_example#Criteria_vs._the_Goal
  156. 156. Future-Proofing Your JavaScript Framework Decision - @JohnRiv1 5 6 ANALYTIC HIERARCHY PROCESS (AHP) Goal: Criteria: Alternatives: CHOOSE THE MOST SUITABLE LEADER CHARISMA RAMÓN EDUCATIONEXPERIENCE INTEGRITY KATE PAUL
  157. 157. Future-Proofing Your JavaScript Framework Decision - @JohnRiv1 5 7 AHP MATRIX PRIORITY CALCULATIONS CRITERIA EXPERIENCE EDUCATION CHARISMA INTEGRITY PRIORITY EXPERIENCE 1 4 3 7 0.547 EDUCATION 1/4 1 1/3 3 0.127 CHARISMA 1/3 3 1 5 0.270 INTEGRITY 1/7 1/3 1/5 1 0.056 https://en.wikipedia.org/wiki/Analytic_hierarchy_process_–_leader_example#Criteria_vs._the_Goal
  158. 158. Future-Proofing Your JavaScript Framework Decision - @JohnRiv1 5 8 ANALYTIC HIERARCHY PROCESS (AHP) Goal: Criteria: Alternatives: CHOOSE THE MOST SUITABLE LEADER CHARISMA RAMÓN EDUCATIONEXPERIENCE INTEGRITY KATE PAUL 0.547
  159. 159. Future-Proofing Your JavaScript Framework Decision - @JohnRiv1 5 9 AHP MATRIX PRIORITY CALCULATIONS EXPERIENCE RAMÓN KATE PAUL PRIORITY RAMÓN 1 1/4 4 0.2 1 7 KATE 4 1 9 0.7 1 7 PAUL 1/4 1/9 1 0.066 https://en.wikipedia.org/wiki/Analytic_hierarchy_process_–_leader_example#Alternatives_vs._criteria
  160. 160. Future-Proofing Your JavaScript Framework Decision - @JohnRiv1 6 0 ANALYTIC HIERARCHY PROCESS (AHP) Goal: Criteria: Alternatives: CHOOSE THE MOST SUITABLE LEADER CHARISMA RAMÓN EDUCATIONEXPERIENCE INTEGRITY KATE PAUL 0.547 0.217 0.717 0.066
  161. 161. Future-Proofing Your JavaScript Framework Decision - @JohnRiv1 6 1 AHP FINAL PRIORITY CALCULATIONS EXPERIENCE PRIORITY PRIORITY
 vs. GOAL PRIORITY with respect to EXPERIENCE RAMÓN 0.2 1 7 KATE 0.7 1 7 PAUL 0.066 https://en.wikipedia.org/wiki/Analytic_hierarchy_process_–_leader_example#Synthesizing_final_priorities
  162. 162. Future-Proofing Your JavaScript Framework Decision - @JohnRiv1 6 2 ANALYTIC HIERARCHY PROCESS (AHP) Goal: Criteria: Alternatives: CHOOSE THE MOST SUITABLE LEADER CHARISMA RAMÓN EDUCATIONEXPERIENCE INTEGRITY KATE PAUL 0.547 0.217 0.717 0.066
  163. 163. Future-Proofing Your JavaScript Framework Decision - @JohnRiv1 6 3 AHP FINAL PRIORITY CALCULATIONS EXPERIENCE PRIORITY PRIORITY
 vs. GOAL PRIORITY with respect to EXPERIENCE RAMÓN 0.2 1 7 0.547 KATE 0.7 1 7 0.547 PAUL 0.066 0.547 https://en.wikipedia.org/wiki/Analytic_hierarchy_process_–_leader_example#Synthesizing_final_priorities
  164. 164. Future-Proofing Your JavaScript Framework Decision - @JohnRiv1 6 4 AHP FINAL PRIORITY CALCULATIONS EXPERIENCE PRIORITY PRIORITY
 vs. GOAL PRIORITY with respect to EXPERIENCE RAMÓN 0.2 1 7 0.547 KATE 0.7 1 7 0.547 PAUL 0.066 0.547 https://en.wikipedia.org/wiki/Analytic_hierarchy_process_–_leader_example#Synthesizing_final_priorities x x x
  165. 165. Future-Proofing Your JavaScript Framework Decision - @JohnRiv1 6 5 AHP FINAL PRIORITY CALCULATIONS EXPERIENCE PRIORITY PRIORITY
 vs. GOAL PRIORITY with respect to EXPERIENCE RAMÓN 0.2 1 7 0.547 0.1 1 9 KATE 0.7 1 7 0.547 0.392 PAUL 0.066 0.547 0.036 https://en.wikipedia.org/wiki/Analytic_hierarchy_process_–_leader_example#Synthesizing_final_priorities x x x = = =
  166. 166. Future-Proofing Your JavaScript Framework Decision - @JohnRiv1 6 6 AHP FINAL PRIORITY CALCULATIONS EXPERIENCE PRIORITY PRIORITY
 vs. GOAL PRIORITY with respect to EXPERIENCE RAMÓN 0.2 1 7 0.547 0.1 1 9 KATE 0.7 1 7 0.547 0.392 PAUL 0.066 0.547 0.036 https://en.wikipedia.org/wiki/Analytic_hierarchy_process_–_leader_example#Synthesizing_final_priorities x x x = = =
  167. 167. Future-Proofing Your JavaScript Framework Decision - @JohnRiv1 6 7 AHP FINAL PRIORITY CALCULATIONS CANDIDATE PRIORITY with respect to EXPERIENCE PRIORITY with respect to EDUCATION PRIORITY with respect to CHARISMA PRIORITY with respect to INTEGRITY PRIORITY with respect to GOAL RAMÓN KATE PAUL https://en.wikipedia.org/wiki/Analytic_hierarchy_process_–_leader_example#Synthesizing_final_priorities
  168. 168. Future-Proofing Your JavaScript Framework Decision - @JohnRiv1 6 8 AHP FINAL PRIORITY CALCULATIONS CANDIDATE PRIORITY with respect to EXPERIENCE PRIORITY with respect to EDUCATION PRIORITY with respect to CHARISMA PRIORITY with respect to INTEGRITY PRIORITY with respect to GOAL RAMÓN 0.1 1 9 KATE 0.392 PAUL 0.036 https://en.wikipedia.org/wiki/Analytic_hierarchy_process_–_leader_example#Synthesizing_final_priorities
  169. 169. Future-Proofing Your JavaScript Framework Decision - @JohnRiv1 6 9 AHP FINAL PRIORITY CALCULATIONS CANDIDATE PRIORITY with respect to EXPERIENCE PRIORITY with respect to EDUCATION PRIORITY with respect to CHARISMA PRIORITY with respect to INTEGRITY PRIORITY with respect to GOAL RAMÓN 0.1 1 9 0.024 0.201 0.015 KATE 0.392 0.010 0.052 0.038 PAUL 0.036 0.093 0.017 0.004 https://en.wikipedia.org/wiki/Analytic_hierarchy_process_–_leader_example#Synthesizing_final_priorities
  170. 170. Future-Proofing Your JavaScript Framework Decision - @JohnRiv1 7 0 AHP FINAL PRIORITY CALCULATIONS CANDIDATE PRIORITY with respect to EXPERIENCE PRIORITY with respect to EDUCATION PRIORITY with respect to CHARISMA PRIORITY with respect to INTEGRITY PRIORITY with respect to GOAL RAMÓN 0.1 1 9 0.024 0.201 0.015 KATE 0.392 0.010 0.052 0.038 PAUL 0.036 0.093 0.017 0.004 https://en.wikipedia.org/wiki/Analytic_hierarchy_process_–_leader_example#Synthesizing_final_priorities = = = + + + + + + + + +
  171. 171. Future-Proofing Your JavaScript Framework Decision - @JohnRiv1 7 1 AHP FINAL PRIORITY CALCULATIONS CANDIDATE PRIORITY with respect to EXPERIENCE PRIORITY with respect to EDUCATION PRIORITY with respect to CHARISMA PRIORITY with respect to INTEGRITY PRIORITY with respect to GOAL RAMÓN 0.1 1 9 0.024 0.201 0.015 0.358 KATE 0.392 0.010 0.052 0.038 0.492 PAUL 0.036 0.093 0.017 0.004 0.149 https://en.wikipedia.org/wiki/Analytic_hierarchy_process_–_leader_example#Synthesizing_final_priorities = = = + + + + + + + + +
  172. 172. Future-Proofing Your JavaScript Framework Decision - @JohnRiv1 7 2 AHP FINAL PRIORITY CALCULATIONS CANDIDATE PRIORITY with respect to EXPERIENCE PRIORITY with respect to EDUCATION PRIORITY with respect to CHARISMA PRIORITY with respect to INTEGRITY PRIORITY with respect to GOAL RAMÓN 0.1 1 9 0.024 0.201 0.015 0.358 KATE 0.392 0.010 0.052 0.038 0.492 PAUL 0.036 0.093 0.017 0.004 0.149 https://en.wikipedia.org/wiki/Analytic_hierarchy_process_–_leader_example#Synthesizing_final_priorities = = = + + + + + + + + +
  173. 173. “SURVEY ICON” BY PIXABAY LICENSED BY CC0
  174. 174. Future-Proofing Your JavaScript Framework Decision - @JohnRiv1 7 4 “FOUR PERSON HOLDING BULB LIGHT DECORS” BY RAWPIXEL.COM LICENSED BY PEXELS.COM
  175. 175. Future-Proofing Your JavaScript Framework Decision - @JohnRiv1 7 5 “HAWAII HANA ROAD” BY PIXABAY LICENSED BY CC0
  176. 176. Future-Proofing Your JavaScript Framework Decision - @JohnRiv1 7 6 “WELCOME TO HANA” BY KIRT EDBLOM LICENSED BY CC BY-SA 2.0
  177. 177. Future-Proofing Your JavaScript Framework Decision - @JohnRiv1 7 7 “HANA BEACH PARK” BY TRAVIS THURSTON LICENSED BY CC BY-SA 3.0
  178. 178. Future-Proofing Your JavaScript Framework Decision - @JohnRiv1 7 8 “HANA BEACH PARK” BY TRAVIS THURSTON LICENSED BY CC BY-SA 3.0 IT’S THE JOURNEY, NOT THE DESTINATION
  179. 179. Future-Proofing Your JavaScript Framework Decision - @JohnRiv1 7 9 “HANA BEACH PARK” BY TRAVIS THURSTON LICENSED BY CC BY-SA 3.0 IT’S THE JOURNEY, AND THE DESTINATION
  180. 180. HOW DID OUR TEAM DECIDE?
  181. 181. Future-Proofing Your JavaScript Framework Decision - @JohnRiv1 8 1 OUR JS FRAMEWORK CRITERIA •Community •Performance •Redux compatibility •Web Components support •Localization •Developer Productivity •Hybrid App Support
  182. 182. Future-Proofing Your JavaScript Framework Decision - @JohnRiv1 8 2 OUR JS FRAMEWORK CRITERIA (WEIGHTED)
  183. 183. Future-Proofing Your JavaScript Framework Decision - @JohnRiv1 8 3 OUR JS FRAMEWORK DECISION Option 1: Option 2: Option 3:
  184. 184. Future-Proofing Your JavaScript Framework Decision - @JohnRiv1 8 4 OUR JS FRAMEWORK DECISION Option 1: Option 2: Option 3: Try it with your team! http://github.com/ComcastSamples/ahp-tool
  185. 185. Future-Proofing Your JavaScript Framework Decision - @JohnRiv1 8 5 TAKEAWAYS • Build with a Sacrificial Architecture • Use Redux (or similar unidirectional data flow) • Use Tailwind with PurgeCSS • Demo Driven Development • Use the Analytic Hierarchy Process for decisions LINKS • https://redux.js.org/ • https://redux-observable.js.org/ • https://tailwindcss.com • https://www.purgecss.com/ • http://github.com/ComcastSamples/ahp-tool THANK YOU! Please send comments, questions, or feedback to me at @JohnRiv

×