Skip to content

Commit c9bb741

Browse files
housseindjirdehmrmckebianschmitz
authored andcommitted
Add performance relayer + documentation (web-vitals) (facebook#9116)
Co-authored-by: Brody McKee <[email protected]> Co-authored-by: Ian Schmitz <[email protected]>
1 parent 23bd740 commit c9bb741

File tree

10 files changed

+114
-5
lines changed

10 files changed

+114
-5
lines changed
+65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
---
2+
id: measuring-performance
3+
title: Measuring Performance
4+
---
5+
6+
By default, Create React App includes a performance relayer that allows you to measure and analyze
7+
the performance of your application using different metrics.
8+
9+
To measure any of the supported metrics, you only need to pass a function into the `reportWebVitals`
10+
function in `index.js`:
11+
12+
```js
13+
reportWebVitals(console.log);
14+
```
15+
16+
This function is fired when the final values for any of the metrics have finished calculating on the
17+
page. You can use it to log any of the results to the console or send to a particular endpoint.
18+
19+
## Web Vitals
20+
21+
[Web Vitals](https://web.dev/vitals/) are a set of useful metrics that aim to capture the user
22+
experience of a web page. In Create React App, a third-party library is used to measure these
23+
metrics ([web-vitals](https://github.com/GoogleChrome/web-vitals)).
24+
25+
To understand more about the object returned to the function when a metric value is calculated,
26+
refer to the [documentation](https://github.com/GoogleChrome/web-vitals/#types). The [Browser
27+
Support](https://github.com/GoogleChrome/web-vitals/#browser-support) section also explains which browsers are supported.
28+
29+
## Sending results to analytics
30+
31+
With the `reportWebVitals` function, you can send any of results to an analytics endpoint to measure and track real user performance on your site. For example:
32+
33+
```js
34+
function sendToAnalytics(metric) {
35+
const body = JSON.stringify(metric);
36+
const url = 'https://example.com/analytics';
37+
38+
// Use `navigator.sendBeacon()` if available, falling back to `fetch()`
39+
if (navigator.sendBeacon) {
40+
navigator.sendBeacon(url, body);
41+
} else {
42+
fetch(url, { body, method: 'POST', keepalive: true });
43+
}
44+
}
45+
46+
reportWebVitals(sendToAnalytics);
47+
```
48+
49+
> **Note:** If you use Google Analytics, use the `id` value to make it easier to construct metric distributions manually (to calculate percentiles, etc…).
50+
>
51+
> ```js
52+
> function sendToAnalytics({id, name, value}) {
53+
> ga('send', 'event', {
54+
> eventCategory: 'Web Vitals',
55+
> eventAction: name,
56+
> eventValue: Math.round(name === 'CLS' ? value * 1000 : value), // values must be integers
57+
> eventLabel: id, // id unique to current page load
58+
> nonInteraction: true, // avoids affecting bounce rate
59+
> });
60+
> }
61+
>
62+
> reportWebVitals(sendToAnalytics);
63+
> ```
64+
>
65+
> Read more about sending results to Google Analytics [here](https://github.com/GoogleChrome/web-vitals#send-the-results-to-google-analytics).

docusaurus/website/sidebars.json

+1
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
"adding-a-router",
3737
"adding-custom-environment-variables",
3838
"making-a-progressive-web-app",
39+
"measuring-performance",
3940
"production-build"
4041
],
4142
"Testing": ["running-tests", "debugging-tests"],

package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@
4141
"strip-ansi": "^6.0.0",
4242
"svg-term-cli": "^2.1.1",
4343
"tempy": "^0.2.1",
44-
"wait-for-localhost": "^3.1.0"
44+
"wait-for-localhost": "^3.1.0",
45+
"web-vitals": "^0.2.2"
4546
},
4647
"husky": {
4748
"hooks": {

packages/cra-template-typescript/template.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88
"@types/react": "^16.9.0",
99
"@types/react-dom": "^16.9.0",
1010
"@types/jest": "^25.0.0",
11-
"typescript": "^3.8.0"
11+
"typescript": "^3.8.0",
12+
"web-vitals": "^0.2.2"
1213
}
1314
}
1415
}

packages/cra-template-typescript/template/src/index.tsx

+6
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import ReactDOM from 'react-dom';
33
import './index.css';
44
import App from './App';
55
import * as serviceWorker from './serviceWorker';
6+
import reportWebVitals from './reportWebVitals';
67

78
ReactDOM.render(
89
<React.StrictMode>
@@ -15,3 +16,8 @@ ReactDOM.render(
1516
// unregister() to register() below. Note this comes with some pitfalls.
1617
// Learn more about service workers: https://cra.link/PWA
1718
serviceWorker.unregister();
19+
20+
// If you want to start measuring performance in your app, pass a function
21+
// to log results (for example: reportWebVitals(console.log))
22+
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
23+
reportWebVitals();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { ReportHandler } from 'web-vitals';
2+
3+
const reportWebVitals = (onPerfEntry?: ReportHandler) => {
4+
if (onPerfEntry && onPerfEntry instanceof Function) {
5+
import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
6+
getCLS(onPerfEntry);
7+
getFID(onPerfEntry);
8+
getFCP(onPerfEntry);
9+
getLCP(onPerfEntry);
10+
getTTFB(onPerfEntry);
11+
});
12+
}
13+
}
14+
15+
export default reportWebVitals;

packages/cra-template/template.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
"dependencies": {
44
"@testing-library/jest-dom": "^5.9.0",
55
"@testing-library/react": "^10.2.1",
6-
"@testing-library/user-event": "^11.3.2"
6+
"@testing-library/user-event": "^11.3.2",
7+
"web-vitals": "^0.2.2"
78
}
89
}
910
}

packages/cra-template/template/src/index.js

+6
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import ReactDOM from 'react-dom';
33
import './index.css';
44
import App from './App';
55
import * as serviceWorker from './serviceWorker';
6+
import reportWebVitals from './reportWebVitals';
67

78
ReactDOM.render(
89
<React.StrictMode>
@@ -15,3 +16,8 @@ ReactDOM.render(
1516
// unregister() to register() below. Note this comes with some pitfalls.
1617
// Learn more about service workers: https://cra.link/PWA
1718
serviceWorker.unregister();
19+
20+
// If you want to start measuring performance in your app, pass a function
21+
// to log results (for example: reportWebVitals(console.log))
22+
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
23+
reportWebVitals();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
const reportWebVitals = (onPerfEntry) => {
2+
if (onPerfEntry && onPerfEntry instanceof Function) {
3+
import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
4+
getCLS(onPerfEntry);
5+
getFID(onPerfEntry);
6+
getFCP(onPerfEntry);
7+
getLCP(onPerfEntry);
8+
getTTFB(onPerfEntry);
9+
});
10+
}
11+
}
12+
13+
export default reportWebVitals;

tasks/e2e-installs.sh

+2-2
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ function exists {
5151
# Check for accidental dependencies in package.json
5252
function checkDependencies {
5353
if ! awk '/"dependencies": {/{y=1;next}/},/{y=0; next}y' package.json | \
54-
grep -v -q -E '^\s*"(@testing-library\/.+)|(react(-dom|-scripts)?)"'; then
54+
grep -v -q -E '^\s*"(@testing-library\/.+)|web-vitals|(react(-dom|-scripts)?)"'; then
5555
echo "Dependencies are correct"
5656
else
5757
echo "There are extraneous dependencies in package.json"
@@ -62,7 +62,7 @@ function checkDependencies {
6262
# Check for accidental dependencies in package.json
6363
function checkTypeScriptDependencies {
6464
if ! awk '/"dependencies": {/{y=1;next}/},/{y=0; next}y' package.json | \
65-
grep -v -q -E '^\s*"(@testing-library\/.+)|(@types\/.+)|typescript|(react(-dom|-scripts)?)"'; then
65+
grep -v -q -E '^\s*"(@testing-library\/.+)|web-vitals|(@types\/.+)|typescript|(react(-dom|-scripts)?)"'; then
6666
echo "Dependencies are correct"
6767
else
6868
echo "There are extraneous dependencies in package.json"

0 commit comments

Comments
 (0)