-
Notifications
You must be signed in to change notification settings - Fork 27.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Experimental: hook version of reportWebVitals #28769
Conversation
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you clarify the constraint to continue exporting reportWebVitals
? Is that just so we don't needlessly setup the perf tracking? We should probably find an alternative, because pages/_app
will become a server component, so we won't be able to this particular check.
This comment has been minimized.
This comment has been minimized.
bc52d29
to
5b2a958
Compare
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
f27cafd
to
556e70c
Compare
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
b13af97
to
f0de779
Compare
This comment has been minimized.
This comment has been minimized.
ce661fb
to
65dc1a8
Compare
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Failing test suitesCommit: 4a7404c test/integration/app-document-remove-hmr/test/index.test.js
Expand output● _app removal HMR › should HMR when _document is removed
|
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we be calling this useExperimentalWebVitalsReport
or changing the import to import { useWebVitalsReprot } from './experimental-vitals
since it's not behind an experimental config similar to what we did for the script component while it was experimental?
I think exporting |
This comment has been minimized.
This comment has been minimized.
Stats from current PRDefault Build (Increase detected
|
vercel/next.js canary | huozhi/next.js feat/hook-webvitals | Change | |
---|---|---|---|
buildDuration | 12.4s | 12.3s | -76ms |
buildDurationCached | 3.5s | 3.2s | -320ms |
nodeModulesSize | 182 MB | 182 MB |
Page Load Tests Overall increase ✓
vercel/next.js canary | huozhi/next.js feat/hook-webvitals | Change | |
---|---|---|---|
/ failed reqs | 0 | 0 | ✓ |
/ total time (seconds) | 2.678 | 2.693 | |
/ avg req/sec | 933.63 | 928.35 | |
/error-in-render failed reqs | 0 | 0 | ✓ |
/error-in-render total time (seconds) | 1.357 | 1.326 | -0.03 |
/error-in-render avg req/sec | 1841.72 | 1885.17 | +43.45 |
Client Bundles (main, webpack, commons) Overall increase ⚠️
vercel/next.js canary | huozhi/next.js feat/hook-webvitals | Change | |
---|---|---|---|
779.HASH.js gzip | 179 B | 179 B | ✓ |
framework-HASH.js gzip | 42.2 kB | 42.2 kB | ✓ |
main-HASH.js gzip | 26.8 kB | 27 kB | |
webpack-HASH.js gzip | 1.45 kB | 1.45 kB | ✓ |
Overall change | 70.6 kB | 70.8 kB |
Legacy Client Bundles (polyfills)
vercel/next.js canary | huozhi/next.js feat/hook-webvitals | Change | |
---|---|---|---|
polyfills-a4..dd70.js gzip | 31 kB | 31 kB | ✓ |
Overall change | 31 kB | 31 kB | ✓ |
Client Pages
vercel/next.js canary | huozhi/next.js feat/hook-webvitals | Change | |
---|---|---|---|
_app-HASH.js gzip | 977 B | 977 B | ✓ |
_error-HASH.js gzip | 194 B | 194 B | ✓ |
amp-HASH.js gzip | 311 B | 311 B | ✓ |
css-HASH.js gzip | 328 B | 328 B | ✓ |
dynamic-HASH.js gzip | 2.67 kB | 2.67 kB | ✓ |
head-HASH.js gzip | 351 B | 351 B | ✓ |
hooks-HASH.js gzip | 918 B | 918 B | ✓ |
image-HASH.js gzip | 4.14 kB | 4.14 kB | ✓ |
index-HASH.js gzip | 260 B | 260 B | ✓ |
link-HASH.js gzip | 1.66 kB | 1.66 kB | ✓ |
routerDirect..HASH.js gzip | 320 B | 320 B | ✓ |
script-HASH.js gzip | 386 B | 386 B | ✓ |
withRouter-HASH.js gzip | 319 B | 319 B | ✓ |
bb14e60e810b..30f.css gzip | 125 B | 125 B | ✓ |
Overall change | 13 kB | 13 kB | ✓ |
Client Build Manifests
vercel/next.js canary | huozhi/next.js feat/hook-webvitals | Change | |
---|---|---|---|
_buildManifest.js gzip | 493 B | 493 B | ✓ |
Overall change | 493 B | 493 B | ✓ |
Rendered Page Sizes Overall decrease ✓
vercel/next.js canary | huozhi/next.js feat/hook-webvitals | Change | |
---|---|---|---|
index.html gzip | 539 B | 538 B | -1 B |
link.html gzip | 551 B | 550 B | -1 B |
withRouter.html gzip | 533 B | 532 B | -1 B |
Overall change | 1.62 kB | 1.62 kB | -3 B |
Diffs
Diff for main-HASH.js
@@ -960,6 +960,8 @@
var _isError = _interopRequireDefault(__webpack_require__(676));
+ var _vitals = __webpack_require__(1823);
+
function asyncGeneratorStep(
gen,
resolve,
@@ -1306,6 +1308,7 @@
appEntrypoint,
app,
mod,
+ exportedReportWebVitals,
pageEntrypoint,
_require7,
isValidElementType,
@@ -1347,75 +1350,79 @@
(app = appEntrypoint.component),
(mod = appEntrypoint.exports);
CachedApp = app;
+ exportedReportWebVitals = mod && mod.reportWebVitals;
+
+ onPerfEntry = function onPerfEntry(_ref3) {
+ var id = _ref3.id,
+ name = _ref3.name,
+ startTime = _ref3.startTime,
+ value = _ref3.value,
+ duration = _ref3.duration,
+ entryType = _ref3.entryType,
+ entries = _ref3.entries;
+ // Combines timestamp with random number for unique ID
+ var uniqueID = ""
+ .concat(Date.now(), "-")
+ .concat(
+ Math.floor(Math.random() * (9000000000000 - 1)) +
+ 1000000000000
+ );
+ var perfStartEntry;
+
+ if (entries && entries.length) {
+ perfStartEntry = entries[0].startTime;
+ }
- if (mod && mod.reportWebVitals) {
- onPerfEntry = function onPerfEntry(_ref3) {
- var id = _ref3.id,
- name = _ref3.name,
- startTime = _ref3.startTime,
- value = _ref3.value,
- duration = _ref3.duration,
- entryType = _ref3.entryType,
- entries = _ref3.entries;
- // Combines timestamp with random number for unique ID
- var uniqueID = ""
- .concat(Date.now(), "-")
- .concat(
- Math.floor(Math.random() * (9000000000000 - 1)) +
- 1000000000000
- );
- var perfStartEntry;
-
- if (entries && entries.length) {
- perfStartEntry = entries[0].startTime;
- }
-
- mod.reportWebVitals({
- id: id || uniqueID,
- name: name,
- startTime: startTime || perfStartEntry,
- value: value == null ? duration : value,
- label:
- entryType === "mark" || entryType === "measure"
- ? "custom"
- : "web-vital"
- });
+ var webVitals = {
+ id: id || uniqueID,
+ name: name,
+ startTime: startTime || perfStartEntry,
+ value: value == null ? duration : value,
+ label:
+ entryType === "mark" || entryType === "measure"
+ ? "custom"
+ : "web-vital"
};
- }
+ exportedReportWebVitals === null ||
+ exportedReportWebVitals === void 0
+ ? void 0
+ : exportedReportWebVitals(webVitals);
+ (0, _vitals).trackWebVitalMetric(webVitals);
+ };
if (true) {
- _context.next = 16;
+ _context.next = 17;
break;
}
_context.t0 = {
error: hydrateErr
};
- _context.next = 19;
+ _context.next = 20;
break;
- case 16:
- _context.next = 18;
+ case 17:
+ _context.next = 19;
return pageLoader.routeLoader.whenEntrypoint(page);
- case 18:
+ case 19:
_context.t0 = _context.sent;
- case 19:
+ case 20:
pageEntrypoint = _context.t0;
if (!("error" in pageEntrypoint)) {
- _context.next = 22;
+ _context.next = 23;
break;
}
throw pageEntrypoint.error;
- case 22:
+ case 23:
CachedComponent = pageEntrypoint.component;
if (true) {
- _context.next = 27;
+ _context.next = 28;
break;
}
@@ -1431,7 +1438,7 @@
(isValidElementType = _require7.isValidElementType);
if (isValidElementType(CachedComponent)) {
- _context.next = 27;
+ _context.next = 28;
break;
}
@@ -1442,31 +1449,31 @@
)
);
- case 27:
- _context.next = 32;
+ case 28:
+ _context.next = 33;
break;
- case 29:
- _context.prev = 29;
+ case 30:
+ _context.prev = 30;
_context.t1 = _context["catch"](3);
// This catches errors like throwing in the top level of a module
initialErr = (0, _isError)["default"](_context.t1)
? _context.t1
: new Error(_context.t1 + "");
- case 32:
+ case 33:
if (false) {
}
if (!window.__NEXT_PRELOADREADY) {
- _context.next = 36;
+ _context.next = 37;
break;
}
- _context.next = 36;
+ _context.next = 37;
return window.__NEXT_PRELOADREADY(dynamicIds);
- case 36:
+ case 37:
exports.router = router = (0, _router1).createRouter(
page,
query,
@@ -1512,13 +1519,13 @@
render(renderCtx);
return _context.abrupt("return", emitter);
- case 43:
+ case 44:
return _context.abrupt("return", {
emitter: emitter,
renderCtx: renderCtx
});
- case 44:
+ case 45:
case "end":
return _context.stop();
}
@@ -1526,7 +1533,7 @@
},
_callee,
null,
- [[3, 29]]
+ [[3, 30]]
);
})
);
@@ -7706,6 +7713,50 @@
/***/
},
+ /***/ 1823: /***/ function(
+ __unused_webpack_module,
+ exports,
+ __webpack_require__
+ ) {
+ "use strict";
+
+ Object.defineProperty(exports, "__esModule", {
+ value: true
+ });
+ exports.trackWebVitalMetric = trackWebVitalMetric;
+ exports.useExperimentalWebVitalsReport = useExperimentalWebVitalsReport;
+ exports.webVitalsCallbacks = void 0;
+ var _react = __webpack_require__(7294);
+ const webVitalsCallbacks = new Set();
+ exports.webVitalsCallbacks = webVitalsCallbacks;
+ const metrics = [];
+ function trackWebVitalMetric(metric) {
+ metrics.push(metric);
+ webVitalsCallbacks.forEach(callback => callback(metric));
+ }
+ function useExperimentalWebVitalsReport(callback) {
+ const metricIndexRef = (0, _react).useRef(0);
+ (0, _react).useEffect(() => {
+ // Flush calculated metrics
+ const reportMetric = metric => {
+ callback(metric);
+ metricIndexRef.current = metrics.length;
+ };
+ for (let i = metricIndexRef.current; i < metrics.length; i++) {
+ reportMetric(metrics[i]);
+ }
+ webVitalsCallbacks.add(reportMetric);
+ return () => {
+ webVitalsCallbacks.delete(reportMetric);
+ };
+ }, [callback]);
+ }
+
+ //# sourceMappingURL=vitals.js.map
+
+ /***/
+ },
+
/***/ 4155: /***/ function(module) {
// shim for using process in browser
var process = (module.exports = {});
Diff for index.html
@@ -19,7 +19,7 @@
defer=""
></script>
<script
- src="/_next/static/chunks/main-016a32a085579856abd5.js"
+ src="/_next/static/chunks/main-af07b424021c3c0a3f88.js"
defer=""
></script>
<script
Diff for link.html
@@ -19,7 +19,7 @@
defer=""
></script>
<script
- src="/_next/static/chunks/main-016a32a085579856abd5.js"
+ src="/_next/static/chunks/main-af07b424021c3c0a3f88.js"
defer=""
></script>
<script
Diff for withRouter.html
@@ -19,7 +19,7 @@
defer=""
></script>
<script
- src="/_next/static/chunks/main-016a32a085579856abd5.js"
+ src="/_next/static/chunks/main-af07b424021c3c0a3f88.js"
defer=""
></script>
<script
Default Build with SWC (Increase detected ⚠️ )
General Overall increase ⚠️
vercel/next.js canary | huozhi/next.js feat/hook-webvitals | Change | |
---|---|---|---|
buildDuration | 6.4s | 6.5s | |
buildDurationCached | 3.1s | 3.2s | |
nodeModulesSize | 182 MB | 182 MB |
Page Load Tests Overall decrease ⚠️
vercel/next.js canary | huozhi/next.js feat/hook-webvitals | Change | |
---|---|---|---|
/ failed reqs | 0 | 0 | ✓ |
/ total time (seconds) | 2.74 | 2.754 | |
/ avg req/sec | 912.49 | 907.91 | |
/error-in-render failed reqs | 0 | 0 | ✓ |
/error-in-render total time (seconds) | 1.368 | 1.367 | 0 |
/error-in-render avg req/sec | 1826.96 | 1829.27 | +2.31 |
Client Bundles (main, webpack, commons) Overall increase ⚠️
vercel/next.js canary | huozhi/next.js feat/hook-webvitals | Change | |
---|---|---|---|
675-HASH.js gzip | 13.8 kB | 13.8 kB | ✓ |
770.HASH.js gzip | 178 B | 178 B | ✓ |
framework-HASH.js gzip | 50.7 kB | 50.7 kB | ✓ |
main-HASH.js gzip | 34.7 kB | 34.9 kB | |
webpack-HASH.js gzip | 1.65 kB | 1.65 kB | ✓ |
Overall change | 101 kB | 101 kB |
Legacy Client Bundles (polyfills)
vercel/next.js canary | huozhi/next.js feat/hook-webvitals | Change | |
---|---|---|---|
polyfills-a4..dd70.js gzip | 31 kB | 31 kB | ✓ |
Overall change | 31 kB | 31 kB | ✓ |
Client Pages
vercel/next.js canary | huozhi/next.js feat/hook-webvitals | Change | |
---|---|---|---|
_app-HASH.js gzip | 1.32 kB | 1.32 kB | ✓ |
_error-HASH.js gzip | 180 B | 180 B | ✓ |
amp-HASH.js gzip | 315 B | 315 B | ✓ |
css-HASH.js gzip | 331 B | 331 B | ✓ |
dynamic-HASH.js gzip | 2.8 kB | 2.8 kB | ✓ |
head-HASH.js gzip | 356 B | 356 B | ✓ |
hooks-HASH.js gzip | 637 B | 637 B | ✓ |
image-HASH.js gzip | 573 B | 573 B | ✓ |
index-HASH.js gzip | 262 B | 262 B | ✓ |
link-HASH.js gzip | 2.2 kB | 2.2 kB | ✓ |
routerDirect..HASH.js gzip | 326 B | 326 B | ✓ |
script-HASH.js gzip | 393 B | 393 B | ✓ |
withRouter-HASH.js gzip | 322 B | 322 B | ✓ |
bb14e60e810b..30f.css gzip | 125 B | 125 B | ✓ |
Overall change | 10.1 kB | 10.1 kB | ✓ |
Client Build Manifests
vercel/next.js canary | huozhi/next.js feat/hook-webvitals | Change | |
---|---|---|---|
_buildManifest.js gzip | 511 B | 511 B | ✓ |
Overall change | 511 B | 511 B | ✓ |
Rendered Page Sizes Overall increase ⚠️
vercel/next.js canary | huozhi/next.js feat/hook-webvitals | Change | |
---|---|---|---|
index.html gzip | 538 B | 539 B | |
link.html gzip | 551 B | 551 B | ✓ |
withRouter.html gzip | 531 B | 532 B | |
Overall change | 1.62 kB | 1.62 kB |
Diffs
Diff for main-HASH.js
@@ -374,6 +374,7 @@
var _routeAnnouncer = __webpack_require__(1639);
var _router1 = __webpack_require__(557);
var _isError = _interopRequireDefault2(__webpack_require__(676));
+ var _vitals = __webpack_require__(1823);
function asyncGeneratorStep(
gen,
resolve,
@@ -687,6 +688,7 @@
appEntrypoint,
app,
mod,
+ exportedReportWebVitals,
pageEntrypoint,
isValidElementType,
getNodeError,
@@ -717,66 +719,70 @@
(mod = ref.exports),
ref;
CachedApp = app;
- if (mod && mod.reportWebVitals) {
- onPerfEntry = function(param) {
- var id = param.id,
- name = param.name,
- startTime = param.startTime,
- value = param.value,
- duration = param.duration,
- entryType = param.entryType,
- entries = param.entries;
- // Combines timestamp with random number for unique ID
- var uniqueID = ""
- .concat(Date.now(), "-")
- .concat(
- Math.floor(Math.random() * (9000000000000 - 1)) +
- 1000000000000
- );
- var perfStartEntry;
- if (entries && entries.length) {
- perfStartEntry = entries[0].startTime;
- }
- mod.reportWebVitals({
- id: id || uniqueID,
- name: name,
- startTime: startTime || perfStartEntry,
- value: value == null ? duration : value,
- label:
- entryType === "mark" || entryType === "measure"
- ? "custom"
- : "web-vital"
- });
+ exportedReportWebVitals = mod && mod.reportWebVitals;
+ onPerfEntry = function(param) {
+ var id = param.id,
+ name = param.name,
+ startTime = param.startTime,
+ value = param.value,
+ duration = param.duration,
+ entryType = param.entryType,
+ entries = param.entries;
+ // Combines timestamp with random number for unique ID
+ var uniqueID = ""
+ .concat(Date.now(), "-")
+ .concat(
+ Math.floor(Math.random() * (9000000000000 - 1)) +
+ 1000000000000
+ );
+ var perfStartEntry;
+ if (entries && entries.length) {
+ perfStartEntry = entries[0].startTime;
+ }
+ var webVitals = {
+ id: id || uniqueID,
+ name: name,
+ startTime: startTime || perfStartEntry,
+ value: value == null ? duration : value,
+ label:
+ entryType === "mark" || entryType === "measure"
+ ? "custom"
+ : "web-vital"
};
- }
+ exportedReportWebVitals === null ||
+ exportedReportWebVitals === void 0
+ ? void 0
+ : exportedReportWebVitals(webVitals);
+ (0, _vitals).trackWebVitalMetric(webVitals);
+ };
if (
// error, so we need to skip waiting for the entrypoint.
true
) {
- _ctx.next = 15;
+ _ctx.next = 16;
break;
}
_ctx.t0 = {
error: hydrateErr
};
- _ctx.next = 18;
+ _ctx.next = 19;
break;
- case 15:
- _ctx.next = 17;
+ case 16:
+ _ctx.next = 18;
return pageLoader.routeLoader.whenEntrypoint(page);
- case 17:
- _ctx.t0 = _ctx.sent;
case 18:
+ _ctx.t0 = _ctx.sent;
+ case 19:
pageEntrypoint = _ctx.t0;
if (!("error" in pageEntrypoint)) {
- _ctx.next = 21;
+ _ctx.next = 22;
break;
}
throw pageEntrypoint.error;
- case 21:
+ case 22:
CachedComponent = pageEntrypoint.component;
if (true) {
- _ctx.next = 26;
+ _ctx.next = 27;
break;
}
var ref4;
@@ -792,7 +798,7 @@
(isValidElementType = ref4.isValidElementType),
ref4;
if (isValidElementType(CachedComponent)) {
- _ctx.next = 26;
+ _ctx.next = 27;
break;
}
throw new Error(
@@ -801,27 +807,27 @@
'"'
)
);
- case 26:
- _ctx.next = 31;
+ case 27:
+ _ctx.next = 32;
break;
- case 28:
- _ctx.prev = 28;
+ case 29:
+ _ctx.prev = 29;
_ctx.t1 = _ctx["catch"](2);
// This catches errors like throwing in the top level of a module
initialErr = (0, _isError).default(_ctx.t1)
? _ctx.t1
: new Error(_ctx.t1 + "");
- case 31:
+ case 32:
if (false) {
var ref;
}
if (!window.__NEXT_PRELOADREADY) {
- _ctx.next = 35;
+ _ctx.next = 36;
break;
}
- _ctx.next = 35;
+ _ctx.next = 36;
return window.__NEXT_PRELOADREADY(dynamicIds);
- case 35:
+ case 36:
exports.router = router = (0, _router1).createRouter(
page,
query,
@@ -860,19 +866,19 @@
}
render(renderCtx);
return _ctx.abrupt("return", emitter);
- case 42:
+ case 43:
return _ctx.abrupt("return", {
emitter: emitter,
renderCtx: renderCtx
});
- case 43:
+ case 44:
case "end":
return _ctx.stop();
}
},
_callee,
null,
- [[2, 28]]
+ [[2, 29]]
);
})
);
@@ -7001,6 +7007,50 @@
/***/
},
+ /***/ 1823: /***/ function(
+ __unused_webpack_module,
+ exports,
+ __webpack_require__
+ ) {
+ "use strict";
+
+ Object.defineProperty(exports, "__esModule", {
+ value: true
+ });
+ exports.trackWebVitalMetric = trackWebVitalMetric;
+ exports.useExperimentalWebVitalsReport = useExperimentalWebVitalsReport;
+ exports.webVitalsCallbacks = void 0;
+ var _react = __webpack_require__(7294);
+ const webVitalsCallbacks = new Set();
+ exports.webVitalsCallbacks = webVitalsCallbacks;
+ const metrics = [];
+ function trackWebVitalMetric(metric) {
+ metrics.push(metric);
+ webVitalsCallbacks.forEach(callback => callback(metric));
+ }
+ function useExperimentalWebVitalsReport(callback) {
+ const metricIndexRef = (0, _react).useRef(0);
+ (0, _react).useEffect(() => {
+ // Flush calculated metrics
+ const reportMetric = metric => {
+ callback(metric);
+ metricIndexRef.current = metrics.length;
+ };
+ for (let i = metricIndexRef.current; i < metrics.length; i++) {
+ reportMetric(metrics[i]);
+ }
+ webVitalsCallbacks.add(reportMetric);
+ return () => {
+ webVitalsCallbacks.delete(reportMetric);
+ };
+ }, [callback]);
+ }
+
+ //# sourceMappingURL=vitals.js.map
+
+ /***/
+ },
+
/***/ 4155: /***/ function(module) {
// shim for using process in browser
var process = (module.exports = {});
Diff for index.html
@@ -19,7 +19,7 @@
defer=""
></script>
<script
- src="/_next/static/chunks/main-bdf746ee231657bbdcec.js"
+ src="/_next/static/chunks/main-f04de6fa2ac852a0da37.js"
defer=""
></script>
<script
Diff for link.html
@@ -19,7 +19,7 @@
defer=""
></script>
<script
- src="/_next/static/chunks/main-bdf746ee231657bbdcec.js"
+ src="/_next/static/chunks/main-f04de6fa2ac852a0da37.js"
defer=""
></script>
<script
Diff for withRouter.html
@@ -19,7 +19,7 @@
defer=""
></script>
<script
- src="/_next/static/chunks/main-bdf746ee231657bbdcec.js"
+ src="/_next/static/chunks/main-f04de6fa2ac852a0da37.js"
defer=""
></script>
<script
Experimental
Introduce
next/vitals
anduseExperimentalWebVitalsReport
API which is not limited by_app
.pages/index.js