react-render-profiler 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +134 -0
- package/dist/index.d.ts +26 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +105 -0
- package/dist/index.js.map +1 -0
- package/package.json +51 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Bogdan
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
# React Render Profiler
|
|
2
|
+
|
|
3
|
+
A tiny profiler helper to measure initial render + rerender timings for React components.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm i react-render-profiler
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Why
|
|
12
|
+
|
|
13
|
+
Use it when you want:
|
|
14
|
+
|
|
15
|
+
- render count and rerender count per component instance
|
|
16
|
+
- approximate commit timing (`render start` -> `useEffect`)
|
|
17
|
+
- delayed aggregated reporting to keep console noise low
|
|
18
|
+
|
|
19
|
+
## Usage (HOC)
|
|
20
|
+
|
|
21
|
+
```tsx
|
|
22
|
+
import { withRenderProfiler } from 'react-render-profiler';
|
|
23
|
+
import { ProductCard } from './ProductCard';
|
|
24
|
+
|
|
25
|
+
export default withRenderProfiler(ProductCard, {
|
|
26
|
+
reportAfterMs: 5000,
|
|
27
|
+
logEachRender: false
|
|
28
|
+
});
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Actual usage patterns
|
|
32
|
+
|
|
33
|
+
### 1) Wrap component on export (global for all usages)
|
|
34
|
+
|
|
35
|
+
```tsx
|
|
36
|
+
function MenuItem(props) {
|
|
37
|
+
...
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export default withRenderProfiler(MenuItem, {
|
|
41
|
+
componentName: 'MenuItem',
|
|
42
|
+
groupByComponent: true,
|
|
43
|
+
enabled: process.env.NODE_ENV !== 'production',
|
|
44
|
+
reportAfterMs: 5000,
|
|
45
|
+
});
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### 2) Wrap only in one place (recommended for focused profiling)
|
|
49
|
+
|
|
50
|
+
```tsx
|
|
51
|
+
const FooterProfiled = withRenderProfiler(FooterWidget, {
|
|
52
|
+
componentName: 'HomePage:FooterWidget',
|
|
53
|
+
groupByComponent: true,
|
|
54
|
+
enabled: process.env.NODE_ENV !== 'production',
|
|
55
|
+
reportAfterMs: 5000,
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
// Inside ProductPage:
|
|
59
|
+
<RecommendationsWidgetProfiled productAlias={product.alias} />
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Measure only specific usage
|
|
63
|
+
|
|
64
|
+
For HOC usage, `enabled` can be a function of component props.
|
|
65
|
+
This lets you measure only specific places/instances and keep others unprofiled.
|
|
66
|
+
|
|
67
|
+
```tsx
|
|
68
|
+
type CardProps = { alias: string; profileRender?: boolean };
|
|
69
|
+
|
|
70
|
+
const ProductCardProfiled = withRenderProfiler<CardProps>(ProductCard, {
|
|
71
|
+
componentName: 'ProductCard',
|
|
72
|
+
groupByComponent: true,
|
|
73
|
+
enabled: (props) => props.profileRender === true,
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
// Only this usage is measured:
|
|
77
|
+
<ProductCardProfiled alias="a" profileRender />
|
|
78
|
+
|
|
79
|
+
// This usage is ignored by profiler:
|
|
80
|
+
<ProductCardProfiled alias="b" />
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Usage (Hook)
|
|
84
|
+
|
|
85
|
+
```tsx
|
|
86
|
+
import { useRenderProfiler } from 'react-render-profiler';
|
|
87
|
+
|
|
88
|
+
export function CheckoutSidebar() {
|
|
89
|
+
useRenderProfiler('CheckoutSidebar', { reportAfterMs: 3000 });
|
|
90
|
+
return <aside>...</aside>;
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## API
|
|
95
|
+
|
|
96
|
+
### `withRenderProfiler(Component, options?)`
|
|
97
|
+
|
|
98
|
+
Wraps a component and reports stats to console after inactivity timeout.
|
|
99
|
+
|
|
100
|
+
### `useRenderProfiler(componentName, options?)`
|
|
101
|
+
|
|
102
|
+
Hook variant when you do not want to wrap export.
|
|
103
|
+
|
|
104
|
+
### `options`
|
|
105
|
+
|
|
106
|
+
- `reportAfterMs` (default `3000`) - report debounce timeout
|
|
107
|
+
- `groupByComponent` (default `false`) - aggregate all instances under one component report
|
|
108
|
+
- `logEachRender` (default `false`) - emit log on every commit
|
|
109
|
+
- `enabled` (default `true`) - disable profiler globally (`boolean`) or for HOC by props (`(props) => boolean`)
|
|
110
|
+
- `logger` - custom logger function for integrating with your telemetry
|
|
111
|
+
|
|
112
|
+
### Typical presets
|
|
113
|
+
|
|
114
|
+
- **Page/widget profiling**: `{ componentName, groupByComponent: true, enabled: dev, reportAfterMs: 5000 }`
|
|
115
|
+
- **Instance-level profiling**: `{ componentName, enabled: (props) => ..., reportAfterMs: 2000-5000 }`
|
|
116
|
+
|
|
117
|
+
## Notes
|
|
118
|
+
|
|
119
|
+
- In React StrictMode (development), render/effect invocations can be doubled.
|
|
120
|
+
- This helper measures render-to-effect timing, not full browser paint time.
|
|
121
|
+
|
|
122
|
+
## Report Fields
|
|
123
|
+
|
|
124
|
+
Each console row includes these fields:
|
|
125
|
+
|
|
126
|
+
- `label` - logger label, usually `[RenderProfiler] <ComponentName>`
|
|
127
|
+
- `component` - component name used for profiling/grouping
|
|
128
|
+
- `renders` - total committed renders counted in this profile bucket
|
|
129
|
+
- `initialRenders` - number of first renders for mounted instances in this bucket
|
|
130
|
+
- `rerenders` - number of subsequent renders (`renders - initialRenders`)
|
|
131
|
+
- `totalMs` - sum of measured render durations in milliseconds
|
|
132
|
+
- `avgMs` - average render duration (`totalMs / renders`)
|
|
133
|
+
- `minMs` - fastest measured render duration in milliseconds
|
|
134
|
+
- `maxMs` - slowest measured render duration in milliseconds
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
type LogPayload = {
|
|
3
|
+
component: string;
|
|
4
|
+
renders: number;
|
|
5
|
+
initialRenders: number;
|
|
6
|
+
rerenders: number;
|
|
7
|
+
totalMs: number;
|
|
8
|
+
avgMs: number;
|
|
9
|
+
minMs: number;
|
|
10
|
+
maxMs: number;
|
|
11
|
+
};
|
|
12
|
+
export type RenderProfilerOptions = {
|
|
13
|
+
componentName?: string;
|
|
14
|
+
groupByComponent?: boolean;
|
|
15
|
+
reportAfterMs?: number;
|
|
16
|
+
logEachRender?: boolean;
|
|
17
|
+
enabled?: boolean;
|
|
18
|
+
logger?: (label: string, payload: LogPayload) => void;
|
|
19
|
+
};
|
|
20
|
+
export type RenderProfilerHOCOptions<P> = Omit<RenderProfilerOptions, 'enabled'> & {
|
|
21
|
+
enabled?: boolean | ((props: P) => boolean);
|
|
22
|
+
};
|
|
23
|
+
export declare const useRenderProfiler: (componentName: string, options?: RenderProfilerOptions) => void;
|
|
24
|
+
export declare const withRenderProfiler: <P extends object>(WrappedComponent: React.ComponentType<P>, options?: RenderProfilerHOCOptions<P>) => React.FC<P>;
|
|
25
|
+
export {};
|
|
26
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA4B,MAAM,OAAO,CAAC;AAEjD,KAAK,UAAU,GAAG;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,KAAK,IAAI,CAAC;CACvD,CAAC;AAEF,MAAM,MAAM,wBAAwB,CAAC,CAAC,IAAI,IAAI,CAAC,qBAAqB,EAAE,SAAS,CAAC,GAAG;IACjF,OAAO,CAAC,EAAE,OAAO,GAAG,CAAC,CAAC,KAAK,EAAE,CAAC,KAAK,OAAO,CAAC,CAAC;CAC7C,CAAC;AAyDF,eAAO,MAAM,iBAAiB,kBACb,MAAM,YACZ,qBAAqB,KAC7B,IAgEF,CAAC;AAEF,eAAO,MAAM,kBAAkB,oHAe9B,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.withRenderProfiler = exports.useRenderProfiler = void 0;
|
|
4
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
const react_1 = require("react");
|
|
6
|
+
const defaultLogger = (label, payload) => {
|
|
7
|
+
// Console table keeps output readable when multiple profiled components run.
|
|
8
|
+
// eslint-disable-next-line no-console
|
|
9
|
+
console.table([{ label, ...payload }]);
|
|
10
|
+
};
|
|
11
|
+
const groupedStatsStore = new Map();
|
|
12
|
+
const createEmptyStats = () => ({
|
|
13
|
+
renders: 0,
|
|
14
|
+
initialRenders: 0,
|
|
15
|
+
rerenders: 0,
|
|
16
|
+
totalMs: 0,
|
|
17
|
+
minMs: Number.POSITIVE_INFINITY,
|
|
18
|
+
maxMs: 0,
|
|
19
|
+
timerId: null
|
|
20
|
+
});
|
|
21
|
+
const scheduleReport = (componentName, stats, reportAfterMs, logger) => {
|
|
22
|
+
if (stats.timerId) {
|
|
23
|
+
clearTimeout(stats.timerId);
|
|
24
|
+
}
|
|
25
|
+
stats.timerId = setTimeout(() => {
|
|
26
|
+
const avg = stats.renders > 0 ? stats.totalMs / stats.renders : 0;
|
|
27
|
+
const payload = {
|
|
28
|
+
component: componentName,
|
|
29
|
+
renders: stats.renders,
|
|
30
|
+
initialRenders: stats.initialRenders,
|
|
31
|
+
rerenders: stats.rerenders,
|
|
32
|
+
totalMs: Number(stats.totalMs.toFixed(2)),
|
|
33
|
+
avgMs: Number(avg.toFixed(2)),
|
|
34
|
+
minMs: Number((Number.isFinite(stats.minMs) ? stats.minMs : 0).toFixed(2)),
|
|
35
|
+
maxMs: Number(stats.maxMs.toFixed(2))
|
|
36
|
+
};
|
|
37
|
+
logger(`[RenderProfiler] ${componentName}`, payload);
|
|
38
|
+
}, reportAfterMs);
|
|
39
|
+
};
|
|
40
|
+
const useRenderProfiler = (componentName, options = {}) => {
|
|
41
|
+
const { groupByComponent = false, reportAfterMs = 3000, logEachRender = false, enabled = true, logger = defaultLogger } = options;
|
|
42
|
+
const renderStartRef = (0, react_1.useRef)(0);
|
|
43
|
+
const instanceRenderCountRef = (0, react_1.useRef)(0);
|
|
44
|
+
const statsRef = (0, react_1.useRef)(createEmptyStats());
|
|
45
|
+
if (groupByComponent && !groupedStatsStore.has(componentName)) {
|
|
46
|
+
groupedStatsStore.set(componentName, createEmptyStats());
|
|
47
|
+
}
|
|
48
|
+
const activeStats = groupByComponent ? groupedStatsStore.get(componentName) : statsRef.current;
|
|
49
|
+
if (enabled) {
|
|
50
|
+
const now = performance.now();
|
|
51
|
+
renderStartRef.current = now;
|
|
52
|
+
activeStats.renders += 1;
|
|
53
|
+
instanceRenderCountRef.current += 1;
|
|
54
|
+
if (instanceRenderCountRef.current === 1) {
|
|
55
|
+
activeStats.initialRenders += 1;
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
activeStats.rerenders += 1;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
(0, react_1.useEffect)(() => {
|
|
62
|
+
if (!enabled) {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
const end = performance.now();
|
|
66
|
+
const renderDuration = end - renderStartRef.current;
|
|
67
|
+
const stats = activeStats;
|
|
68
|
+
stats.totalMs += renderDuration;
|
|
69
|
+
stats.minMs = Math.min(stats.minMs, renderDuration);
|
|
70
|
+
stats.maxMs = Math.max(stats.maxMs, renderDuration);
|
|
71
|
+
if (logEachRender) {
|
|
72
|
+
logger(`[RenderProfiler] ${componentName}#${stats.renders}`, {
|
|
73
|
+
component: componentName,
|
|
74
|
+
renders: stats.renders,
|
|
75
|
+
initialRenders: stats.initialRenders,
|
|
76
|
+
rerenders: stats.rerenders,
|
|
77
|
+
totalMs: Number(stats.totalMs.toFixed(2)),
|
|
78
|
+
avgMs: Number((stats.totalMs / stats.renders).toFixed(2)),
|
|
79
|
+
minMs: Number(stats.minMs.toFixed(2)),
|
|
80
|
+
maxMs: Number(stats.maxMs.toFixed(2))
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
scheduleReport(componentName, stats, reportAfterMs, logger);
|
|
84
|
+
return () => {
|
|
85
|
+
if (!groupByComponent && stats.timerId) {
|
|
86
|
+
clearTimeout(stats.timerId);
|
|
87
|
+
stats.timerId = null;
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
}, [activeStats, componentName, enabled, groupByComponent, logEachRender, logger, reportAfterMs]);
|
|
91
|
+
};
|
|
92
|
+
exports.useRenderProfiler = useRenderProfiler;
|
|
93
|
+
const withRenderProfiler = (WrappedComponent, options = {}) => {
|
|
94
|
+
const wrappedName = options.componentName || WrappedComponent.displayName || WrappedComponent.name || 'AnonymousComponent';
|
|
95
|
+
const ProfiledComponent = (props) => {
|
|
96
|
+
const { enabled = true, ...restOptions } = options;
|
|
97
|
+
const resolvedEnabled = typeof enabled === 'function' ? enabled(props) : enabled;
|
|
98
|
+
(0, exports.useRenderProfiler)(wrappedName, { ...restOptions, enabled: resolvedEnabled });
|
|
99
|
+
return (0, jsx_runtime_1.jsx)(WrappedComponent, { ...props });
|
|
100
|
+
};
|
|
101
|
+
ProfiledComponent.displayName = `withRenderProfiler(${wrappedName})`;
|
|
102
|
+
return ProfiledComponent;
|
|
103
|
+
};
|
|
104
|
+
exports.withRenderProfiler = withRenderProfiler;
|
|
105
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "react-render-profiler",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Lightweight React render and rerender profiler",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"types": "./dist/index.d.ts",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"build": "tsc",
|
|
9
|
+
"build:watch": "tsc -w",
|
|
10
|
+
"test": "jest",
|
|
11
|
+
"prepublishOnly": "npm run build",
|
|
12
|
+
"lint": "eslint --ext .ts --ext .tsx ."
|
|
13
|
+
},
|
|
14
|
+
"author": "Bohdan Surai",
|
|
15
|
+
"license": "MIT",
|
|
16
|
+
"repository": {
|
|
17
|
+
"type": "git",
|
|
18
|
+
"url": "git+https://github.com/bsurai/react-render-profiler.git"
|
|
19
|
+
},
|
|
20
|
+
"homepage": "https://github.com/bsurai/react-render-profiler#readme",
|
|
21
|
+
"bugs": {
|
|
22
|
+
"url": "https://github.com/bsurai/react-render-profiler/issues"
|
|
23
|
+
},
|
|
24
|
+
"files": [
|
|
25
|
+
"dist",
|
|
26
|
+
"README.md",
|
|
27
|
+
"LICENSE"
|
|
28
|
+
],
|
|
29
|
+
"keywords": [
|
|
30
|
+
"react",
|
|
31
|
+
"performance",
|
|
32
|
+
"profiler",
|
|
33
|
+
"render",
|
|
34
|
+
"rerender"
|
|
35
|
+
],
|
|
36
|
+
"peerDependencies": {
|
|
37
|
+
"react": ">=16.8.0"
|
|
38
|
+
},
|
|
39
|
+
"devDependencies": {
|
|
40
|
+
"@testing-library/jest-dom": "^6.9.1",
|
|
41
|
+
"@testing-library/react": "^16.3.2",
|
|
42
|
+
"@types/jest": "^30.0.0",
|
|
43
|
+
"@types/node": "^18.19.130",
|
|
44
|
+
"@types/react": "^19.2.2",
|
|
45
|
+
"jest": "^30.3.0",
|
|
46
|
+
"jest-environment-jsdom": "^30.3.0",
|
|
47
|
+
"react-dom": "^19.2.5",
|
|
48
|
+
"ts-jest": "^29.4.9",
|
|
49
|
+
"typescript": "4.9.5"
|
|
50
|
+
}
|
|
51
|
+
}
|