Skip to content

Instantly share code, notes, and snippets.

@manabuyasuda
Created November 25, 2024 08:21
Show Gist options
  • Save manabuyasuda/f05d333c191ad936716318ed28a34263 to your computer and use it in GitHub Desktop.
Save manabuyasuda/f05d333c191ad936716318ed28a34263 to your computer and use it in GitHub Desktop.
import { useEffect, useRef } from 'react';
type RenderTimeOptions = {
/**
* 計測完了のトリガーとなる条件。
* コンポーネント側でレンダリングを完了した状態を持たせて、それを設定する想定。
*/
completeTrigger: boolean;
/**
* 計測結果を区別するための識別子。
*/
identifier?: string;
/**
* 計測を有効にするかどうか。
*/
enabled?: boolean;
};
/**
* クライアントコンポーネントの表示完了時間を計測するカスタムフックです。
* @param options - 計測オプション
* @param options.completeTrigger - 計測完了のトリガーとなる条件(必須)
* @param options.identifier - 計測結果を区別するための識別子
* @param options.enabled - 計測を有効にするかどうか
* @returns void - 計測結果のログ(ミリ秒)
* @example
* useClientRenderingTime({
* completeTrigger: isReady,
* identifier: 'Chart:',
* enabled: product.productName === '商品名',
* });
* // 特定の商品だけ計測する場合:Chart: client rendering time: 12.700000047683716ms
* useClientRenderingTime({
* completeTrigger: isReady,
* identifier: `Chart(${product.name}):`,
* });
* // 全ての商品で計測する場合:Chart(商品名): client rendering time: 12.700000047683716ms
*/
export const useClientRenderingTime = (options: RenderTimeOptions) => {
const startTimeRef = useRef<number>(0);
const effectStartTimeRef = useRef<number>(0);
// コンポーネントの関数実行時(レンダリング開始時)に計測を開始する
if (options?.enabled !== false && startTimeRef.current === 0) {
startTimeRef.current = performance.now();
console.log(`${options.identifier} 計測開始`);
}
// useEffect開始時にも計測を開始する
useEffect(() => {
if (options?.enabled === false) return;
effectStartTimeRef.current = performance.now();
console.log(`${options.identifier} useEffect開始`);
}, []);
// 計測完了の処理
useEffect(() => {
// 計測を無効にしている場合は何もしない
if (options?.enabled === false) return;
// 計測完了のトリガーがまだ発生していない場合は何もしない
if (!options.completeTrigger) return;
const endTime = performance.now();
const initialDuration = effectStartTimeRef.current - startTimeRef.current;
const effectDuration = endTime - effectStartTimeRef.current;
const totalDuration = endTime - startTimeRef.current;
console.log(`${options.identifier} 計測完了`);
console.table({
initialRender: {
説明: '初期レンダリング〜useEffect開始',
結果: `${initialDuration}ms`,
},
effectDuration: {
説明: 'useEffect開始〜計測完了',
結果: `${effectDuration}ms`,
},
totalDuration: {
説明: '初期レンダリング〜計測完了',
結果: `${totalDuration}ms`,
},
});
}, [options.identifier, options.enabled, options.completeTrigger]);
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment