O slideshow foi denunciado.
Utilizamos seu perfil e dados de atividades no LinkedIn para personalizar e exibir anúncios mais relevantes. Altere suas preferências de anúncios quando desejar.

Изоморфные react-приложения

3.112 visualizações

Publicada em

Доклад, с которым я выступал 23 ноября 2015 г. на первом React Moscow Meetup.

Publicada em: Tecnologia

Изоморфные react-приложения

  1. 1. Изоморфные
 React-приложения Денис Измайлов 23 ноября 2015
  2. 2. Денис Измайлов • 15 лет опыта разработки ПО и web • Последние 5 лет полностью Front-end, Node.js и архитектуре • Более 10 проектов, в т.ч. много SPA, highload и React • Коммиты в Redux, webpack и koa • Спикер HighLoad++ 2015, MoscowJS • Автор статей на Habrahabr и англоязычных ресурсах , CEO
  3. 3. Почему от классического Single Page Application необходимо отказаться?
  4. 4. Как изоморфные приложения отразятся на Вашей зарплате?
  5. 5. Что вы будете делать
 на этих выходных?
  6. 6. Вы уже знаете 1. React 14 2. webpack 3. ES6 4. Node.js 5. Express / koa 6. Isomorphic (Universal) apps 6
  7. 7. Часть 1
  8. 8. Web стал очень большим
  9. 9. Искусство
 Разработка под Web
 
 Наука
  10. 10. Раньше было просто • Создал страницу • Добавил пару скриптов • Отправил в Production
  11. 11. Раньше было просто Сервер Браузер 11
  12. 12. Раньше было просто Сервер Браузер Делал всё 12
  13. 13. Раньше было просто Сервер Браузер - HTML - [CSS, JavaScript] Делал всё 13
  14. 14. Это работало
  15. 15. Single Page
 Applications
 (SPA)
  16. 16. Single Page Application Сервер Браузер 16
  17. 17. Single Page Application Сервер Браузер Страница существует?
 Авторизация нужна?
 Доступ есть? 17
  18. 18. Single Page Application Сервер Браузер Страница существует?
 Авторизация нужна?
 Доступ есть? - Tiny HTML, [CSS] - JavaScript bundle 18
  19. 19. Single Page Application Плюсы • Легко начать • webpack • <div id=“root” /> • React, Redux • build 19
  20. 20. Single Page Application Плюсы • Легко начать • Богатый функционал webpack, <div id=“root” />, React, Redux 20
  21. 21. Single Page Application Плюсы • Легко начать • Богатый функционал • Быстро дорабатывать webpack, <div id=“root” />, React, Redux 21
  22. 22. Single Page Application Плюсы • Легко начать • Богатый функционал • Быстро дорабатывать • Отзывчивый UI webpack, <div id=“root” />, React, Redux 22
  23. 23. Single Page Application Плюсы • Легко начать • Богатый функционал • Быстро дорабатывать • Отзывчивый UI • Удобно кэшировать webpack, <div id=“root” />, React, Redux 23
  24. 24. - Wow. И не одного минуса?
  25. 25. Single Page Application Минусы • Долгая загрузка • JavaScript bundle up to 3-5 Mb • первое обращение • исполнение • память 25
  26. 26. Single Page Application Минусы • Долгая загрузка • Сложность поддержки • side-эффекты • memory leak 1st request, CPU, mem 26
  27. 27. Single Page Application Минусы • Долгая загрузка • Сложность поддержки • Пустая страница, один URL 1st request, CPU, mem side-эффекты, memory leaks 27
  28. 28. Single Page Application Минусы • Долгая загрузка • Сложность поддержки • Пустая страница, один URL • Legacy Browsers 1st request, CPU, mem side-эффекты, memory leaks 28
  29. 29. - Разве это минусы?
  30. 30. Single Page Application Минусы • Долгая загрузка для бизнеса снижение UX 30
  31. 31. Single Page Application Минусы • Долгая загрузка • Сложность поддержки для бизнеса снижение UX риски 31
  32. 32. Single Page Application Минусы • Долгая загрузка • Сложность поддержки • Пустая страница для бизнеса снижение UX риски проблемы SEO 32
  33. 33. Single Page Application Минусы • Долгая загрузка • Сложность поддержки • Пустая страница • Один URL для бизнеса снижение UX риски проблемы SEO проблемы SMM 33
  34. 34. Single Page Application Минусы • Долгая загрузка • Сложность поддержки • Пустая страница • Один URL • Legacy Browsers для бизнеса снижение UX риски проблемы SEO проблемы SMM потеря ЦА 34
  35. 35. Single Page Application Минусы • Долгая загрузка • Сложность поддержки • Пустая страница • Один URL • Legacy Browsers для бизнеса снижение UX риски проблемы SEO проблемы SMM потеря ЦА Расходы
  36. 36. Single Page Application Минусы для бизнеса снижение UX риски проблемы SEO проблемы SMM потеря ЦА Расходы
  37. 37. - WAT? Что делать?
  38. 38. Взять лучшее из обоих миров
  39. 39. Изоморфные приложения
  40. 40. Изоморфные приложения By isomorphic we mean that any given line of code (with notable exceptions) can execute both on the client and the server. 
 Charlie Robbins,
 18 Oct 2011
  41. 41. Шаблоны Стили Локализация Конфигурация Routes Права доступа Модели Схемы Валидация Сервисы Изоморфные приложения server.jsNode.js worker.js client.jsBrowser admin.js Бизнес-логика Компоненты API-интерфейсы Actions, Reducers Static Files
  42. 42. Браузер Изоморфные приложения Front-end сервер Back-end сервер
 
 Database Java
 etc
  43. 43. Браузер Изоморфные приложения Front-end сервер Back-end сервер
 
 Database Java
 etc
  44. 44. Браузер Изоморфные приложения Front-end сервер Back-end сервер
 
 Database Java
 etc - HTML - [critical CSS] - …
  45. 45. Front-end клиент Изоморфные приложения Front-end сервер Back-end сервер
 
 Database Java
 etc - HTML - [critical CSS] - JS Bundle
  46. 46. Front-end клиент Изоморфные приложения Front-end сервер Back-end сервер
 
 Database Java
 etc - HTML - [critical CSS] - JS Bundle
  47. 47. Front-end клиент Изоморфные приложения Front-end сервер • Единая среда исполнения
 • Общая кодовая база
 • Полный контроль
 • Экосистема 47
  48. 48. - Но как?
  49. 49. Server-Side Rendering
 (SSR)
  50. 50. Server-Side Rendering • Сборка HTML на Front-end сервере • Моментальное отображение в браузере, ещё до загрузки JS • Когда JS загрузится, React только добавит обработчики событий • А это очень быстро 50
  51. 51. Server-Side Rendering Код на сервере выглядит очень просто: import ReactDOMServer from 'react-dom/server';
 import Application from './components/application';
 
 const body = ReactDOMServer.renderToString(
 <Application />
 ); 51
  52. 52. Server-Side Rendering 1. Пользователь видит страницу мгновенно 2. Отсутствие дополнительных запросов на получение данных 3. Страница может работать даже без JS 4. Полноценная URL-навигация и мета- тэги 5. Сохранение всех возможностей современного JavaScript 52
  53. 53. Часть 2
  54. 54. Производительность и масштабирование
  55. 55. Масштабирование
  56. 56. Масштабирование
 функциональное
  57. 57. Server-Side Rendering Всё супер, когда данные есть: import ReactDOMServer from 'react-dom/server';
 import Application from './components/application';
 
 const initialState = { siteName: ‘Startup Makers' };
 const body = ReactDOMServer.renderToString(
 <Application state={initialState} />
 ); 57
  58. 58. Server-Side Rendering Всё супер, когда данные есть: import ReactDOMServer from 'react-dom/server';
 import Application from './components/application';
 
 const initialState = { siteName: ‘Startup Makers' };
 const body = ReactDOMServer.renderToString(
 <Application state={initialState} />
 ); Но если их надо получать извне? 58
  59. 59. Server-Side Rendering Как получить асинхронный State:
 1. Вручную для каждой страницы 2. Facebook Relay 3. redux-catch-promise 59
  60. 60. Асинхронный State Вручную для каждой страницы: • Получить State, необходимый для страницы
 • ReactDOMServer.renderToString() 60
  61. 61. Асинхронный State Facebook Relay: 1. The framework for building data-driven React applications 2. Declarative. Colocation. Mutations. 3. https://github.com/facebook/relay/ issues/136 4. 1Q2016 61
  62. 62. Асинхронный State redux-catch-promise: • Redux - state container для React • Redux: the best for isomorphic apps, MoscowJS 25
 https://youtu.be/Uyk_8WWna6s • redux-catch-promise - это middleware для Redux 62
  63. 63. Асинхронный State redux-catch-promise: 1. callback для захвата Promise-экшнов 2. Делаем рендер компонент 3. Из компонент - запрос к БД, отдавая Promise 4. Собираем все эти промисы, ожидаем их завершения 5. Повторный рендер, с данными 63
  64. 64. Асинхронный State redux-catch-promise: 1. Примеры и исходный код:
 https://github.com/DenisIzmaylov/ redux-catch-promise 2. Установка: npm install redux-catch-promise 64
  65. 65. Производительность
  66. 66. Производительность Тестовый стенд: MacBook Pro 15” Retina (Early 2013) 2.4 GHz Intel Core i7 66
  67. 67. Производительность Размер страницы: 56 238 байт
  68. 68. Производительность Размер страницы: 56 238 байт
  69. 69. Производительность Размер страницы: 56 238 байт
  70. 70. Производительность Размер страницы: 56 238 байт
  71. 71. Производительность Размер страницы: 56 238 байт
  72. 72. Производительность Размер страницы: 56 238 байт
  73. 73. Производительность Для теста используем: ab -n 100 http://localhost:3000/profile
 73
  74. 74. Производительность Для теста используем: ab -n 100 http://localhost:3000/profile Запускаем… 74
  75. 75. Производительность Для теста используем: ab -n 100 http://localhost:3000/profile Запускаем… Time per request: 61.850 ms 75
  76. 76. Производительность 61.850 ms
 Это медленно или быстро? 76
  77. 77. Производительность 61.850 ms
 Это медленно или быстро?
 
 Тот же шаблон в Handlebars:
 8.385 ms
 
 86% less 77
  78. 78. Производительность 61.850 ms
 Это медленно или быстро?
 
 Тот же шаблон в Handlebars:
 8.385 ms
 
 86% less 78
  79. 79. Производительность 1. Идём в Google - ничего полезного 2. Пробуем спросить Twitter - тишина: 79
  80. 80. Производительность Ок, а что если? NODE_ENV=production Запускаем… 80
  81. 81. Производительность Ок, а что если? NODE_ENV=production Запускаем… Time per request: 37.943 ms
 (vs 61.850 ms)
 39% less 81
  82. 82. Производительность Вроде лучше.
 
 Но всё ещё не торт. 82
  83. 83. Ищем дальше
  84. 84. GitHub issues
  85. 85. Производительность • “Server rendering is slower with npm react”
 
 https://github.com/facebook/react/issues/812
 
 85
  86. 86. Производительность • “Server rendering is slower with npm react”
 
 https://github.com/facebook/react/issues/812
 
 Решение:
 явно подключать react/dist/react.min.js 86
  87. 87. Производительность Создаём node_modules/react.js:
 
 if (process.env.NODE_ENV === 'production') { module.exports = require('react/dist/react.min.js'); } else { module.exports = require('react/dist/react.js'); }
 87
  88. 88. Производительность Создаём node_modules/react.js:
 
 if (process.env.NODE_ENV === 'production') { module.exports = require('react/dist/react.min.js'); } else { module.exports = require('react/dist/react.js'); }
 88
  89. 89. Как это изменило результат?
  90. 90. Производительность Server rendering is slower with npm react react/dist/react.min.js Запускаем… 90
  91. 91. Производительность Server rendering is slower with npm react react/dist/react.min.js Запускаем… Time per request: 38.253 ms
 (vs 37.943 ms)
 0.08% more 91
  92. 92. Производительность Server rendering is slower with npm react react/dist/react.min.js Запускаем… Time per request: 38.253 ms
 (vs 37.943 ms)
 0.08% more FAILED 92
  93. 93. 0 17,5 35 52,5 70 38,25337,943 8,385 61,85 React SSR Handlebars production react.min.js Результаты
  94. 94. 0 17,5 35 52,5 70 38,25337,943 8,385 61,85 React SSR Handlebars production react.min.js Результаты NODE_ENV=production
 39% less
  95. 95. Часть 3
  96. 96. Продвинутые
 решения
  97. 97. Продвинутые решения 1. Precompilation + Cache 2. Rendering Separation 3. Progressive Rendering 4. Facebook BigPipe 5. HAProxy 97
  98. 98. Precompilation + Cache • UI = f(state) • f = React Component • state = path + [actions] + …
 1. Простое решение: redis 2. “Отложенный рендеринг”:
 redis + kue.js + workers 98
  99. 99. Rendering Separation 99
  100. 100. Progressive Rendering 100
  101. 101. Progressive Rendering • React DOM Stream • Flushing the Document Early • “Streams make this library as much as 47% faster in sending down a full page than ReactDOM.renderToString” • Target - 108KB page on Heroku • Time To First Byte (TTFB) - 55% faster • https://github.com/aickin/react-dom-stream 101
  102. 102. Facebook BigPipe • Сборка страницы в процессе загрузки • Загружается параллельно • Устойчивость к ошибкам
  103. 103. Facebook BigPipe • Сборка страницы в процессе загрузки • Загружается параллельно • Устойчивость к ошибкам
  104. 104. Facebook BigPipe • Сборка страницы в процессе загрузки • Загружается параллельно • Устойчивость к ошибкам
  105. 105. Facebook BigPipe 105
  106. 106. HAProxy • Несколько экземпляров Node.js • Обратитесь к DevOps 106
  107. 107. Эпилог
  108. 108. Рекомендации • Присоединяйтесь
 к сообществу MoscowJS
 http://moscowjs.ru/ • Улучшайте английский, не читайте советских газет • Читайте оригиналы и технические блоги • Активно внедряйте в свою жизнь Twitter и GitHub 108
  109. 109. Полезные материалы 1. Supercharging page load (100 Days of Google Dev)
 https://youtu.be/d5_6yHixpsQ 2. Making Netflix.com Faster
 http://techblog.netflix.com/2015/08/making-netflixcom- faster.html 3. New technologies for the new LinkedIn home page
 https://engineering.linkedin.com/frontend/new-technologies- new-linkedin-home-page 4. Improving performance on Twitter.com
 https://blog.twitter.com/2012/improving-performance-on- twittercom 5. Scaling Isomorphic Javascript Code
 http://blog.nodejitsu.com/scaling-isomorphic-javascript-code/ 109
  110. 110. Полезные материалы 6. From AngularJS to React: The Isomorphic Way
 https://blog.risingstack.com/from-angularjs-to-react-the- isomorphic-way/ 7. Isomorphic JavaScript: The Future of Web Apps
 http://nerds.airbnb.com/isomorphic-javascript-future-web-apps/ 8. React server side rendering performance
 http://www.slideshare.net/nickdreckshage/react-meetup 9. The Lost Art of Progressive HTML Rendering
 http://blog.codinghorror.com/the-lost-art-of-progressive-html- rendering/ 10. Extract and inline Critical Path CSS in HTML pages
 https://github.com/addyosmani/critical 110
  111. 111. Послесловие «Большинство проблем алгоритмов можно решить сменой структуры данных», Андрей Ситник “Changes is our work”,
 Jake Archibald, Google
  112. 112. Почему от классического Single Page Application необходимо отказаться?
  113. 113. izmaylov.dm@gmail.com Присылайте свой мобильный телефон
 и краткую информацию о себе
  114. 114. Спасибо за внимание Денис Измайлов @DenisIzmaylov https://github.com/DenisIzmaylov http://startup-makers.ru denis_izmaylov izmaylov.dm@gmail.com
  115. 115. Приложение 1

×