Created
November 25, 2024 08:21
-
-
Save manabuyasuda/f05d333c191ad936716318ed28a34263 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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