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

Post on 16-Apr-2017

2.459 views 0 download

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

ИзоморфныеReact-приложенияДенис Измайлов

23 ноября 2015

Денис Измайлов• 15 лет опыта разработки ПО и web

• Последние 5 лет полностью Front-end, Node.js и архитектуре

• Более 10 проектов, в т.ч. много SPA, highload и React

• Коммиты в Redux, webpack и koa

• Спикер HighLoad++ 2015, MoscowJS

• Автор статей на Habrahabr и англоязычных ресурсах

, CEO

Почему от классического Single Page Application необходимо отказаться?

Как изоморфные приложения отразятся на Вашей зарплате?

Что вы будете делатьна этих выходных?

Вы уже знаете1. React 14

2. webpack

3. ES6

4. Node.js

5. Express / koa

6. Isomorphic (Universal) apps6

Часть 1

Web стал очень большим

Искусство

Разработка под Web

Наука

Раньше было просто• Создал страницу

• Добавил пару скриптов

• Отправил в Production

Раньше было просто

Сервер

Браузер

11

Раньше было просто

Сервер

Браузер

Делал всё

12

Раньше было просто

Сервер

Браузер- HTML - [CSS, JavaScript]

Делал всё

13

Это работало

Single PageApplications

(SPA)

Single Page Application

Сервер

Браузер

16

Single Page Application

Сервер

Браузер

Страница существует?Авторизация нужна? Доступ есть?

17

Single Page Application

Сервер

Браузер

Страница существует?Авторизация нужна? Доступ есть?

- Tiny HTML, [CSS] - JavaScript bundle

18

Single Page ApplicationПлюсы

• Легко начать • webpack

• <div id=“root” />

• React, Redux

• build

19

Single Page ApplicationПлюсы

• Легко начать

• Богатый функционал

webpack, <div id=“root” />, React, Redux

20

Single Page ApplicationПлюсы

• Легко начать

• Богатый функционал

• Быстро дорабатывать

webpack, <div id=“root” />, React, Redux

21

Single Page ApplicationПлюсы

• Легко начать

• Богатый функционал

• Быстро дорабатывать

• Отзывчивый UI

webpack, <div id=“root” />, React, Redux

22

Single Page ApplicationПлюсы

• Легко начать

• Богатый функционал

• Быстро дорабатывать

• Отзывчивый UI

• Удобно кэшировать

webpack, <div id=“root” />, React, Redux

23

- Wow. И не одного минуса?

Single Page ApplicationМинусы

• Долгая загрузка • JavaScript bundle up to 3-5 Mb

• первое обращение

• исполнение

• память

25

Single Page ApplicationМинусы

• Долгая загрузка

• Сложность поддержки

• side-эффекты

• memory leak

1st request, CPU, mem

26

Single Page ApplicationМинусы

• Долгая загрузка

• Сложность поддержки

• Пустая страница, один URL

1st request, CPU, mem

side-эффекты, memory leaks

27

Single Page ApplicationМинусы

• Долгая загрузка

• Сложность поддержки

• Пустая страница, один URL

• Legacy Browsers

1st request, CPU, mem

side-эффекты, memory leaks

28

- Разве это минусы?

Single Page ApplicationМинусы

• Долгая загрузка

для бизнеса

снижение UX

30

Single Page ApplicationМинусы

• Долгая загрузка

• Сложность поддержки

для бизнеса

снижение UX

риски

31

Single Page ApplicationМинусы

• Долгая загрузка

• Сложность поддержки

• Пустая страница

для бизнеса

снижение UX

риски

проблемы SEO

32

Single Page ApplicationМинусы

• Долгая загрузка

• Сложность поддержки

• Пустая страница

• Один URL

для бизнеса

снижение UX

риски

проблемы SEO

проблемы SMM

33

Single Page ApplicationМинусы

• Долгая загрузка

• Сложность поддержки

• Пустая страница

• Один URL

• Legacy Browsers

для бизнеса

снижение UX

риски

проблемы SEO

проблемы SMM

потеря ЦА

34

Single Page ApplicationМинусы

• Долгая загрузка

• Сложность поддержки

• Пустая страница

• Один URL

• Legacy Browsers

для бизнеса

снижение UX

риски

проблемы SEO

проблемы SMM

потеря ЦА

Расходы

Single Page ApplicationМинусы

для бизнеса

снижение UX

риски

проблемы SEO

проблемы SMM

потеря ЦА

Расходы

- WAT? Что делать?

Взять лучшее из обоих миров

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

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

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

Шаблоны

Стили

Локализация

Конфигурация

Routes

Права доступа

Модели

Схемы

Валидация

Сервисы

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

server.jsNode.js

worker.js

client.jsBrowser

admin.js

Бизнес-логика

Компоненты

API-интерфейсы

Actions, Reducers

Static Files

Браузер

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

Front-end сервер

Back-end сервер

Database

Javaetc

Браузер

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

Front-end сервер

Back-end сервер

Database

Javaetc

Браузер

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

Front-end сервер

Back-end сервер

Database

Javaetc

- HTML - [critical CSS] - …

Front-end клиент

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

Front-end сервер

Back-end сервер

Database

Javaetc

- HTML - [critical CSS] - JS Bundle

Front-end клиент

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

Front-end сервер

Back-end сервер

Database

Javaetc

- HTML - [critical CSS] - JS Bundle

Front-end клиент

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

Front-end сервер

• Единая среда исполнения

• Общая кодовая база

• Полный контроль

• Экосистема

47

- Но как?

Server-Side Rendering(SSR)

Server-Side Rendering• Сборка HTML на Front-end сервере

• Моментальное отображение в

браузере, ещё до загрузки JS

• Когда JS загрузится, React только

добавит обработчики событий

• А это очень быстро50

Server-Side RenderingКод на сервере выглядит очень просто:

import ReactDOMServer from 'react-dom/server';import Application from './components/application';const body = ReactDOMServer.renderToString( <Application />);

51

Server-Side Rendering1. Пользователь видит страницу

мгновенно

2. Отсутствие дополнительных запросов на получение данных

3. Страница может работать даже без JS

4. Полноценная URL-навигация и мета-тэги

5. Сохранение всех возможностей современного JavaScript

52

Часть 2

Производительность и масштабирование

Масштабирование

Масштабированиефункциональное

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

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

Server-Side RenderingКак получить асинхронный State:

1. Вручную для каждой страницы

2. Facebook Relay

3. redux-catch-promise

59

Асинхронный StateВручную для каждой страницы:

• Получить State, необходимый для страницы

• ReactDOMServer.renderToString()

60

Асинхронный StateFacebook Relay:

1. The framework for building data-driven React applications

2. Declarative. Colocation. Mutations.

3. https://github.com/facebook/relay/issues/136

4. 1Q201661

Асинхронный Stateredux-catch-promise:

• Redux - state container для React

• Redux: the best for isomorphic apps, MoscowJS 25https://youtu.be/Uyk_8WWna6s

• redux-catch-promise - это middleware для Redux

62

Асинхронный Stateredux-catch-promise:

1. callback для захвата Promise-экшнов

2. Делаем рендер компонент

3. Из компонент - запрос к БД, отдавая Promise

4. Собираем все эти промисы, ожидаем их завершения

5. Повторный рендер, с данными63

Асинхронный Stateredux-catch-promise:

1. Примеры и исходный код:https://github.com/DenisIzmaylov/redux-catch-promise

2. Установка:

npm install redux-catch-promise

64

Производительность

Производительность

Тестовый стенд:

MacBook Pro 15” Retina (Early 2013)

2.4 GHz Intel Core i7

66

ПроизводительностьРазмер страницы: 56 238 байт

ПроизводительностьРазмер страницы: 56 238 байт

ПроизводительностьРазмер страницы: 56 238 байт

ПроизводительностьРазмер страницы: 56 238 байт

ПроизводительностьРазмер страницы: 56 238 байт

ПроизводительностьРазмер страницы: 56 238 байт

Производительность

Для теста используем:

ab -n 100 http://localhost:3000/profile

73

Производительность

Для теста используем:

ab -n 100 http://localhost:3000/profile

Запускаем…

74

Производительность

Для теста используем:

ab -n 100 http://localhost:3000/profile

Запускаем…

Time per request: 61.850 ms

75

Производительность

61.850 msЭто медленно или быстро?

76

Производительность

61.850 msЭто медленно или быстро?

Тот же шаблон в Handlebars:

8.385 ms

86% less

77

Производительность

61.850 msЭто медленно или быстро?

Тот же шаблон в Handlebars:

8.385 ms

86% less

78

Производительность1. Идём в Google - ничего полезного

2. Пробуем спросить Twitter - тишина:

79

Производительность

Ок, а что если?

NODE_ENV=production

Запускаем…

80

Производительность

Ок, а что если?

NODE_ENV=production

Запускаем…

Time per request: 37.943 ms(vs 61.850 ms)

39% less81

Производительность

Вроде лучше.

Но всё ещё не торт.

82

Ищем дальше

GitHub issues

Производительность

• “Server rendering is slower with npm react”https://github.com/facebook/react/issues/812

85

Производительность

• “Server rendering is slower with npm react”https://github.com/facebook/react/issues/812Решение:явно подключать react/dist/react.min.js

86

ПроизводительностьСоздаём 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

ПроизводительностьСоздаём 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

Как это изменило результат?

Производительность

Server rendering is slower with npm react

react/dist/react.min.js

Запускаем…

90

Производительность

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

Производительность

Server rendering is slower with npm react

react/dist/react.min.js

Запускаем…

Time per request: 38.253 ms(vs 37.943 ms)0.08% moreFAILED

92

0

17,5

35

52,5

70

38,25337,943

8,385

61,85

React SSR Handlebars production react.min.js

Результаты

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

Часть 3

Продвинутыерешения

Продвинутые решения

1. Precompilation + Cache 2. Rendering Separation 3. Progressive Rendering 4. Facebook BigPipe 5. HAProxy

97

Precompilation + Cache

• UI = f(state)

• f = React Component

• state = path + [actions] + …

1. Простое решение: redis

2. “Отложенный рендеринг”:redis + kue.js + workers 98

Rendering Separation

99

Progressive Rendering

100

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-stream101

Facebook BigPipe• Сборка страницы в процессе загрузки • Загружается параллельно • Устойчивость к ошибкам

Facebook BigPipe• Сборка страницы в процессе загрузки • Загружается параллельно • Устойчивость к ошибкам

Facebook BigPipe• Сборка страницы в процессе загрузки • Загружается параллельно • Устойчивость к ошибкам

Facebook BigPipe

105

HAProxy• Несколько экземпляров Node.js

• Обратитесь к DevOps

106

Эпилог

Рекомендации• Присоединяйтеськ сообществу MoscowJShttp://moscowjs.ru/

• Улучшайте английский, не читайте советских газет

• Читайте оригиналы и технические блоги

• Активно внедряйте в свою жизнь Twitter и GitHub

108

Полезные материалы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 pagehttps://engineering.linkedin.com/frontend/new-technologies-new-linkedin-home-page

4. Improving performance on Twitter.comhttps://blog.twitter.com/2012/improving-performance-on-twittercom

5. Scaling Isomorphic Javascript Codehttp://blog.nodejitsu.com/scaling-isomorphic-javascript-code/

109

Полезные материалы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 Appshttp://nerds.airbnb.com/isomorphic-javascript-future-web-apps/

8. React server side rendering performancehttp://www.slideshare.net/nickdreckshage/react-meetup

9. The Lost Art of Progressive HTML Renderinghttp://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

Послесловие«Большинство проблем

алгоритмов можно решить сменой структуры данных»,

Андрей Ситник

“Changes is our work”,Jake Archibald, Google

Почему от классического Single Page Application необходимо отказаться?

izmaylov.dm@gmail.com

Присылайте свой мобильный телефони краткую информацию о себе

Спасибо за внимание

Денис Измайлов

@DenisIzmaylov

https://github.com/DenisIzmaylov

http://startup-makers.ru

denis_izmaylov

izmaylov.dm@gmail.com

Приложение 1