-
Notifications
You must be signed in to change notification settings - Fork 30.2k
chore: add dev boot profiling and benchmark scripts #87940
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
Conversation
This stack of pull requests is managed by Graphite. Learn more about stacking. |
e0108f1 to
4fa7d80
Compare
2b81a1a to
4977db5
Compare
748e836 to
8c9b326
Compare
7cfbab1 to
7eb9491
Compare
Stats from current PRDefault Build (Increase detected
|
| vercel/next.js canary | vercel/next.js perf-dev-scripts | Change | |
|---|---|---|---|
| buildDuration | 17.8s | 15s | N/A |
| buildDurationCached | 13.9s | 11s | N/A |
| nodeModulesSize | 457 MB | 457 MB | ✓ |
| nextStartRea..uration (ms) | 713ms | 727ms | N/A |
Client Bundles (main, webpack) Overall increase ⚠️
| vercel/next.js canary | vercel/next.js perf-dev-scripts | Change | |
|---|---|---|---|
| 2086.HASH.js gzip | 169 B | 169 B | ✓ |
| 2161-HASH.js gzip | 5.39 kB | 5.41 kB | N/A |
| 2747-HASH.js gzip | 4.48 kB | 4.46 kB | N/A |
| 4322-HASH.js gzip | 52.5 kB | 52.2 kB | N/A |
| ec793fe8-HASH.js gzip | 62.3 kB | 62.3 kB | N/A |
| framework-HASH.js gzip | 59.8 kB | 59.8 kB | N/A |
| main-app-HASH.js gzip | 252 B | 253 B | N/A |
| main-HASH.js gzip | 38.4 kB | 38.7 kB | |
| webpack-HASH.js gzip | 1.68 kB | 1.69 kB | N/A |
| Overall change | 38.5 kB | 38.9 kB |
Legacy Client Bundles (polyfills)
| vercel/next.js canary | vercel/next.js perf-dev-scripts | Change | |
|---|---|---|---|
| polyfills-HASH.js gzip | 39.4 kB | 39.4 kB | ✓ |
| Overall change | 39.4 kB | 39.4 kB | ✓ |
Client Pages
| vercel/next.js canary | vercel/next.js perf-dev-scripts | Change | |
|---|---|---|---|
| _app-HASH.js gzip | 194 B | 193 B | N/A |
| _error-HASH.js gzip | 182 B | 182 B | ✓ |
| css-HASH.js gzip | 336 B | 335 B | N/A |
| dynamic-HASH.js gzip | 1.8 kB | 1.8 kB | N/A |
| edge-ssr-HASH.js gzip | 256 B | 256 B | ✓ |
| head-HASH.js gzip | 352 B | 349 B | N/A |
| hooks-HASH.js gzip | 385 B | 384 B | N/A |
| image-HASH.js gzip | 580 B | 580 B | ✓ |
| index-HASH.js gzip | 259 B | 258 B | N/A |
| link-HASH.js gzip | 2.5 kB | 2.51 kB | N/A |
| routerDirect..HASH.js gzip | 319 B | 317 B | N/A |
| script-HASH.js gzip | 385 B | 387 B | N/A |
| withRouter-HASH.js gzip | 316 B | 315 B | N/A |
| 1afbb74e6ecf..834.css gzip | 106 B | 106 B | ✓ |
| Overall change | 1.12 kB | 1.12 kB | ✓ |
Client Build Manifests
| vercel/next.js canary | vercel/next.js perf-dev-scripts | Change | |
|---|---|---|---|
| _buildManifest.js gzip | 738 B | 738 B | ✓ |
| Overall change | 738 B | 738 B | ✓ |
Rendered Page Sizes
| vercel/next.js canary | vercel/next.js perf-dev-scripts | Change | |
|---|---|---|---|
| index.html gzip | 523 B | 525 B | N/A |
| link.html gzip | 537 B | 539 B | N/A |
| withRouter.html gzip | 520 B | 521 B | N/A |
| Overall change | 0 B | 0 B | ✓ |
Edge SSR bundle Size Overall increase ⚠️
| vercel/next.js canary | vercel/next.js perf-dev-scripts | Change | |
|---|---|---|---|
| edge-ssr.js gzip | 124 kB | 124 kB | N/A |
| page.js gzip | 238 kB | 239 kB | |
| Overall change | 238 kB | 239 kB |
Middleware size Overall increase ⚠️
| vercel/next.js canary | vercel/next.js perf-dev-scripts | Change | |
|---|---|---|---|
| middleware-b..fest.js gzip | 653 B | 656 B | N/A |
| middleware-r..fest.js gzip | 155 B | 156 B | N/A |
| middleware.js gzip | 32.6 kB | 32.9 kB | |
| edge-runtime..pack.js gzip | 846 B | 846 B | ✓ |
| Overall change | 33.4 kB | 33.8 kB |
Next Runtimes
| vercel/next.js canary | vercel/next.js perf-dev-scripts | Change | |
|---|---|---|---|
| app-page-exp...dev.js gzip | 302 kB | 302 kB | ✓ |
| app-page-exp..prod.js gzip | 157 kB | 157 kB | ✓ |
| app-page-tur...dev.js gzip | 302 kB | 302 kB | N/A |
| app-page-tur..prod.js gzip | 157 kB | 157 kB | ✓ |
| app-page-tur...dev.js gzip | 299 kB | 299 kB | N/A |
| app-page-tur..prod.js gzip | 155 kB | 155 kB | ✓ |
| app-page.run...dev.js gzip | 299 kB | 299 kB | N/A |
| app-page.run..prod.js gzip | 155 kB | 155 kB | ✓ |
| app-route-ex...dev.js gzip | 68.7 kB | 68.7 kB | ✓ |
| app-route-ex..prod.js gzip | 47.5 kB | 47.5 kB | ✓ |
| app-route-tu...dev.js gzip | 68.7 kB | 68.7 kB | ✓ |
| app-route-tu..prod.js gzip | 47.5 kB | 47.5 kB | ✓ |
| app-route-tu...dev.js gzip | 68.3 kB | 68.3 kB | ✓ |
| app-route-tu..prod.js gzip | 47.3 kB | 47.3 kB | ✓ |
| app-route.ru...dev.js gzip | 68.3 kB | 68.3 kB | ✓ |
| app-route.ru..prod.js gzip | 47.3 kB | 47.3 kB | ✓ |
| dist_client_...dev.js gzip | 324 B | 324 B | ✓ |
| dist_client_...dev.js gzip | 326 B | 326 B | ✓ |
| dist_client_...dev.js gzip | 318 B | 318 B | ✓ |
| dist_client_...dev.js gzip | 317 B | 317 B | ✓ |
| pages-api-tu...dev.js gzip | 41.1 kB | 41.1 kB | ✓ |
| pages-api-tu..prod.js gzip | 31.2 kB | 31.2 kB | ✓ |
| pages-api.ru...dev.js gzip | 41 kB | 41 kB | ✓ |
| pages-api.ru..prod.js gzip | 31.2 kB | 31.2 kB | ✓ |
| pages-turbo....dev.js gzip | 50.7 kB | 50.7 kB | ✓ |
| pages-turbo...prod.js gzip | 38.2 kB | 38.2 kB | ✓ |
| pages.runtim...dev.js gzip | 50.6 kB | 50.6 kB | ✓ |
| pages.runtim..prod.js gzip | 38.1 kB | 38.1 kB | ✓ |
| server.runti..prod.js gzip | 59.9 kB | 59.9 kB | ✓ |
| Overall change | 1.77 MB | 1.77 MB | ✓ |
build cache
| vercel/next.js canary | vercel/next.js perf-dev-scripts | Change | |
|---|---|---|---|
| 0.pack gzip | 3.62 MB | 3.62 MB | N/A |
| index.pack gzip | 99.3 kB | 97.8 kB | N/A |
| Overall change | 0 B | 0 B | ✓ |
Diff details
Diff for page.js
Diff too large to display
Diff for middleware.js
Diff too large to display
Diff for edge-ssr.js
Diff too large to display
Diff for _buildManifest.js
@@ -611,35 +611,35 @@ self.__BUILD_MANIFEST = (function (a, b, c) {
numHashes: NaN,
bitArray: [],
},
- "/": ["static\u002Fchunks\u002Fpages\u002Findex-dda7d8b64d4ba15c.js"],
+ "/": ["static\u002Fchunks\u002Fpages\u002Findex-d95f7ec6af4d2644.js"],
"/_error": [
- "static\u002Fchunks\u002Fpages\u002F_error-6ef44d3954f25711.js",
+ "static\u002Fchunks\u002Fpages\u002F_error-209c0c82205a7c9f.js",
],
"/css": [
"static\u002Fcss\u002Fded6b86ab9cc0a1f.css",
- "static\u002Fchunks\u002Fpages\u002Fcss-c8aaa7211416a045.js",
+ "static\u002Fchunks\u002Fpages\u002Fcss-62710339bc830ded.js",
],
"/dynamic": [
- "static\u002Fchunks\u002Fpages\u002Fdynamic-d53bb7f318f342c2.js",
+ "static\u002Fchunks\u002Fpages\u002Fdynamic-8ed3486bb68dd6c6.js",
],
"/edge-ssr": [
- "static\u002Fchunks\u002Fpages\u002Fedge-ssr-1383106d4a3e7d72.js",
+ "static\u002Fchunks\u002Fpages\u002Fedge-ssr-0db9f7bb610d3072.js",
],
- "/head": ["static\u002Fchunks\u002Fpages\u002Fhead-1db1c4be1a45662f.js"],
- "/hooks": ["static\u002Fchunks\u002Fpages\u002Fhooks-e6deee5b72a5b112.js"],
+ "/head": ["static\u002Fchunks\u002Fpages\u002Fhead-747416c4075e42aa.js"],
+ "/hooks": ["static\u002Fchunks\u002Fpages\u002Fhooks-8b10205be7505244.js"],
"/image": [
- "static\u002Fchunks\u002F2747-90c828280005c0c3.js",
- "static\u002Fchunks\u002Fpages\u002Fimage-868472cd5e84efc9.js",
+ "static\u002Fchunks\u002F6349-ee9aecde860d4832.js",
+ "static\u002Fchunks\u002Fpages\u002Fimage-f90ae17c3ad1d38b.js",
],
- "/link": ["static\u002Fchunks\u002Fpages\u002Flink-0ec374e48b2ce5d9.js"],
+ "/link": ["static\u002Fchunks\u002Fpages\u002Flink-6ab9a67b348df1bf.js"],
"/routerDirect": [
- "static\u002Fchunks\u002Fpages\u002FrouterDirect-1a34bfadbc088491.js",
+ "static\u002Fchunks\u002Fpages\u002FrouterDirect-f132fb471e65a8b9.js",
],
"/script": [
- "static\u002Fchunks\u002Fpages\u002Fscript-52320f59afbd096d.js",
+ "static\u002Fchunks\u002Fpages\u002Fscript-8e2028e44b8da2d9.js",
],
"/withRouter": [
- "static\u002Fchunks\u002Fpages\u002FwithRouter-3b1a16d3dfa21c16.js",
+ "static\u002Fchunks\u002Fpages\u002FwithRouter-a86d259faa012c1c.js",
],
sortedPages: [
"\u002F",Diff for dynamic-HASH.js
@@ -1,17 +1,24 @@
(self["webpackChunk_N_E"] = self["webpackChunk_N_E"] || []).push([
[2291],
{
- /***/ 1231: /***/ (
- module,
+ /***/ 2604: /***/ (
+ __unused_webpack_module,
__unused_webpack_exports,
__webpack_require__
) => {
- module.exports = __webpack_require__(4464);
+ (window.__NEXT_P = window.__NEXT_P || []).push([
+ "/dynamic",
+ function () {
+ return __webpack_require__(3643);
+ },
+ ]);
+ if (false) {
+ }
/***/
},
- /***/ 2101: /***/ (
+ /***/ 3401: /***/ (
__unused_webpack_module,
exports,
__webpack_require__
@@ -38,24 +45,63 @@
/***/
},
- /***/ 3458: /***/ (
+ /***/ 3643: /***/ (
__unused_webpack_module,
- __unused_webpack_exports,
+ __webpack_exports__,
__webpack_require__
) => {
- (window.__NEXT_P = window.__NEXT_P || []).push([
- "/dynamic",
- function () {
- return __webpack_require__(9381);
- },
- ]);
- if (false) {
- }
+ "use strict";
+ __webpack_require__.r(__webpack_exports__);
+ /* harmony export */ __webpack_require__.d(__webpack_exports__, {
+ /* harmony export */ __N_SSP: () => /* binding */ __N_SSP,
+ /* harmony export */ default: () => __WEBPACK_DEFAULT_EXPORT__,
+ /* harmony export */
+ });
+ /* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__ =
+ __webpack_require__(3108);
+ /* harmony import */ var next_dynamic__WEBPACK_IMPORTED_MODULE_1__ =
+ __webpack_require__(3973);
+ /* harmony import */ var next_dynamic__WEBPACK_IMPORTED_MODULE_1___default =
+ /*#__PURE__*/ __webpack_require__.n(
+ next_dynamic__WEBPACK_IMPORTED_MODULE_1__
+ );
+
+ const DynamicHello = next_dynamic__WEBPACK_IMPORTED_MODULE_1___default()(
+ () =>
+ __webpack_require__
+ .e(/* import() */ 1596)
+ .then(__webpack_require__.bind(__webpack_require__, 1596))
+ .then((mod) => mod.Hello),
+ {
+ loadableGenerated: {
+ webpack: () => [/*require.resolve*/ 1596],
+ },
+ }
+ );
+ const Page = () =>
+ /*#__PURE__*/ (0, react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)(
+ react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.Fragment,
+ {
+ children: [
+ /*#__PURE__*/ (0,
+ react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)("p", {
+ children: "testing next/dynamic size",
+ }),
+ /*#__PURE__*/ (0,
+ react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(
+ DynamicHello,
+ {}
+ ),
+ ],
+ }
+ );
+ var __N_SSP = true;
+ /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = Page;
/***/
},
- /***/ 4464: /***/ (module, exports, __webpack_require__) => {
+ /***/ 3660: /***/ (module, exports, __webpack_require__) => {
"use strict";
Object.defineProperty(exports, "__esModule", {
@@ -88,7 +134,7 @@
__webpack_require__(4312)
);
const _loadablesharedruntime = /*#__PURE__*/ _interop_require_default._(
- __webpack_require__(9799)
+ __webpack_require__(4539)
);
const isServerSide = "object" === "undefined";
// Normalize loader to return the module as form { default: Component } for `React.lazy`.
@@ -188,63 +234,17 @@
/***/
},
- /***/ 9381: /***/ (
- __unused_webpack_module,
- __webpack_exports__,
+ /***/ 3973: /***/ (
+ module,
+ __unused_webpack_exports,
__webpack_require__
) => {
- "use strict";
- __webpack_require__.r(__webpack_exports__);
- /* harmony export */ __webpack_require__.d(__webpack_exports__, {
- /* harmony export */ __N_SSP: () => /* binding */ __N_SSP,
- /* harmony export */ default: () => __WEBPACK_DEFAULT_EXPORT__,
- /* harmony export */
- });
- /* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__ =
- __webpack_require__(3108);
- /* harmony import */ var next_dynamic__WEBPACK_IMPORTED_MODULE_1__ =
- __webpack_require__(1231);
- /* harmony import */ var next_dynamic__WEBPACK_IMPORTED_MODULE_1___default =
- /*#__PURE__*/ __webpack_require__.n(
- next_dynamic__WEBPACK_IMPORTED_MODULE_1__
- );
-
- const DynamicHello = next_dynamic__WEBPACK_IMPORTED_MODULE_1___default()(
- () =>
- __webpack_require__
- .e(/* import() */ 2086)
- .then(__webpack_require__.bind(__webpack_require__, 2086))
- .then((mod) => mod.Hello),
- {
- loadableGenerated: {
- webpack: () => [/*require.resolve*/ 2086],
- },
- }
- );
- const Page = () =>
- /*#__PURE__*/ (0, react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)(
- react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.Fragment,
- {
- children: [
- /*#__PURE__*/ (0,
- react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)("p", {
- children: "testing next/dynamic size",
- }),
- /*#__PURE__*/ (0,
- react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(
- DynamicHello,
- {}
- ),
- ],
- }
- );
- var __N_SSP = true;
- /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = Page;
+ module.exports = __webpack_require__(3660);
/***/
},
- /***/ 9799: /***/ (
+ /***/ 4539: /***/ (
__unused_webpack_module,
exports,
__webpack_require__
@@ -286,7 +286,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE
const _react = /*#__PURE__*/ _interop_require_default._(
__webpack_require__(4312)
);
- const _loadablecontextsharedruntime = __webpack_require__(2101);
+ const _loadablecontextsharedruntime = __webpack_require__(3401);
function resolve(obj) {
return obj && obj.default ? obj.default : obj;
}
@@ -524,7 +524,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE
/******/ var __webpack_exec__ = (moduleId) =>
__webpack_require__((__webpack_require__.s = moduleId));
/******/ __webpack_require__.O(0, [636, 6593, 8792], () =>
- __webpack_exec__(3458)
+ __webpack_exec__(2604)
);
/******/ var __webpack_exports__ = __webpack_require__.O();
/******/ _N_E = __webpack_exports__;Diff for edge-ssr-HASH.js
@@ -1,7 +1,24 @@
(self["webpackChunk_N_E"] = self["webpackChunk_N_E"] || []).push([
[676],
{
- /***/ 1564: /***/ (
+ /***/ 7046: /***/ (
+ __unused_webpack_module,
+ __unused_webpack_exports,
+ __webpack_require__
+ ) => {
+ (window.__NEXT_P = window.__NEXT_P || []).push([
+ "/edge-ssr",
+ function () {
+ return __webpack_require__(7142);
+ },
+ ]);
+ if (false) {
+ }
+
+ /***/
+ },
+
+ /***/ 7142: /***/ (
__unused_webpack_module,
__webpack_exports__,
__webpack_require__
@@ -20,30 +37,13 @@
/***/
},
-
- /***/ 4300: /***/ (
- __unused_webpack_module,
- __unused_webpack_exports,
- __webpack_require__
- ) => {
- (window.__NEXT_P = window.__NEXT_P || []).push([
- "/edge-ssr",
- function () {
- return __webpack_require__(1564);
- },
- ]);
- if (false) {
- }
-
- /***/
- },
},
/******/ (__webpack_require__) => {
// webpackRuntimeModules
/******/ var __webpack_exec__ = (moduleId) =>
__webpack_require__((__webpack_require__.s = moduleId));
/******/ __webpack_require__.O(0, [636, 6593, 8792], () =>
- __webpack_exec__(4300)
+ __webpack_exec__(7046)
);
/******/ var __webpack_exports__ = __webpack_require__.O();
/******/ _N_E = __webpack_exports__;Diff for head-HASH.js
@@ -1,34 +1,17 @@
(self["webpackChunk_N_E"] = self["webpackChunk_N_E"] || []).push([
[5350],
{
- /***/ 1548: /***/ (
- __unused_webpack_module,
- __unused_webpack_exports,
- __webpack_require__
- ) => {
- (window.__NEXT_P = window.__NEXT_P || []).push([
- "/head",
- function () {
- return __webpack_require__(4282);
- },
- ]);
- if (false) {
- }
-
- /***/
- },
-
- /***/ 3952: /***/ (
+ /***/ 3770: /***/ (
module,
__unused_webpack_exports,
__webpack_require__
) => {
- module.exports = __webpack_require__(1653);
+ module.exports = __webpack_require__(9025);
/***/
},
- /***/ 4282: /***/ (
+ /***/ 6236: /***/ (
__unused_webpack_module,
__webpack_exports__,
__webpack_require__
@@ -43,7 +26,7 @@
/* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__ =
__webpack_require__(3108);
/* harmony import */ var next_head__WEBPACK_IMPORTED_MODULE_1__ =
- __webpack_require__(3952);
+ __webpack_require__(3770);
/* harmony import */ var next_head__WEBPACK_IMPORTED_MODULE_1___default =
/*#__PURE__*/ __webpack_require__.n(
next_head__WEBPACK_IMPORTED_MODULE_1__
@@ -76,13 +59,30 @@
/***/
},
+
+ /***/ 6510: /***/ (
+ __unused_webpack_module,
+ __unused_webpack_exports,
+ __webpack_require__
+ ) => {
+ (window.__NEXT_P = window.__NEXT_P || []).push([
+ "/head",
+ function () {
+ return __webpack_require__(6236);
+ },
+ ]);
+ if (false) {
+ }
+
+ /***/
+ },
},
/******/ (__webpack_require__) => {
// webpackRuntimeModules
/******/ var __webpack_exec__ = (moduleId) =>
__webpack_require__((__webpack_require__.s = moduleId));
/******/ __webpack_require__.O(0, [636, 6593, 8792], () =>
- __webpack_exec__(1548)
+ __webpack_exec__(6510)
);
/******/ var __webpack_exports__ = __webpack_require__.O();
/******/ _N_E = __webpack_exports__;Diff for index-HASH.js
@@ -1,24 +1,7 @@
(self["webpackChunk_N_E"] = self["webpackChunk_N_E"] || []).push([
[3332],
{
- /***/ 6376: /***/ (
- __unused_webpack_module,
- __unused_webpack_exports,
- __webpack_require__
- ) => {
- (window.__NEXT_P = window.__NEXT_P || []).push([
- "/",
- function () {
- return __webpack_require__(8460);
- },
- ]);
- if (false) {
- }
-
- /***/
- },
-
- /***/ 8460: /***/ (
+ /***/ 830: /***/ (
__unused_webpack_module,
__webpack_exports__,
__webpack_require__
@@ -36,13 +19,30 @@
/***/
},
+
+ /***/ 1938: /***/ (
+ __unused_webpack_module,
+ __unused_webpack_exports,
+ __webpack_require__
+ ) => {
+ (window.__NEXT_P = window.__NEXT_P || []).push([
+ "/",
+ function () {
+ return __webpack_require__(830);
+ },
+ ]);
+ if (false) {
+ }
+
+ /***/
+ },
},
/******/ (__webpack_require__) => {
// webpackRuntimeModules
/******/ var __webpack_exec__ = (moduleId) =>
__webpack_require__((__webpack_require__.s = moduleId));
/******/ __webpack_require__.O(0, [636, 6593, 8792], () =>
- __webpack_exec__(6376)
+ __webpack_exec__(1938)
);
/******/ var __webpack_exports__ = __webpack_require__.O();
/******/ _N_E = __webpack_exports__;Diff for link-HASH.js
@@ -1,7 +1,220 @@
(self["webpackChunk_N_E"] = self["webpackChunk_N_E"] || []).push([
[4672],
{
- /***/ 857: /***/ (module, exports, __webpack_require__) => {
+ /***/ 2774: /***/ (module, exports, __webpack_require__) => {
+ "use strict";
+
+ Object.defineProperty(exports, "__esModule", {
+ value: true,
+ });
+ Object.defineProperty(exports, "useIntersection", {
+ enumerable: true,
+ get: function () {
+ return useIntersection;
+ },
+ });
+ const _react = __webpack_require__(4312);
+ const _requestidlecallback = __webpack_require__(9413);
+ const hasIntersectionObserver =
+ typeof IntersectionObserver === "function";
+ const observers = new Map();
+ const idList = [];
+ function createObserver(options) {
+ const id = {
+ root: options.root || null,
+ margin: options.rootMargin || "",
+ };
+ const existing = idList.find(
+ (obj) => obj.root === id.root && obj.margin === id.margin
+ );
+ let instance;
+ if (existing) {
+ instance = observers.get(existing);
+ if (instance) {
+ return instance;
+ }
+ }
+ const elements = new Map();
+ const observer = new IntersectionObserver((entries) => {
+ entries.forEach((entry) => {
+ const callback = elements.get(entry.target);
+ const isVisible =
+ entry.isIntersecting || entry.intersectionRatio > 0;
+ if (callback && isVisible) {
+ callback(isVisible);
+ }
+ });
+ }, options);
+ instance = {
+ id,
+ observer,
+ elements,
+ };
+ idList.push(id);
+ observers.set(id, instance);
+ return instance;
+ }
+ function observe(element, callback, options) {
+ const { id, observer, elements } = createObserver(options);
+ elements.set(element, callback);
+ observer.observe(element);
+ return function unobserve() {
+ elements.delete(element);
+ observer.unobserve(element);
+ // Destroy observer when there's nothing left to watch:
+ if (elements.size === 0) {
+ observer.disconnect();
+ observers.delete(id);
+ const index = idList.findIndex(
+ (obj) => obj.root === id.root && obj.margin === id.margin
+ );
+ if (index > -1) {
+ idList.splice(index, 1);
+ }
+ }
+ };
+ }
+ function useIntersection({ rootRef, rootMargin, disabled }) {
+ const isDisabled = disabled || !hasIntersectionObserver;
+ const [visible, setVisible] = (0, _react.useState)(false);
+ const elementRef = (0, _react.useRef)(null);
+ const setElement = (0, _react.useCallback)((element) => {
+ elementRef.current = element;
+ }, []);
+ (0, _react.useEffect)(() => {
+ if (hasIntersectionObserver) {
+ if (isDisabled || visible) return;
+ const element = elementRef.current;
+ if (element && element.tagName) {
+ const unobserve = observe(
+ element,
+ (isVisible) => isVisible && setVisible(isVisible),
+ {
+ root: rootRef?.current,
+ rootMargin,
+ }
+ );
+ return unobserve;
+ }
+ } else {
+ if (!visible) {
+ const idleCallback = (0,
+ _requestidlecallback.requestIdleCallback)(() => setVisible(true));
+ return () =>
+ (0, _requestidlecallback.cancelIdleCallback)(idleCallback);
+ }
+ }
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [isDisabled, rootMargin, rootRef, visible, elementRef.current]);
+ const resetVisible = (0, _react.useCallback)(() => {
+ setVisible(false);
+ }, []);
+ return [setElement, visible, resetVisible];
+ }
+ if (
+ (typeof exports.default === "function" ||
+ (typeof exports.default === "object" && exports.default !== null)) &&
+ typeof exports.default.__esModule === "undefined"
+ ) {
+ Object.defineProperty(exports.default, "__esModule", {
+ value: true,
+ });
+ Object.assign(exports.default, exports);
+ module.exports = exports.default;
+ } //# sourceMappingURL=use-intersection.js.map
+
+ /***/
+ },
+
+ /***/ 3351: /***/ (module, exports, __webpack_require__) => {
+ "use strict";
+
+ Object.defineProperty(exports, "__esModule", {
+ value: true,
+ });
+ Object.defineProperty(exports, "useMergedRef", {
+ enumerable: true,
+ get: function () {
+ return useMergedRef;
+ },
+ });
+ const _react = __webpack_require__(4312);
+ function useMergedRef(refA, refB) {
+ const cleanupA = (0, _react.useRef)(null);
+ const cleanupB = (0, _react.useRef)(null);
+ // NOTE: In theory, we could skip the wrapping if only one of the refs is non-null.
+ // (this happens often if the user doesn't pass a ref to Link/Form/Image)
+ // But this can cause us to leak a cleanup-ref into user code (previously via `<Link legacyBehavior>`),
+ // and the user might pass that ref into ref-merging library that doesn't support cleanup refs
+ // (because it hasn't been updated for React 19)
+ // which can then cause things to blow up, because a cleanup-returning ref gets called with `null`.
+ // So in practice, it's safer to be defensive and always wrap the ref, even on React 19.
+ return (0, _react.useCallback)(
+ (current) => {
+ if (current === null) {
+ const cleanupFnA = cleanupA.current;
+ if (cleanupFnA) {
+ cleanupA.current = null;
+ cleanupFnA();
+ }
+ const cleanupFnB = cleanupB.current;
+ if (cleanupFnB) {
+ cleanupB.current = null;
+ cleanupFnB();
+ }
+ } else {
+ if (refA) {
+ cleanupA.current = applyRef(refA, current);
+ }
+ if (refB) {
+ cleanupB.current = applyRef(refB, current);
+ }
+ }
+ },
+ [refA, refB]
+ );
+ }
+ function applyRef(refA, current) {
+ if (typeof refA === "function") {
+ const cleanup = refA(current);
+ if (typeof cleanup === "function") {
+ return cleanup;
+ } else {
+ return () => refA(null);
+ }
+ } else {
+ refA.current = current;
+ return () => {
+ refA.current = null;
+ };
+ }
+ }
+ if (
+ (typeof exports.default === "function" ||
+ (typeof exports.default === "object" && exports.default !== null)) &&
+ typeof exports.default.__esModule === "undefined"
+ ) {
+ Object.defineProperty(exports.default, "__esModule", {
+ value: true,
+ });
+ Object.assign(exports.default, exports);
+ module.exports = exports.default;
+ } //# sourceMappingURL=use-merged-ref.js.map
+
+ /***/
+ },
+
+ /***/ 3440: /***/ (
+ module,
+ __unused_webpack_exports,
+ __webpack_require__
+ ) => {
+ module.exports = __webpack_require__(4757);
+
+ /***/
+ },
+
+ /***/ 4757: /***/ (module, exports, __webpack_require__) => {
"use strict";
/* __next_internal_client_entry_do_not_use__ cjs */
Object.defineProperty(exports, "__esModule", {
@@ -23,22 +236,22 @@
return useLinkStatus;
},
});
- const _interop_require_wildcard = __webpack_require__(8781);
+ const _interop_require_wildcard = __webpack_require__(1162);
const _jsxruntime = __webpack_require__(3108);
const _react = /*#__PURE__*/ _interop_require_wildcard._(
__webpack_require__(4312)
);
- const _resolvehref = __webpack_require__(4055);
- const _islocalurl = __webpack_require__(7175);
- const _formaturl = __webpack_require__(9674);
- const _utils = __webpack_require__(7424);
- const _addlocale = __webpack_require__(589);
- const _routercontextsharedruntime = __webpack_require__(7010);
- const _useintersection = __webpack_require__(2330);
- const _getdomainlocale = __webpack_require__(7207);
- const _addbasepath = __webpack_require__(9942);
- const _usemergedref = __webpack_require__(8067);
- const _erroronce = __webpack_require__(1945);
+ const _resolvehref = __webpack_require__(4691);
+ const _islocalurl = __webpack_require__(4763);
+ const _formaturl = __webpack_require__(3246);
+ const _utils = __webpack_require__(7372);
+ const _addlocale = __webpack_require__(1809);
+ const _routercontextsharedruntime = __webpack_require__(2254);
+ const _useintersection = __webpack_require__(2774);
+ const _getdomainlocale = __webpack_require__(8803);
+ const _addbasepath = __webpack_require__(5834);
+ const _usemergedref = __webpack_require__(3351);
+ const _erroronce = __webpack_require__(6021);
const prefetched = new Set();
function prefetch(router, href, as, options) {
if (false) {
@@ -417,168 +630,43 @@
/***/
},
- /***/ 1945: /***/ (__unused_webpack_module, exports) => {
- "use strict";
-
- Object.defineProperty(exports, "__esModule", {
- value: true,
- });
- Object.defineProperty(exports, "errorOnce", {
- enumerable: true,
- get: function () {
- return errorOnce;
+ /***/ 5326: /***/ (
+ __unused_webpack_module,
+ __unused_webpack_exports,
+ __webpack_require__
+ ) => {
+ (window.__NEXT_P = window.__NEXT_P || []).push([
+ "/link",
+ function () {
+ return __webpack_require__(9058);
},
- });
- let errorOnce = (_) => {};
+ ]);
if (false) {
- } //# sourceMappingURL=error-once.js.map
+ }
/***/
},
- /***/ 2330: /***/ (module, exports, __webpack_require__) => {
+ /***/ 6021: /***/ (__unused_webpack_module, exports) => {
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true,
});
- Object.defineProperty(exports, "useIntersection", {
+ Object.defineProperty(exports, "errorOnce", {
enumerable: true,
get: function () {
- return useIntersection;
+ return errorOnce;
},
});
- const _react = __webpack_require__(4312);
- const _requestidlecallback = __webpack_require__(601);
- const hasIntersectionObserver =
- typeof IntersectionObserver === "function";
- const observers = new Map();
- const idList = [];
- function createObserver(options) {
- const id = {
- root: options.root || null,
- margin: options.rootMargin || "",
- };
- const existing = idList.find(
- (obj) => obj.root === id.root && obj.margin === id.margin
- );
- let instance;
- if (existing) {
- instance = observers.get(existing);
- if (instance) {
- return instance;
- }
- }
- const elements = new Map();
- const observer = new IntersectionObserver((entries) => {
- entries.forEach((entry) => {
- const callback = elements.get(entry.target);
- const isVisible =
- entry.isIntersecting || entry.intersectionRatio > 0;
- if (callback && isVisible) {
- callback(isVisible);
- }
- });
- }, options);
- instance = {
- id,
- observer,
- elements,
- };
- idList.push(id);
- observers.set(id, instance);
- return instance;
- }
- function observe(element, callback, options) {
- const { id, observer, elements } = createObserver(options);
- elements.set(element, callback);
- observer.observe(element);
- return function unobserve() {
- elements.delete(element);
- observer.unobserve(element);
- // Destroy observer when there's nothing left to watch:
- if (elements.size === 0) {
- observer.disconnect();
- observers.delete(id);
- const index = idList.findIndex(
- (obj) => obj.root === id.root && obj.margin === id.margin
- );
- if (index > -1) {
- idList.splice(index, 1);
- }
- }
- };
- }
- function useIntersection({ rootRef, rootMargin, disabled }) {
- const isDisabled = disabled || !hasIntersectionObserver;
- const [visible, setVisible] = (0, _react.useState)(false);
- const elementRef = (0, _react.useRef)(null);
- const setElement = (0, _react.useCallback)((element) => {
- elementRef.current = element;
- }, []);
- (0, _react.useEffect)(() => {
- if (hasIntersectionObserver) {
- if (isDisabled || visible) return;
- const element = elementRef.current;
- if (element && element.tagName) {
- const unobserve = observe(
- element,
- (isVisible) => isVisible && setVisible(isVisible),
- {
- root: rootRef?.current,
- rootMargin,
- }
- );
- return unobserve;
- }
- } else {
- if (!visible) {
- const idleCallback = (0,
- _requestidlecallback.requestIdleCallback)(() => setVisible(true));
- return () =>
- (0, _requestidlecallback.cancelIdleCallback)(idleCallback);
- }
- }
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, [isDisabled, rootMargin, rootRef, visible, elementRef.current]);
- const resetVisible = (0, _react.useCallback)(() => {
- setVisible(false);
- }, []);
- return [setElement, visible, resetVisible];
- }
- if (
- (typeof exports.default === "function" ||
- (typeof exports.default === "object" && exports.default !== null)) &&
- typeof exports.default.__esModule === "undefined"
- ) {
- Object.defineProperty(exports.default, "__esModule", {
- value: true,
- });
- Object.assign(exports.default, exports);
- module.exports = exports.default;
- } //# sourceMappingURL=use-intersection.js.map
-
- /***/
- },
-
- /***/ 4972: /***/ (
- __unused_webpack_module,
- __unused_webpack_exports,
- __webpack_require__
- ) => {
- (window.__NEXT_P = window.__NEXT_P || []).push([
- "/link",
- function () {
- return __webpack_require__(7600);
- },
- ]);
+ let errorOnce = (_) => {};
if (false) {
- }
+ } //# sourceMappingURL=error-once.js.map
/***/
},
- /***/ 7207: /***/ (module, exports, __webpack_require__) => {
+ /***/ 8803: /***/ (module, exports, __webpack_require__) => {
"use strict";
Object.defineProperty(exports, "__esModule", {
@@ -590,7 +678,7 @@
return getDomainLocale;
},
});
- const _normalizetrailingslash = __webpack_require__(151);
+ const _normalizetrailingslash = __webpack_require__(1315);
const basePath =
/* unused pure expression or super */ null && (false || "");
function getDomainLocale(path, locale, locales, domainLocales) {
@@ -614,7 +702,7 @@
/***/
},
- /***/ 7600: /***/ (
+ /***/ 9058: /***/ (
__unused_webpack_module,
__webpack_exports__,
__webpack_require__
@@ -629,7 +717,7 @@
/* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__ =
__webpack_require__(3108);
/* harmony import */ var next_link__WEBPACK_IMPORTED_MODULE_1__ =
- __webpack_require__(7830);
+ __webpack_require__(3440);
/* harmony import */ var next_link__WEBPACK_IMPORTED_MODULE_1___default =
/*#__PURE__*/ __webpack_require__.n(
next_link__WEBPACK_IMPORTED_MODULE_1__
@@ -659,101 +747,13 @@
/***/
},
-
- /***/ 7830: /***/ (
- module,
- __unused_webpack_exports,
- __webpack_require__
- ) => {
- module.exports = __webpack_require__(857);
-
- /***/
- },
-
- /***/ 8067: /***/ (module, exports, __webpack_require__) => {
- "use strict";
-
- Object.defineProperty(exports, "__esModule", {
- value: true,
- });
- Object.defineProperty(exports, "useMergedRef", {
- enumerable: true,
- get: function () {
- return useMergedRef;
- },
- });
- const _react = __webpack_require__(4312);
- function useMergedRef(refA, refB) {
- const cleanupA = (0, _react.useRef)(null);
- const cleanupB = (0, _react.useRef)(null);
- // NOTE: In theory, we could skip the wrapping if only one of the refs is non-null.
- // (this happens often if the user doesn't pass a ref to Link/Form/Image)
- // But this can cause us to leak a cleanup-ref into user code (previously via `<Link legacyBehavior>`),
- // and the user might pass that ref into ref-merging library that doesn't support cleanup refs
- // (because it hasn't been updated for React 19)
- // which can then cause things to blow up, because a cleanup-returning ref gets called with `null`.
- // So in practice, it's safer to be defensive and always wrap the ref, even on React 19.
- return (0, _react.useCallback)(
- (current) => {
- if (current === null) {
- const cleanupFnA = cleanupA.current;
- if (cleanupFnA) {
- cleanupA.current = null;
- cleanupFnA();
- }
- const cleanupFnB = cleanupB.current;
- if (cleanupFnB) {
- cleanupB.current = null;
- cleanupFnB();
- }
- } else {
- if (refA) {
- cleanupA.current = applyRef(refA, current);
- }
- if (refB) {
- cleanupB.current = applyRef(refB, current);
- }
- }
- },
- [refA, refB]
- );
- }
- function applyRef(refA, current) {
- if (typeof refA === "function") {
- const cleanup = refA(current);
- if (typeof cleanup === "function") {
- return cleanup;
- } else {
- return () => refA(null);
- }
- } else {
- refA.current = current;
- return () => {
- refA.current = null;
- };
- }
- }
- if (
- (typeof exports.default === "function" ||
- (typeof exports.default === "object" && exports.default !== null)) &&
- typeof exports.default.__esModule === "undefined"
- ) {
- Object.defineProperty(exports.default, "__esModule", {
- value: true,
- });
- Object.assign(exports.default, exports);
- module.exports = exports.default;
- } //# sourceMappingURL=use-merged-ref.js.map
-
- /***/
- },
},
/******/ (__webpack_require__) => {
// webpackRuntimeModules
/******/ var __webpack_exec__ = (moduleId) =>
__webpack_require__((__webpack_require__.s = moduleId));
/******/ __webpack_require__.O(0, [636, 6593, 8792], () =>
- __webpack_exec__(4972)
+ __webpack_exec__(5326)
);
/******/ var __webpack_exports__ = __webpack_require__.O();
/******/ _N_E = __webpack_exports__;Diff for routerDirect-HASH.js
@@ -1,17 +1,7 @@
(self["webpackChunk_N_E"] = self["webpackChunk_N_E"] || []).push([
[188],
{
- /***/ 1179: /***/ (
- module,
- __unused_webpack_exports,
- __webpack_require__
- ) => {
- module.exports = __webpack_require__(9864);
-
- /***/
- },
-
- /***/ 1640: /***/ (
+ /***/ 2014: /***/ (
__unused_webpack_module,
__webpack_exports__,
__webpack_require__
@@ -26,7 +16,7 @@
/* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__ =
__webpack_require__(3108);
/* harmony import */ var next_router__WEBPACK_IMPORTED_MODULE_1__ =
- __webpack_require__(1179);
+ __webpack_require__(4169);
/* harmony import */ var next_router__WEBPACK_IMPORTED_MODULE_1___default =
/*#__PURE__*/ __webpack_require__.n(
next_router__WEBPACK_IMPORTED_MODULE_1__
@@ -46,7 +36,17 @@
/***/
},
- /***/ 2172: /***/ (
+ /***/ 4169: /***/ (
+ module,
+ __unused_webpack_exports,
+ __webpack_require__
+ ) => {
+ module.exports = __webpack_require__(9700);
+
+ /***/
+ },
+
+ /***/ 4414: /***/ (
__unused_webpack_module,
__unused_webpack_exports,
__webpack_require__
@@ -54,7 +54,7 @@
(window.__NEXT_P = window.__NEXT_P || []).push([
"/routerDirect",
function () {
- return __webpack_require__(1640);
+ return __webpack_require__(2014);
},
]);
if (false) {
@@ -68,7 +68,7 @@
/******/ var __webpack_exec__ = (moduleId) =>
__webpack_require__((__webpack_require__.s = moduleId));
/******/ __webpack_require__.O(0, [636, 6593, 8792], () =>
- __webpack_exec__(2172)
+ __webpack_exec__(4414)
);
/******/ var __webpack_exports__ = __webpack_require__.O();
/******/ _N_E = __webpack_exports__;Diff for script-HASH.js
@@ -1,17 +1,34 @@
(self["webpackChunk_N_E"] = self["webpackChunk_N_E"] || []).push([
[1209],
{
- /***/ 4977: /***/ (
+ /***/ 2591: /***/ (
module,
__unused_webpack_exports,
__webpack_require__
) => {
- module.exports = __webpack_require__(326);
+ module.exports = __webpack_require__(4634);
/***/
},
- /***/ 5887: /***/ (
+ /***/ 5030: /***/ (
+ __unused_webpack_module,
+ __unused_webpack_exports,
+ __webpack_require__
+ ) => {
+ (window.__NEXT_P = window.__NEXT_P || []).push([
+ "/script",
+ function () {
+ return __webpack_require__(7557);
+ },
+ ]);
+ if (false) {
+ }
+
+ /***/
+ },
+
+ /***/ 7557: /***/ (
__unused_webpack_module,
__webpack_exports__,
__webpack_require__
@@ -26,7 +43,7 @@
/* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__ =
__webpack_require__(3108);
/* harmony import */ var next_script__WEBPACK_IMPORTED_MODULE_1__ =
- __webpack_require__(4977);
+ __webpack_require__(2591);
/* harmony import */ var next_script__WEBPACK_IMPORTED_MODULE_1___default =
/*#__PURE__*/ __webpack_require__.n(
next_script__WEBPACK_IMPORTED_MODULE_1__
@@ -58,30 +75,13 @@
/***/
},
-
- /***/ 6268: /***/ (
- __unused_webpack_module,
- __unused_webpack_exports,
- __webpack_require__
- ) => {
- (window.__NEXT_P = window.__NEXT_P || []).push([
- "/script",
- function () {
- return __webpack_require__(5887);
- },
- ]);
- if (false) {
- }
-
- /***/
- },
},
/******/ (__webpack_require__) => {
// webpackRuntimeModules
/******/ var __webpack_exec__ = (moduleId) =>
__webpack_require__((__webpack_require__.s = moduleId));
/******/ __webpack_require__.O(0, [636, 6593, 8792], () =>
- __webpack_exec__(6268)
+ __webpack_exec__(5030)
);
/******/ var __webpack_exports__ = __webpack_require__.O();
/******/ _N_E = __webpack_exports__;Diff for withRouter-HASH.js
@@ -1,34 +1,7 @@
(self["webpackChunk_N_E"] = self["webpackChunk_N_E"] || []).push([
[3263],
{
- /***/ 1179: /***/ (
- module,
- __unused_webpack_exports,
- __webpack_require__
- ) => {
- module.exports = __webpack_require__(9864);
-
- /***/
- },
-
- /***/ 2028: /***/ (
- __unused_webpack_module,
- __unused_webpack_exports,
- __webpack_require__
- ) => {
- (window.__NEXT_P = window.__NEXT_P || []).push([
- "/withRouter",
- function () {
- return __webpack_require__(4501);
- },
- ]);
- if (false) {
- }
-
- /***/
- },
-
- /***/ 4501: /***/ (
+ /***/ 559: /***/ (
__unused_webpack_module,
__webpack_exports__,
__webpack_require__
@@ -43,7 +16,7 @@
/* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__ =
__webpack_require__(3108);
/* harmony import */ var next_router__WEBPACK_IMPORTED_MODULE_1__ =
- __webpack_require__(1179);
+ __webpack_require__(4169);
/* harmony import */ var next_router__WEBPACK_IMPORTED_MODULE_1___default =
/*#__PURE__*/ __webpack_require__.n(
next_router__WEBPACK_IMPORTED_MODULE_1__
@@ -61,13 +34,40 @@
/***/
},
+
+ /***/ 726: /***/ (
+ __unused_webpack_module,
+ __unused_webpack_exports,
+ __webpack_require__
+ ) => {
+ (window.__NEXT_P = window.__NEXT_P || []).push([
+ "/withRouter",
+ function () {
+ return __webpack_require__(559);
+ },
+ ]);
+ if (false) {
+ }
+
+ /***/
+ },
+
+ /***/ 4169: /***/ (
+ module,
+ __unused_webpack_exports,
+ __webpack_require__
+ ) => {
+ module.exports = __webpack_require__(9700);
+
+ /***/
+ },
},
/******/ (__webpack_require__) => {
// webpackRuntimeModules
/******/ var __webpack_exec__ = (moduleId) =>
__webpack_require__((__webpack_require__.s = moduleId));
/******/ __webpack_require__.O(0, [636, 6593, 8792], () =>
- __webpack_exec__(2028)
+ __webpack_exec__(726)
);
/******/ var __webpack_exports__ = __webpack_require__.O();
/******/ _N_E = __webpack_exports__;Diff for 2161-HASH.js
Diff too large to display
Diff for 2747-HASH.js
Diff too large to display
Diff for 4322-HASH.js
failed to diffDiff for main-HASH.js
Diff too large to display
✅ Tests PassedUpdated 2026-01-01 20:57:30 UTC · Commit: 9718f19 |
7eb9491 to
8f76e8a
Compare
8f76e8a to
3517bf6
Compare
3517bf6 to
4f78126
Compare
ea5e533 to
12c85c1
Compare
4f78126 to
0aaff46
Compare
fc4e20e to
dac73f8
Compare
dac73f8 to
825d52a
Compare
1b5f052 to
ddae4cb
Compare
825d52a to
97d217c
Compare
ddae4cb to
f5f9f70
Compare
97d217c to
2f34bc1
Compare
f5f9f70 to
e7f9cde
Compare
2c33314 to
0fd2a8f
Compare
7bda420 to
ff755ce
Compare
0fd2a8f to
c093116
Compare
c093116 to
d312852
Compare
ff755ce to
40a4c11
Compare
d312852 to
098df8c
Compare
| fi | ||
|
|
||
| # Measure wall-clock time from command start | ||
| local start_time=$(python3 -c 'import time; print(int(time.time() * 1000))') |
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.
Script will fail if python3 is not installed. This is used for millisecond timestamp generation but python3 is not universally available on all systems (particularly older macOS or minimal Linux containers).
Fix: Use date +%s%3N on Linux or add a fallback:
local start_time=$(date +%s%3N 2>/dev/null || python3 -c 'import time; print(int(time.time() * 1000))')Note: date +%s%3N doesn't work on macOS, so a more robust cross-platform solution would check the OS first.
Spotted by Graphite Agent
Is this helpful? React 👍 or 👎 to let us know.
098df8c to
2b3bcde
Compare
- benchmark-boot-time.sh: Wall-clock benchmark with two metrics - benchmark-next-dev-boot.js: Multi-iteration benchmark with stats - profile-next-dev-boot.js: CPU profiling infrastructure - analyze-*.js: Profile and bundle analysis tools - trace-cli-startup.js: Module loading trace 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <[email protected]>
2b3bcde to
9d6987d
Compare
9d6987d to
a4f5cf1
Compare
| const min = Math.min(...times) | ||
| const max = Math.max(...times) | ||
| const sorted = [...times].sort((a, b) => a - b) | ||
| const median = sorted[Math.floor(sorted.length / 2)] |
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.
| const median = sorted[Math.floor(sorted.length / 2)] | |
| const median = | |
| sorted.length % 2 === 0 | |
| ? (sorted[sorted.length / 2 - 1] + sorted[sorted.length / 2]) / 2 | |
| : sorted[Math.floor(sorted.length / 2)] |
The median calculation is incorrect for arrays with an even number of elements. It returns the upper-middle element instead of averaging the two middle elements, which can skew benchmark statistics.
View Details
Analysis
Incorrect median calculation for even-length arrays in benchmark script
What fails: The calcStats() function in scripts/benchmark-next-dev-boot.js line 158 uses sorted[Math.floor(sorted.length / 2)] which returns the upper-middle element for even-length arrays instead of averaging the two middle elements.
How to reproduce:
// For even-length array [10, 20, 30, 40]:
const sorted = [10, 20, 30, 40];
const median = sorted[Math.floor(sorted.length / 2)]; // Returns 30
const correct = (sorted[1] + sorted[2]) / 2; // Should be 25Result: For 4-element array returns 30, for 2-element array returns 20
Expected: Median should be the average of the two middle elements for even-length arrays:
- [10, 20, 30, 40] → (20 + 30) / 2 = 25
- [10, 20] → (10 + 20) / 2 = 15
- For odd-length arrays, the current implementation happens to work correctly by coincidence
This causes inaccurate median statistics in benchmark results, misrepresenting Next.js boot time performance profiles.
Merge activity
|

Summary
Development scripts for profiling and benchmarking Next.js dev server boot time.
Benchmarking Scripts
benchmark-boot-time.sh- Wall-clock benchmarking with two metrics:benchmark-next-dev-boot.js- Multi-iteration benchmarking with statistics (median, p95, stddev)Profiling Scripts
profile-next-dev-boot.js- CPU profiling infrastructure using V8 inspectoranalyze-profile.js- Analyze CPU profiles to identify hot modules by CPU timeAnalysis Scripts
analyze-dev-server-bundle.js- Bundle analyzer for dev server (generates treemap report)trace-cli-startup.js- Module loading trace to identify slow importsUsage
Test Plan
./scripts/benchmark-boot-time.shlocally