Upload
denis-izmaylov
View
581
Download
2
Embed Size (px)
Citation preview
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
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
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
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
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
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
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) })
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
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
Executing…
Time per request: 62 ms
97
Performance
Ok, what if we do that?
NODE_ENV=production
Executing…
Time per request: 38 ms(vs 62 ms)39% less
103
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
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
ResultsNODE_ENV=production
39% less
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
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
“Almost all algorithm problems could be solved by changing a
data structure”
“Changes is our work”,Jake Archibald, Google
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
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