Thought I'd also provide some more context on some common questions that people have asked.
### Why are you using React to render a landing page?
The Netflix landing page is a lot more dynamic than most people think it is.
It's our most heavily A/B-tested page in the signup flow, with even some machine learning models being used to customize the messaging and imagery that you get depending on location, whether or not you were a previous Netflix member, device type, and a lot more. Even beyond that, Netflix supports almost 200 countries now, and there's a different combination of localization, legal challenges, and value messaging for each one. We end up sharing a lot of the logic and UI for these A/B testing and localization challenges throughout the signup flow, mainly through React components.
The example I always love to give is the <TermsOfUse/> component that we have, which to a Netflix customer signing up is literally one or two checkboxes on the UI, but has some of the most complicated logic in the codebase due to the vast number of countries and user states we support. Because of all this, it's more valuable for us to share these common React components across the entire signup process, both the landing page and the rest of the flow, which is a single-page React and Redux application.
We've seen a lot of conversion value though in improving the performance of the landing page, especially in countries with slower connections, but we don't also want to re-duplicate a lot of the shared UI logic that we have.
The tradeoff that we decided to make is to server-render the landing page using React, but also pre-fetching React / Redux / the code for the rest of the signup flow while on it. This optimizes first load performance, but also optimizes the time to load for the rest of the signup flow, which has a much larger JS bundle size to download since it's a single-page app.
### What's the performance metric that's being used?
It's TTI (Time to Interactive), when the user can fully interact with the page. This is different than TTR (Time to Render) for us, when the user can fully view the page. There's more information in the talk about the differences.
### Why not Service Workers or some other pre-loading / caching mechanism?
We have been experimenting with it, but it's mainly the lack of some browser support - Safari is the main one. Generally the Netflix signup flow needs to have more legacy browser support than the Netflix member experience. Lots of people sign up on a pretty old browser, but only ever watch Netflix on the native mobile apps or a TV device.
I work on React. We’d love to hear from your team sometimes and collaborate on this sort of thing. We’re solving many of the same problems but I rarely hear from Netflix engineers except at talks when announcing they’re avoiding React or have forked it, often for reasons we weren’t even aware of.
I'd love to sit and talk React with you and your team. We're always particularly interested in performance optimizations so maybe we can swap some knowledge.
Not aware of any team that is actively avoiding React but we're a fairly prolific bunch when it comes to public speaking and knowledge sharing so perhaps I missed some announcement from another UI team. A few of my colleagues will be speaking at the SFHTML5 meetup[1] in a few weeks if you'd like to come hang out and talk shop or feel free to drop me a line at jem@netflix.com :).
I had a terrible time trying to find react performance _monitoring_. There's plenty of performance _troubleshooting_ once you already know what component is slow, but nothing that monitors.
Did I miss something? I see some `measureLifecycleperf` functions in the react source but those look like dead ends.
So in other words: the main reason removing the React code in the frontend in this case gave such an immense performance benefit is that the logic used to compute the rendered UI is significantly more complex than the logic necessary to make that UI interactive.
It's not React that's slow, it's the logic needed to render the page?
That's pretty close. For our use case (and many others), the biggest culprit for increased TTI is the sheer size of the JavaScript payload and the time the browser takes to parse the whole bundle[1]. We still use React and other libraries on the server to generate the HTML but rather than sending all that JS down, Tony worked out exactly which client interactions still needed JS and wrote those in plain JS which resulted in a big TTI win as the browser simply had less data to parse.
Hi could you post some before and after traces (chrome dev tools recordings) of the site. Performance is nuanced, and the original tweet only helps to put down others (the react team) unfairly.
I think the win here is less about react and more about not running as much javascript on the client. I hypothesize that the traces will show this, but it is impossible to know for sure without them :)
Let’s say you think it’s not React or you have time to improve React to solve that problem: wouldn’t having some data help test that assertion and make changes?
In the talk you say that you reduced JS and therefore lowered TTI and saw more clicks on the signup button. Is it possible that you are just _tracking_ more clicks, but the total is the same?
Does it really matter how much JS there is if it's loaded after HTML and the user can already move to the sign up step without it?
Please make the search textbox always visible. Most of the times I go to Netflix.com is to see if it has the movie I want to see. (I live in Sweden, Netflix is pretty small here)
And going to the front page of Netflix, clicking the Search icon is not a pretty experience. What happens next is a chuggy chuggy animation of the textbox gliding out, and typing in it is a disaster of input lag.
I bet you fire an event for each key I press while in there? Perhaps wait with that until the rest of the page has loaded?
Thanks for taking the time to answer everyone's questions!
Do you simply use Nodejs to do the SSR? I've seen some complaints about the difficulty of scaling node to run well in a cluster, and about security things. Have you had to deal with that?
I'd honestly love to see what you did there. People use Java for the reason that all of those questions have decent answers by now.
I've been ranting here occasionally about the infuriating unprofessionalism of a web app that can't operate without JS. There is very little that you can do with JS that can't also be done with the help of a server, unless you start making up overly-specific requirements about what technologies are used, or writing user stories for robots. As a diehard NoJS guy and a developer who uses React professionally, my community's willingness to accept of the problem, and obliviousness to the solutions established by the React devs themselves, are pretty embarrassing. And it's not like I hate the language, Node has been my go-to application server for years now (Clojure is displacing that for me, but I digress).
Last year, I was building a simple SVG based chart dashboard for internal usage. Being a NoJS guy, I would sometimes disable JS while developing, on purpose or otherwise, and aside from forcing me to manually hit refresh in the browser, things generally worked. I added a couple links (styled as buttons) for zooming, to supplement the JS based drag-window zoom, and let the browser scroll the potentially very wide SVG chart within a div. If necessary, I could have even embedded the whole thing in an iframe, to avoid triggering whole page reloads, but our caching story was tight enough to compensate. Also, the React-rendered SVG represented the bulk of the markup on the page anyway.
Interactive visualisation, no JS needed. It added maybe an extra 10% to my workload (we already had the SSR stack), and helped me to avoid a variety of little glitches that plague many client-only apps, glitches that users learn to tolerate with mild disgust. The satisfaction of seeing our in-house dashboard pop up "instantly" with data, while Parsely and New Relic were still churning spinners or stuttering while waiting on JS, or even waiting for initial data after waiting on JS, was very cathartic. TTI can equal TTR, we have the technology, we've had it for a decade or so.
Yes, just like Intel. We engineered our way into this, we'll engineer our way out, and then smooth it all over with more engineering. Entropy wins again.
It is quite telling that you give the example of the <TermsOfUse/> component which has "one or two checkboxes on the UI" that "has some of the most complicated logic in the codebase".
I can't quite tell what you're implying here... but this makes total sense to me.
Every country has different regulations, and therefore would require different wording and agreements as a Terms of Use. Anyone that has worked at a multi-national company understands this is just The Way It Is.
At Nike there is a ton of logic on a per-country basis. For example, they might own the copyright of the word "FlyKnit" in most countries, but in Italy they don't and get fined if it's ever misused. There's a TON of development work that caters to legal / regulation problems like this.
The full talks are available here if people want to watch them:
https://www.youtube.com/watch?v=V8oTJ8OZ5S0&t=11m30s
Thought I'd also provide some more context on some common questions that people have asked.
### Why are you using React to render a landing page?
The Netflix landing page is a lot more dynamic than most people think it is.
It's our most heavily A/B-tested page in the signup flow, with even some machine learning models being used to customize the messaging and imagery that you get depending on location, whether or not you were a previous Netflix member, device type, and a lot more. Even beyond that, Netflix supports almost 200 countries now, and there's a different combination of localization, legal challenges, and value messaging for each one. We end up sharing a lot of the logic and UI for these A/B testing and localization challenges throughout the signup flow, mainly through React components.
The example I always love to give is the <TermsOfUse/> component that we have, which to a Netflix customer signing up is literally one or two checkboxes on the UI, but has some of the most complicated logic in the codebase due to the vast number of countries and user states we support. Because of all this, it's more valuable for us to share these common React components across the entire signup process, both the landing page and the rest of the flow, which is a single-page React and Redux application.
We've seen a lot of conversion value though in improving the performance of the landing page, especially in countries with slower connections, but we don't also want to re-duplicate a lot of the shared UI logic that we have.
The tradeoff that we decided to make is to server-render the landing page using React, but also pre-fetching React / Redux / the code for the rest of the signup flow while on it. This optimizes first load performance, but also optimizes the time to load for the rest of the signup flow, which has a much larger JS bundle size to download since it's a single-page app.
### What's the performance metric that's being used?
It's TTI (Time to Interactive), when the user can fully interact with the page. This is different than TTR (Time to Render) for us, when the user can fully view the page. There's more information in the talk about the differences.
### Why not Service Workers or some other pre-loading / caching mechanism?
We have been experimenting with it, but it's mainly the lack of some browser support - Safari is the main one. Generally the Netflix signup flow needs to have more legacy browser support than the Netflix member experience. Lots of people sign up on a pretty old browser, but only ever watch Netflix on the native mobile apps or a TV device.
#####
Feel free to comment here or tweet at Tony (https://twitter.com/tedwards947) or me (https://twitter.com/clarler) if there's any other questions that we can help answer.
Though from a lot of experience, 140 characters isn't always enough to provide enough context for JavaScript framework discussions. ;)
If these sort of performance and UI challenges seem interesting to you, our team is also hiring for UI engineers and an engineering manager!
* Senior Software Engineer (React, Node): https://jobs.netflix.com/jobs/864767
* Senior Software Engineer (Android): https://jobs.netflix.com/jobs/864766
* Engineering Manager: https://jobs.netflix.com/jobs/865119
Cheers!