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.

Как мы разрабатываем новый фронтенд / Филипп Нехаев (Tinkoff.ru)

2,168 views

Published on

Недавно запустили новый сайт Тинькофф.

У нас есть желание поделиться с аудиторией подходом и опытом разработки большого изоморфного приложения на React.js и Flux. Меньше чем за год мы разработали новый сайт и интернет-банк, заложив платформу на ближайшие несколько лет для быстрой разработки фронтенда новых продуктов.

Сейчас tinkoff.ru насчитывает более 3000 компонентов и сотни страниц.

Published in: Engineering
  • Be the first to comment

  • Be the first to like this

Как мы разрабатываем новый фронтенд / Филипп Нехаев (Tinkoff.ru)

  1. 1. Как мы разрабатываем новый фронтенд Tinkoff.ru Филипп Нехаев Архитектор веб-интерфейсов Тинькофф банк
  2. 2. 2 1. О наших задачах 2. Обзор стэков 3. Переиспользование 4. Оптимизация 5. Сборка и деплой
  3. 3. 3 Какие задачи решаем
  4. 4. Сервер Клиент 2011 сайт и Интернет-Банк Java/Spring, JSP, Maven JS, jQuery, Handlebars, Backbone, Maven/Grunt Что было раньше 4
  5. 5. 5 • Два UI-слоя Сервер Java
 JSP Клиент JS
 Handlebars Что было раньше
  6. 6. 6 • Два UI-слоя • Дублирование логики Сервер Java
 JSP Клиент JS
 Handlebars Что было раньше
  7. 7. 7 • Два UI-слоя • Дублирование логики • Две группы разработчиков Сервер Java
 JSP Клиент JS
 Handlebars Что было раньше
  8. 8. 8 • Два UI-слоя • Дублирование логики • Две группы разработчиков • Дорогая поддержка Сервер Java
 JSP Клиент JS
 Handlebars Что было раньше
  9. 9. Сервер Клиент 2011 сайт и Интернет-Банк Java/Spring, JSP, Maven JS, jQuery, Handlebars, Backbone, Maven/Grunt 2014 Кошелек JS, Backbone, Handlebars, Bower/Grunt Что было раньше 9
  10. 10. Сервер Клиент 2011 сайт и Интернет-Банк Java/Spring, JSP, Maven JS, jQuery, Handlebars, Backbone, Maven/Grunt 2014 Кошелек JS, Backbone, Handlebars, Bower/Grunt 2015 Интернет-Банк v5 JS, Angular, Bower/Gulp Что было раньше 10
  11. 11. 11 Клиент JS • Сложно решать задачи SEO и SMM Что было раньше
  12. 12. 12 Универсальное приложение
  13. 13. Сервер Клиент 2016 Сайт, Интернет-Банк, Кошелек, Брокеры, 🔜 JS, React, Flux, NPM/Webpack 🏎 Что есть сейчас 13
  14. 14. 14 • SEO и SMM Сервер JS Клиент 🏎 Что есть сейчас
  15. 15. 15 • SEO и SMM • Переиспользование 99% кода Сервер JS Клиент 🏎 Что есть сейчас
  16. 16. 16 • SEO и SMM • Переиспользование 99% кода • Одна группа разработчиков Сервер JS Клиент 🏎 Что есть сейчас
  17. 17. 17 • SEO и SMM • Переиспользование 99% кода • Одна группа разработчиков • Скорость разработки Сервер JS Клиент 🏎 Что есть сейчас
  18. 18. 18 • SEO и SMM • Переиспользование 99% кода • Одна группа разработчиков • Скорость разработки • Нет монолитности Сервер JS Клиент 🏎 Что есть сейчас
  19. 19. 19 • Реализация Flux Fluxible
  20. 20. 20 • Реализация Flux • Используем только Routr и Dispatchr Fluxible
  21. 21. 21 Сервисы Действия Сторы Компоненты Доступ к API UI логика Рендер Бизнес логика Распределение по слоям
  22. 22. 22 🌠 Жизнь приложения Node.js Браузер Интеракция • Роутинг на подприложения • Поиск редиректов • Независимый контекст • Сериализация состояния • Создание контекста • Десериализация состояния • Циклы взаимодействия
  23. 23. 23 Контекст на сервере
  24. 24. Прогрессивная загрузка 24
  25. 25. 25
  26. 26. 26
  27. 27. 27 import { ACCOUNT_LIST } from '../actions';
 import { CLIENT } from '../roles';
 
 accountList.isServer = true;
 accountList.requiredRoles = [CLIENT];
 
 function accountList(context) {
 return context.service('account/list') .then(payload => context.dispatch(ACCOUNT_LIST, payload));
 }
 
 export default accountList; Action creator
  28. 28. 28 Переиспользуемые компоненты
  29. 29. 29 Коннектор Чистый компонент Получают данные из сторов Получают данные из props Передают данные в чистый компонент через props Рендерит данные в HTML Обрабатывают callbacks, вызывают действия Обрабатывают DOM-события, вызывают callbacks Переиспользуемые компоненты
  30. 30. 30 import { LogoPure } from './LogoPure.jsx';
 
 const UILogo = connect( ['config', 'brands'], ({
 brands,
 config: { brandsBasePath }
 }) => ({
 brands,
 brandsBasePath
 }) )(LogoPure);
 
 export default UILogo; Компонент коннектор
  31. 31. 31 Переиспользуемые компоненты Higher-order Components
  32. 32. 32 ⏱ Оптимизация
  33. 33. 33 ⏱ Оптимизация на клиенте pure-render
  34. 34. 34 ⏱ Оптимизация на клиенте react-perf
  35. 35. 35 ⏱ Оптимизация на клиенте render-logger
  36. 36. 36 • jsx-no-bind ⏱ Оптимизация на клиенте
  37. 37. 37 • jsx-no-bind • batched updates ⏱ Оптимизация на клиенте
  38. 38. 38 ⏱ Оптимизация на клиенте Визуальное ускорение
  39. 39. 39 ⏱ Оптимизация на клиенте Визуальное ускорение
  40. 40. 40 ⏱ Оптимизация на сервере • ES6 Class, NODE_ENV=production – 4x ускорение
  41. 41. 41 ⏱ Оптимизация на сервере • ES6 Class, NODE_ENV=production – 4x ускорение • Minified React – +2%
  42. 42. 42 ⏱ Оптимизация на сервере • ES6 Class, NODE_ENV=production – 4x ускорение • Minified React – +2% • Babel transforms (constant & inline elements) – +10%
  43. 43. 43 ⏱ Оптимизация на сервере • ES6 Class, NODE_ENV=production – 4x ускорение • Minified React – +2% • Babel transforms (constant & inline elements) – +10% • stateless functions – +45%
  44. 44. 44 ⏱ Оптимизация на сервере • ES6 Class, NODE_ENV=production – 4x ускорение • Minified React – +2% • Babel transforms (constant & inline elements) – +10% • stateless functions – +45% • react-dom-stream – +55%
  45. 45. 45 • Кэширование на уровне страницы ⏱ Оптимизация на сервере
  46. 46. 46 • Кэширование на уровне страницы • Без sensitive данных ⏱ Оптимизация на сервере
  47. 47. 47 • nginx Кэш
  48. 48. 48 • nginx • express-cache-on-demand Кэш
  49. 49. 49 • nginx • express-cache-on-demand • lru-cache Кэш
  50. 50. 50 Кэш
  51. 51. 51 • Для сервера и клиента 🏢 Сборка
  52. 52. 52 • Для сервера и клиента • Без переменных окружения 🏢 Сборка
  53. 53. 53 • PM2 > pm2 startOrGracefulReload processes.json 🌋 Деплой
  54. 54. 54 • PM2 > pm2 startOrGracefulReload processes.json • Каждый экземпляр на отдельном порту PORT: process.env.PORT + process.env.NODE_APP_INSTANCE 🌋 Деплой
  55. 55. 55 🌋 Деплой NGINX Node.js Cluster Node.js Cluster NGINX App App App App App App App App
  56. 56. 56 🌋 Деплой NGINX Node.js Cluster Node.js Cluster NGINX App App App App App App App App
  57. 57. 57 • Автогенерация демо для компонентов 🌪 Что осталось?
  58. 58. 58 • Автогенерация демо для компонентов • Разделение на бандлы 🌪 Что осталось?
  59. 59. 59 • Автогенерация демо для компонентов • Разделение на бандлы • Ускорение сборки стилей 🌪 Что осталось?
  60. 60. 60 Универсальное приложение – это просто
  61. 61. 61 👏 Спасибо за внимание! f.nehaev@tinkoff.ru linkedin.com/in/nehaev fb.com/philnehaev Дополнительные материалы: goo.gl/ZEpnTU

×