Performance in React
https://slides.com/tylergraf/performance-in-react

Some Housekeeping Items


Tyler Graf
Senior Web Dev
FamilySearch
tyler@familysearch.org
@tylergraf

Focus: Page load performance
Ship
Less
Code
Rule 1:

Why?

Download Time
2G (280 Kbps)
3G (1.6 Mbps)
Cable (5 Mbps)
200 KB
(1 MB uncompressed)
5.7s
1.0s
320ms

Load Time Moto G4
2G (280 Kbps)
3G (1.6 Mbps)
Cable (5 Mbps)
200 KB
(1 MB uncompressed)
8.0s
3.3s
2.6s
http connection
SSL
| Device | Unique visitors in the last year | Perc |
| ------------------------- | -------------------------------- | ----- |
| Apple iPhone | 7,841,169 | 25.2% |
| Apple iPad | 3,280,247 | 10.6% |
| Samsung Galaxy S8 | 684,974 | 2.2% |
| Samsung Galaxy S9 | 521,036 | 1.7% |
| Samsung Galaxy Note 8 | 428,127 | 1.4% |
| Samsung Galaxy S9 Plus | 420,489 | 1.4% |
| Verizon Galaxy S7 | 345,610 | 1.1% |
| Samsung Galaxy S8 Plus | 334,761 | 1.1% |
| Samsung Galaxy Tab A 10.1 | 235,683 | 0.8% |
| Samsung Galaxy Note 9 | 214,554 | 0.7% |
| Motorola Moto G5 Plus | 206,180 | 0.7% |
| Google Pixel 2 | 182,505 | 0.6% |
| Google Pixel 2 XL | 152,412 | 0.5% |
| Samsung Galaxy S8 | 143,763 | 0.5% |
| Samsung Galaxy S7 | 134,330 | 0.4% |
| Samsung Galaxy S7 Edge | 134,220 | 0.4% |
| Unknown M3 | 133,875 | 0.4% |
| Motorola Moto G6 | 125,804 | 0.4% |
| AT&T Galaxy S7 | 121,423 | 0.4% |
| Motorola Moto G4 | 121,030 | 0.4% |
| Motorola Moto E4 | 118,282 | 0.4% |
| Amazon Fire HD 10 | 116,831 | 0.4% |
| Samsung Galaxy J7 Prime | 116,220 | 0.4% |
| Amazon Fire HD 8 | 110,212 | 0.4% |
| Verizon Galaxy S6 | 109,875 | 0.4% |
| Verizon Galaxy S7 edge | 107,282 | 0.3% |
| Samsung Galaxy Tab 4 10.1 | 104,458 | 0.3% |
| Samsung Galaxy Tab S2 | 102,892 | 0.3% |
| T-Mobile Galaxy S7 | 102,262 | 0.3% |
| Samsung Galaxy J2 Prime | 101,905 | 0.3% |
| Samsung Galaxy A5 | 100,792 | 0.3% |
| Samsung Galaxy J5 Prime | 98,201 | 0.3% |

Person Page
465KB
Person Page
465KB
Moto G4
3G (1.6/768)
Person Page
338KB
Moto G4
3G (1.6/768)
(after visiting the home page)
Person Page
38KB
Moto G4
3G (1.6/768)
(Cached View)
"[Christ] said those who work for the salvation of others will have their sins forgiven and will bring salvation to their own souls" (see D&C 4:4; 31:5; 84:61).
Real Why

Philippines 6 Mbps
China 3 Mbps

Peru 3 Mbps

Moto G4 - 3G
V7 - 3.2 MB (3167 KB)
V8 - 338 KB
How?
Be Lazy


Lazy Load Routes
Lazy Load Routes
import React, { Suspense, lazy } from "react";
import { Switch, Route, Router, NotFound } from "@fs/zion-router";
const PageOne = lazy(() => import("./components/pages/PageOne"));
const PageTwo = lazy(() => import("./components/pages/PageTwo"));
const PageThree = lazy(() => import("./components/pages/PageThree"));
export default function App() {
return (
<Suspense>
<Router>
<Switch>
<Route exact path="/" component={PageOne} />
<Route exact path="/two" component={PageTwo} />
<Route exact path="/three" component={PageThree} />
<Route component={NotFound} />
</Switch>
</Router>
</Suspense>
);
}
On-demand Loading
import React, { useState, Suspense, lazy } from "react";
import Person from "../components/Person";
import { Button } from "@fs/zion-ui";
const OverLay = lazy(() => import("../components/OverLay"));
export default function PageOne() {
const [showMore, setShowMore] = useState();
return (
<Suspense fallback={<div>Loading...</div>}>
<Person />
<Button type="button" onClick={() => setShowMore(true)}>
Show me more!
</Button>
{showMore && <OverLay />}
</Suspense>
);
}
When?
Not critical at render
Way below the fold
Content requires interaction
SHOW MORE
Showing more
Not All Things Are Equal

Funny Story
.icon.thing {
background:
url(data:image/gif;base64,R0lGODlhEAAQAMQAAORHHOVSKudfOulrSOp3WOyDZu6QdvCchPGolfO0o/XBs/fNwfjZ0frl3/zy7////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABAALAAAAAAQABAAAAVVICSOZGlCQAosJ6mu7fiyZeKqNKToQGDsM8hBADgUXoGAiqhSvp5QAnQKGIgUhwFUYLCVDFCrKUE1lBavAViFIDlTImbKC5Gm2hB0SlBCBMQiB0UjIQA7)
no-repeat
left center;
padding: 5px 0 5px 25px;
}
.icon.thing2 {
background:
url(data:image/gif;base64,R0lGODlhEAAQAMQAAORHHOVSKudfOulrSOp3WOyDZu6QdvCchPGolfO0o/XBs/fNwfjZ0frl3/zy7////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABAALAAAAAAQABAAAAVVICSOZGlCQAosJ6mu7fiyZeKqNKToQGDsM8hBADgUXoGAiqhSvp5QAnQKGIgUhwFUYLCVDFCrKUE1lBavAViFIDlTImbKC5Gm2hB0SlBCBMQiB0UjIQA7)
no-repeat
left center;
padding: 5px 0 5px 25px;
}
.icon.thing3 {
background:
url(data:image/gif;base64,R0lGODlhEAAQAMQAAORHHOVSKudfOulrSOp3WOyDZu6QdvCchPGolfO0o/XBs/fNwfjZ0frl3/zy7////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABAALAAAAAAQABAAAAVVICSOZGlCQAosJ6mu7fiyZeKqNKToQGDsM8hBADgUXoGAiqhSvp5QAnQKGIgUhwFUYLCVDFCrKUE1lBavAViFIDlTImbKC5Gm2hB0SlBCBMQiB0UjIQA7)
no-repeat
left center;
padding: 5px 0 5px 25px;
}
.icon.thing4 {
background:
url(data:image/gif;base64,R0lGODlhEAAQAMQAAORHHOVSKudfOulrSOp3WOyDZu6QdvCchPGolfO0o/XBs/fNwfjZ0frl3/zy7////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABAALAAAAAAQABAAAAVVICSOZGlCQAosJ6mu7fiyZeKqNKToQGDsM8hBADgUXoGAiqhSvp5QAnQKGIgUhwFUYLCVDFCrKUE1lBavAViFIDlTImbKC5Gm2hB0SlBCBMQiB0UjIQA7)
no-repeat
left center;
padding: 5px 0 5px 25px;
}
data:image * 100

2s faster!!
Treeshake


// maths.js
export function add(x,y) {
return x + y
}
export function subtract(x,y) {
return x - y
}
// main.js
import { add } from './maths';
add(10, 5)
What's Treeshaking?
Subtract won't be included in the bundle
Caveat
Doesn't work with commonjs modules.
// maths.js
exports.add = (x,y) => {
return x + y
}
exports.subtract = (x,y) => {
return x - y
}
// main.js
import { add } from './maths';
add(10, 5)
How do I know if a 3rd party module is tree-shakable?
Look at package.json main and module
{
"name": "cool-package",
"main": "./dist/main.js",
"module": "./dist/main.es6.js"
}
Method 1
Webpack will look for module first, then main.
export function doStuff(){
// do stuff
}
main.js, may use es6 modules as well, look at the source code.
Method 2

Along with a bunch of other info like gzipped size, it includes tree-shakability.
Bundle analyzer
Be aware of packages and versions


Is that lodash?
61KB Total?
Demo
Do
Don't
- Analyze what's in your bundle
- Pay attention to percentages
- Look for duplication
- Pay attention to byte sizes as much
- Assume everything gets loaded on every page
Audit Regularly
Synthetic
vs
RUM
- Controlled
- CPU
- Network Conditions
- Repeatable
- Real
- Histogram/Percentiles

RUM Histogram
Synthetic Monitoring
- Lighthouse (in chrome dev tools)
- webpagetest.org
- speedcurve.com
- FamilySearch in house



RUM
Real User Monitoring



PageStats (in house)
WebPageTest

How to set a session
setCookie https://www.familysearch.org fssessionid=82cc969a-787e-ca9f-8a06-b6093a54787f-prod
navigate https://www.familysearch.org/tree/pedigree/landscape/LBGY-WZG
navigate https://www.familysearch.org
setCookie https://www.familysearch.org fssessionid=82cc969a-787e-ca9f-8a06-b6093a54787f-prod
navigate https://www.familysearch.org/tree/pedigree/landscape/LBGY-WZG
Homepage => Person Page
Person Page


Perf People to Follow



Philippines 6 Mbps
China 3 Mbps

Peru 3 Mbps

Tyler Graf
Senior Web Dev
FamilySearch
tyler@familysearch.org
@tylergraf

https://slides.com/tylergraf/performance-in-react
Performance in React
By Tyler Graf
Performance in React
- 870