React & Redux in Hulu
程墨 (Morgan Cheng)
@morgancheng
About Me
About Hulu
 System Complexity
 Legacy code in jQuery & Backbone
 UI non-predictable
 Lack of component isolation
 Performance Bottleneck
 Initial AJAX roundtrip for browser-side-rendering
Challenges
jQuery
Backbone
Ruby on Rails
React
Redux
Node + Express
Tech Stack
React vs. jQuery
Code in jQuery
Virtual DOM DOM
<div>
<Foo/>
<Bar>children</Bar>
</div>
JSX
Virtual DOM DOM
<div>
<Foo/>
<Bar>children</Bar>
</div>
JSX
Previous Virtual DOM
Virtual DOM DOM
<div>
<Foo/>
<Bar>children</Bar>
</div>
JSX
Previous Virtual DOM
Diff
Virtual DOM DOM
<div>
<Foo/>
<Bar>children</Bar>
</div>
JSX
Previous Virtual DOM
Diff
React App = Keep Rendering
UI = f(state)
React mixes JS/Style/Markup
if (process.env.BROWSER) {
require('./style.scss');
}
const divStyle = {
color: ‘blue’
};
function render() {
return (
<div onClick={this.onClick} style={divStyle}>Click Me</div>
);
}
Isomorphic/Universal React
const appHtml = ReactDOMServer.renderToString(component);
Server Side
Browser Side
ReactDOM.render(component,
window.document.getElementById("appRoot"));
React Components are bricks, not building
Problem of MVC
Flux
 Inter-dependency among multiple stores
 Hard to support server-side-rendering
 Hard to do hot-reloading
Drawbacks of Flux
Redux = Reducer + Flux
Reducer
(state, action) => newState
Redux
Store
Action Reducer
State
ReducerReducer
View
dispatch
From Perspective of Component
React View
Action Creators
Reducer
State Key
export {view, actions, reducer, stateKey}
Hulu Component
{
foo: { ... }
bar: { ... }
}
State
Reducer
{
foo: { ... }
bar: { ... }
}
Action
React View
React + Redux = Win!
We get Performance
and Maintainability
at the same time with
React & Redux
Without Redux With Redux
Store
Constraints over Conventions
 jQuery Dies Hard
 Legacy Code
 Third Party JavaScript Code
 e.g. Optimizely
React conflicts with jQuery
Virtual DOM DOM
React
jQuery
React conflicts with jQuery
Virtual DOM DOM
React
jQuery
render() componentDidUpdate()componentWillUpdate ()
componentWillMount() render() componentDidMount()
React Mounting Phase
React Updating Phase
invoked only at browser side
not invoked for first time render
class Foo extends React.Component{
componentDidMount() {
// do DOM manipulation with jQuery
}
componentDidUpdate() {
// do DOM manipulation with jQuery
}
render() {
// render JSX for react
}
}
react render
jQuery render
react render
jQuery render
Dehydrate & Rehydrate
State React HTML
Server Side
Browser Side
+ =
Dehydrated State React
+ = Rehydrated HTML
Page A
Web Server API Server
Page Request
HTML
&
Dehydrated Data
API Request
Page A Page B
Web Server API Server
API Request Raw Response Data
Chunked Code
On SPA Navigation
Page A Page B
Reset Singleton Store with
new Reducer and State
Faster React Server Rendering
 Set Production Mode
 NODE_ENV=production node app.js
 Use Minified React.js
 require(‘react/dist/react.min.js’);
 After v0.14, DO_NOT_USE_OR_YOU_WILL_BE_FIRED
 Babel-react-optimize Preset
 https://github.com/thejameskyle/babel-react-optimize
Avoid Wasted-Rendering-Time
Virtual DOM
Previous Virtual DOM
Waste If Same
Avoid Dynamic props
<Foo onClick={ function() { doSomething(); } } />
<Bar style={ {margin: "0px" } }/>
Incremental Page Rendering
React-Router-Redux
<Provider store={store} >
<Router history={history}>
<Route path="/" component={App}>
<Route path="foo" component={Foo} />
<Route path="bar" component={Bar} />
<Route>
</Router>
<Provider>
Maps Path to Page Component
Server Rendering Process
Fetching State
Rendering Components
Render Dehydrated State
fetchState().then(render)
ReactDOMServer.renderToString(...)
<script>
window.initState = ...
</script>
Page Should Not Be Component
class Page {
getComponents() {
return [
Header,
Foo,
Bar,
Footer
];
}
}
Server Rendering Process Improved
Start Fetching State
Rendering Component
Render Dehydrated State
Render Dehydrated State
Rendering Component
Rendering Component
Render Dehydrated State
Push After Every Render
Constraint over Conventions
Search Hulu in WeChat
Thanks
Any Question?

React & Redux in Hulu

Editor's Notes

  • #2 &amp;lt;number&amp;gt;
  • #3 All my experience is about trade off between complexity and performance. &amp;lt;number&amp;gt;
  • #4 Hulu is Subscription-based video provider. &amp;lt;number&amp;gt;
  • #5 &amp;lt;number&amp;gt;
  • #6 &amp;lt;number&amp;gt;
  • #7 The migration of tech stack. Not just because React &amp; Redux is cool and new, but it solves OUR specific problems. &amp;lt;number&amp;gt;
  • #8 jQuery is created for a reason, but React solves the same problem in more understandable way. &amp;lt;number&amp;gt;
  • #9 jQuery code is so easy to be written into a mess. &amp;lt;number&amp;gt;
  • #10 VirtualDOM magic of React/JSX &amp;lt;number&amp;gt;
  • #15 The ensense of React and Redux &amp;lt;number&amp;gt;
  • #16 React is actually implementing web-component. HTML, CSS and JS is consolidated into one component. &amp;lt;number&amp;gt;
  • #17 Just write one component which can be rendered in browser OR in server. It doesn’t matter. Isomorphic(同构) React &amp;lt;number&amp;gt;
  • #18 React is just another jQuery. d It helps to build component, but not work alone for big app. &amp;lt;number&amp;gt;
  • #19 Strictly, Model should not communicate directly with View. But, it is easy to be violated. &amp;lt;number&amp;gt;
  • #20 Flux is uni-direction flow. It doesn’t make sense to match parts between MVC and Flux &amp;lt;number&amp;gt;
  • #21 &amp;lt;number&amp;gt;
  • #22 Redux is a better flux/fluxable. &amp;lt;number&amp;gt;
  • #23 Redux is a better flux/fluxable. &amp;lt;number&amp;gt;
  • #25 View: What content should I rendered? Actions: What ”events” can I respond? Reducer: How to update state according to actions? State Key: The sub state key controlled by this component &amp;lt;number&amp;gt;
  • #26 Data Flow &amp;lt;number&amp;gt;
  • #27 React &amp; Redux enforce functional programming model; isomorphic javascript. Better data management. &amp;lt;number&amp;gt;
  • #29 React &amp; Redux enforce functional programming model; isomorphic JavaScript. All state resides in singleton store. &amp;lt;number&amp;gt;
  • #30 From perspective of architecture, we should enforce constraints instead of just asking people to follow conventions. React &amp; Redux enforce functional programming model; isomorphic JavaScript. Better data management. &amp;lt;number&amp;gt;
  • #31 Optimizely operates perfectly with jQuery, but is not designed for React. &amp;lt;number&amp;gt;
  • #37 Rehydrated HTML must exactly match HTML from server. Otherwise, user will see UI flash. React do this by checking checksum attribute in generated HTML. &amp;lt;number&amp;gt;
  • #38 Work flow of first page access. &amp;lt;number&amp;gt;
  • #40 One piece JavaScript for the whole application might be too big. Need to be chunked. &amp;lt;number&amp;gt;
  • #41 In Single Page Application with chunked code, each page need to reset singleton store to enable new reducer and new stae. &amp;lt;number&amp;gt;
  • #42 React is not designed for Server according to FB. But, there are some tricks to make it faster. &amp;lt;number&amp;gt;
  • #43 &amp;lt;number&amp;gt;
  • #45 Even React helps us to avoid actual DOM manipulation time, it is still a waste if Virtual DOM is actually same in re-rendering. &amp;lt;number&amp;gt;
  • #46 &amp;lt;number&amp;gt;
  • #48 React-Router-Redux maps URL path to Page Component. Each Page Component is actually a React Component. Has to be rendered in sync way. &amp;lt;number&amp;gt;
  • #49 &amp;lt;number&amp;gt;
  • #50 Page should just declare which components it contains, and let framework do the incremental rendering. &amp;lt;number&amp;gt;
  • #51 &amp;lt;number&amp;gt;