performance and scalability art of isomorphic react applications

143
Isomorphic React Applications: Performance & Scalability Denis Izmaylov June 23, 2016

Upload: denis-izmaylov

Post on 09-Jan-2017

582 views

Category:

Software


2 download

TRANSCRIPT

Isomorphic React Applications: Performance & Scalability

Denis Izmaylov

June 23, 2016

Denis Izmaylov• 16 years of Software and Web

development experience

• The last 6 years focused exclusivelyon Front-end and Web

• 15+ projects, including SPA,high-load and React

• Commits to Redux, webpack and koa

• Speaker at HighLoad++ 2015,AgileDays 2016, RIT 2016, DevConf 2016

• Regular speaker at MoscowJS meetups

• “Application and Universal Components” and other articles

• We develop web,mobile and DevOps

projects forour customers

• We use right and most

efficient solutions

• We have more than 20

talented developersin the team

Why should we stop developing classic

Single Page Applications?

How does isomorphic applications

affect your income?

What will you be doing this weekend?

Part 1 Architecture

Web became a serious environment

Art

Web Development

Science

How easy it was• Create a HTML file

• Add some scripts

• Submit to Production

How easy it was

Server

Browser

11

How easy it was

Server

Browser

Does everything

12

How easy it was

Server

Browser- HTML - [CSS, JavaScript]

Does everything

13

It worked

Segmentation

Segmentation

Browser Server

Segmentation

Front-end Back-end

Segmentation

Front-end Back-end

Segmentation

Front-end Back-end

Changes are delivered with delay

Single Page Applications

(SPA)

Single Page Application

Server

Browser

21

Single Page Application

Server

Browser

Does the page exists?Do we need auth? Do we have access?

22

Single Page Application

Server

Browser

Is the page exists?Do we need auth? Do we have access?

- Tiny HTML, [CSS]

- JavaScript bundle

23

Single Page Application

Server

Browser

Is the page exists?Do we need auth? Do we have access?

- Tiny HTML, [CSS]

- JavaScript bundle

24

- AJAX

- iframes

Single Page ApplicationBenefits

• Easy to start • <div id="root" />

• React, Redux

• build JS bundle

25

Single Page ApplicationBenefits

• Easy to start

• Rich features

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

26

Single Page ApplicationBenefits

• Easy to start

• Rich features

• Fast enhancement

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

27

Single Page ApplicationBenefits

• Easy to start

• Rich features

• Fast enhancement

• Responsive UI

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

28

Single Page ApplicationBenefits

• Easy to start

• Rich features

• Fast enhancement

• Responsive UI

• Effortless caching

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

29

- Wow. Is it so ideal?

Single Page ApplicationCosts

• Long-time Start • JavaScript bundle up to 3-5 Mb

• first request

• execution

• memory

31

Single Page ApplicationCosts

• Long-time Start

• Expensive maintenance

• side effects

• memory leaks

1st request, CPU, mem

32

Single Page ApplicationCosts

• Long-time Start

• Expensive maintenance

• Empty page, one URL

1st request, CPU, mem

side effects, memory leaks

33

Single Page ApplicationCosts

• Long-time Start

• Expensive maintenance

• Empty page, one URL

• Hard to support Legacy Browsers

1st request, CPU, mem

side effects, memory leaks

34

- Are they really “costs”?

Single Page Applicationfor business

36

Single Page ApplicationCosts

• Long-Time Start

for business

reduced UX

37

Kissmetrics Blog

Kissmetrics Blog

“…If e-commerce sites

is making $100,000 per day,a one second page delay

could potentially cost you $2.5 million in lost sales

every year…” 39

Single Page ApplicationCosts

• Long-Time Start

• Expensive Maintenance

for business

reduced UX

risks

41

Single Page ApplicationCosts

• Long-Time Start

• Expensive Maintenance

• Empty Page

for business

reduced UX

risks

SEO problems

42

Single Page ApplicationCosts

• Long-Time Start

• Expensive Maintenance

• Empty Page

• One URL

for business

reduced UX

risks

SEO problems

Social Sharing problems

43

Single Page ApplicationCosts

• Long-Time Start

• Expensive Maintenance

• Empty Page

• One URL

• Legacy Browsers

for business

reduced UX

risks

SEO problems

Social Sharing problems

lost audience

44

Single Page ApplicationCosts

• Long-Time Start

• Expensive Maintenance

• Empty Page

• One URL

• Legacy Browsers

for business

reduced UX

risks

SEO problems

Social Sharing problems

lost audience

45Losses

Single Page ApplicationCosts

for business

reduced UX

risks

SEO problems

Social Sharing problems

lost audience

46Losses

- What should we do? How do we solve this?

Take the best from both worlds

Isomorphic Applications

Isomorphic Applications

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

Templates

Stylesheets

i18n

Configuration

Routes

Access Rules

Models

Schemas

Validation

Services

Isomorphic Applications

server.jsNode.js

worker.js

client.jsBrowser

admin.js

Business Logic

Components

API interfaces

Actions, Reducers

Static Files, etc

Templates

Stylesheets

i18n

Configuration

Routes

Access Rules

Models

Schemas

Validation

Services

Isomorphic Applications

server.jsNode.js

worker.js

client.jsBrowser

admin.js

Business Logic

Components

API interfaces

Actions, Reducers

Static Files, etc

+ React Native

Browser(Client)

Isomorphic Applications

Front-end ServerNode.js

Back-end Server

APIDatabase

Java PHPetc

Isomorphic Applications

Browser(Client)

Front-end ServerNode.js

Back-end Server

APIDatabase

Java PHPetc

Isomorphic Applications

- HTML - [critical CSS] - …

Front-end ServerNode.js

Back-end Server

APIDatabase

Java PHPetc

Browser(Client)

Front-end Client

Isomorphic Applications

- HTML - [critical CSS] - JS Bundle

Front-end ServerNode.js

Back-end Server

APIDatabase

Java PHPetc

Front-end Client

Isomorphic Applications

- HTML - [critical CSS] - JS Bundle

Front-end ServerNode.js

Back-end Server

APIDatabase

Java PHPetc

Front-end Client

Isomorphic Applications

Front-end Server

• One execution environment

• Shared codebase

• Full control

• Ecosystem

• Microservices Architecture

58

Yesterday Front-end

was only browser

Front-end Back-end

Front-end Back-end

Today Front-end

is browser and server

- How can we do that?

Server-Side Rendering(SSR)

Server-Side Rendering

• Build HTML on Front-end (Node.js) Server

• Render Page in your browser immediately,

before it loads JavaScript

• When JavaScript will be loaded, React just add event handlers only

• It works very fast

63

Server-Side RenderingExample code for Server-Side:

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

64

Server-Side RenderingExample code for Server-Side:

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

65

Render React Component to plain string

Server-Side Rendering1. Visitors see a page immediately

2. No additional requests to load data

3. The page could work even without JS

4. Full URL-navigation

5. Meta-tags for SEO and SMM

6. Better security66

Part 2 Performance

and Scalability

Functional Scalability

Server-Side RenderingThat’s super when we have all data for response:

import ReactDOMServer from 'react-dom/server';import Application from './components/application';const initialState = { siteName: 'Startup Makers' };const body = ReactDOMServer.renderToString( <Application state={initialState} />);

69

Server-Side RenderingThat’s super when we have all data for response:

import ReactDOMServer from 'react-dom/server';import Application from './components/application';const initialState = { siteName: 'Startup Makers' };const body = ReactDOMServer.renderToString( <Application state={initialState} />);

What if we have to load it async? 70

Server-Side RenderingHow to get async State:

1. Manual for each page

2. Facebook Relay

3. Request Promises

71

Asynchronous StateManual for each page:

• Define which data you have to load for each page

• Load this data and prepare Initial State

• ReactDOMServer.renderToString()

72

Asynchronous StateFacebook Relay:

1. The framework for building data-driven React applications

2. Declarative data fetching

3. https://github.com/denvned/isomorphic-relay

73

Asynchronous StateRequest Promises:

• Redux - state container for React

• Redux is close to be standard for React apps

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

• We will use Redux for next steps74

Request PromisesTwo ways:

1. Call static methods for each main Component before render

2. Pre-render Elements Tree without data,push requests promises in constructors and re-render Elements with data

75

Request PromisesHandle static methods with React Router

1. Create Redux store

2. Link Redux Store with Router middleware

3. Dispatch MATCH action for requested location

4. Add response handler for `store.router.then()`

5. Router middleware lookup for static `fetchData` method in component of Route

76

Request Promises

77

Create Store

Express Route

Wait for resolving `fetchData`

Render Components

with Data

Find Component for route

Request Promises

78

Static method in Components:

class PartnersPage extends Component { static fetchData(getState, dispatch) { dispatch({ type: PARTNERS_REQUEST, payload: fetch('/api/partners', …), }) } // ….

Request Promises

79

Static method in Components:

export default ( <Route path='/' component={Layout}> <Route path='/partners' component={PartnersPage} /> </Route>)

Request Promises

80

Static method in Components:

const store = createStore() store.getState().router.then((err, redirect, props) => { const content = renderToString( <Provider store={store}> <RouterContext {…props} /> </Provider> ) res.send(content) })

Catching Request PromisesStatic method:

1. react-router-redux

2. redux-router

81

Catching Request Promises

What if you need computing for some custom params

to fetch data?

82

Catching Request Promises

What if you like delegatedecision about requests

down to the tree?

83

redux-catch-promise:

1. Render the Elements Tree without Data

2. Collect all promises

3. Wait until they will be resolved

4. Re-render the Elements Tree with fetched data

5. Send rendered HTML to client84

Catching Request Promises

redux-catch-promise:

1. Example and source code:https://github.com/DenisIzmaylov/redux-catch-promise

2. Installation:

npm install redux-catch-promise

85

Catching Request Promises

Performance

Performance

Test stand:

MacBook Pro 15” Retina (Early 2013)

2.4 GHz Intel Core i7

87

PerformancePage size: 56 Kb

PerformancePage size: 56 Kb

PerformancePage size: 56 Kb

PerformancePage size: 56 Kb

PerformancePage size: 56 Kb

PerformancePage size: 56 Kb

Performance

We will test it with ab

Apache HTTP server benchmarking tool

https://httpd.apache.org/docs/2.4/programs/ab.html

94

Performance

Test with:

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

95

Performance

Test with:

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

Executing…

96

Performance

Test with:

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

Executing…

Time per request: 62 ms

97

Performance

62 msIs it slow or fast?

98

Performance

62 msIs it slow or fast?

The same template in Handlebars:

8 ms

86% less99

Performance

62 msIs it slow or fast?

The same template in Handlebars:

8 ms

86% less100

Performance1. Try to search in Google - nothing

2. Try to ask in Twitter - silence:

101

Performance

Ok, what if we do that?

NODE_ENV=production

Executing…

102

Performance

Ok, what if we do that?

NODE_ENV=production

Executing…

Time per request: 38 ms(vs 62 ms)39% less

103

Performance

Looks better

104

Performance

Looks better

But it’s still not funny

105

Go ahead

GitHub issues

Performance

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

108

Performance

• “Server rendering is slower with npm react”https://github.com/facebook/react/issues/812Solution:use directly react/dist/react.min.js

109

PerformanceCreate 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'); }

110

PerformanceCreate 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'); }

111

How does it influenceresults?

Performance

Server rendering is slower with npm react

react/dist/react.min.js

Executing…

113

Performance

Server rendering is slower with npm react

react/dist/react.min.js

Executing…

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

114

Performance

Server rendering is slower with npm react

react/dist/react.min.js

Executing…

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

115

0

17,5

35

52,5

70

38,25337,943

8,385

61,85

React SSR Handlebars production react.min.js

Results

0

17,5

35

52,5

70

38,25337,943

8,385

61,85

React SSR Handlebars production react.min.js

ResultsNODE_ENV=production

39% less

Conclusion

Always useNODE_ENV=production

Part 3 Advanced Solutions

Advanced Solutions

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

120

Precompilation + Cache

• UI = f(state)

• f = React Component

• state = path + [actions] + …

1. Simple solution: redis

2. Deferred server-side rendering:redis + kue.js + workers 121

Rendering Separation

122

HTML Streaming

123Usually we do this

HTML Streaming• 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://www.youtube.com/watch?v=PnpfGy7q96U

• https://github.com/aickin/react-dom-stream124

Facebook BigPipe• Bundle a page during it’s loading • Assets are loading parallel • Resistants to errors

Facebook BigPipe• Bundle a page during it’s loading • Assets are loading parallel • Resistants to errors

Facebook BigPipe• Bundle a page during it’s loading • Assets is loading parallel • Resistants to errors

Facebook BigPipe• Bundle a page during it’s loading • Assets are loading parallel • Resistants to errors

Facebook BigPipe

129

https://www.facebook.com/notes/facebook-engineering/bigpipe-pipelining-web-pages-for-

high-performance/389414033919/

HAProxy

130

• Multiple Node.js instance

• Ask your DevOps engineer

• Use CoreOS, Kubernetes or Mesosphere

Scale Cube

131

Monolith

Infinite Scaling

Y axis - functional

decomposition

X axis - horizontal duplication

Z axis

- re

sourc

es

partiti

oning

X-Axis Scaling

132

Load

Balancer

Application

Application

ApplicationBy replicating the entire application

Y-Axis Scaling

133

Load

Balancer

Chat

Catalog

Orders

/catalog

/chat

/orders

By splittingthe application

Z-Axis Scaling

134

Load

Balancer

[A - I]

[J - R]

[S - Z]

/catalog/*

/catalog/*

/catalog/*

By splittingthe data

Z-Axis Scaling

135

Load

Balancer

Regular

Premium

Premium

/catalog/*

/catalog/*

/catalog/*

By splittingthe resources

Epilogue

“Almost all algorithm problems could be solved by changing a

data structure”

“Changes is our work”,Jake Archibald, Google

Why should we stop developing classic

Single Page Applications?

Takeaways 1. Classic SPA is very expensive for business

2. Isomorphic Applications provides better UX, SEO, Social

Marketing, reduce risks and costs

3. Shared codebase and one ecosystem is good investment

to high efficiency development

4. SSR performance is not good

5. We know a lot of advanced solutions to improve it very

well

6. Microservices architecture is best solution where we will have Front-end Server just as Render service

Thank youDenis Izmaylov

@DenisIzmaylov

DenisIzmaylov

www.startup-makers.com

denis_izmaylov

[email protected]

Useful Links1. 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/

141

Useful Links6. 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

142

Secret Slide