[Deep Dive into the Observer API] 5. PerformanceObserver
[Deep Dive into the Observer API] 5. PerformanceObserver
PerformanceObserver is an observer API for observing performance events. It is related to the Performance tab of the developer tools that appears when you press F12.
TYPESCRIPT
const po = new PerformanceObserver(callback); po.observer(options);
Because it is an observer related to page performance, unlike other observers, there is no process of registering a tag.
You can pass options when registering the observer to fine-tune the detailed settings. It has the PerformanceObserverInit type.
Specifies the performance element the observer will observe. Each element is as follows.
- navigation - Performance metrics related to page load. Can collect timing information from the initial page load, and more.
- resource - Performance metrics related to resources loaded on the page. Targets include images, js, css, and so on.
- mark - Arbitrary timing information specified by the developer.
- measure - Time measurement between two specified marks.
- paint - Performance metrics related to page rendering and painting. Includes First Paint (FP), First Meaningful Paint (FMP), and so on.
- longtask - Identifies long-running processes taking 50ms or more.
- element - Performance metrics related to DOM element rendering.
- frame - Performance metrics related to animation frames. Provides information related to animation and scroll performance analysis.
- event - Performance metrics related to the occurrence of events.
- first-input - Performance metrics related to the user's action.
- largest-contentful-paint - Performance metrics for the rendering of large-content elements.
- layout-shift - Performance metrics for element movement on the page.
type cannot be used together with entryTypes, described below.
Specifies the performance elements the observer will observe as an array. Useful when measuring multiple performance metrics.
An option specifying whether to include existing performance metrics. It is declared as false by default.
Through the callback method, you can handle performance-related metrics. It has the PerformanceObserverCallback type.
Returns the performance metrics object PerformanceObserverEntryList. You can extract the desired list via the getEntries, getEntriesByName, and getEntriesByType methods.
Each element is a performance object corresponding to the element specified in type or entryTypes. It holds a different object depending on the performance element being measured.
Returns the PerformanceObserver object. Through this, PerformanceObserver can also be handled in a chained manner within the callback method.
Let's use PerformanceObserver conveniently through a custom hook.
TYPESCRIPT
export function usePerformanceObserver(): void { // }
Define the usePerformanceObserver method as above.
To use useMutationObserver, the following two elements are needed.
- A callback method
- Options
Unlike the observers we've covered so far, no DOM is needed.
TYPESCRIPT
import { useEffect } from "react"; export type UsePerformanceObserverCallback = (entry: PerformanceEntry) => void; /** * Hook method for applying PerformanceObserver * * @param {UsePerformanceObserverCallback} callback: Callback method * @param {PerformanceObserverInit} options: Options */ export function usePerformanceObserver( callback: UsePerformanceObserverCallback, options?: PerformanceObserverInit ): void { useEffect(() => { const po = new PerformanceObserver((entries) => { entries.getEntries().forEach(callback); }); }, [callback, options]); }
Initialize PerformanceObserver and assign it to the po variable.
You can register a tag through the po.observe() method.
TYPESCRIPT
import { useEffect } from "react"; export type UsePerformanceObserverCallback = (entry: PerformanceEntry) => void; /** * Hook method for applying PerformanceObserver * * @param {UsePerformanceObserverCallback} callback: Callback method * @param {PerformanceObserverInit} options: Options */ export function usePerformanceObserver( callback: UsePerformanceObserverCallback, options?: PerformanceObserverInit ): void { useEffect(() => { const po = new PerformanceObserver((entries) => { entries.getEntries().forEach(callback); }); po.observe(options); }, [callback, options]); }
Finally, add cleanup code so that PerformanceObserver registrations don't stack up every time the component re-renders.
PerformanceObserver can be removed via the po.disconnect() method.
TYPESCRIPT
import { useEffect } from "react"; export type UsePerformanceObserverCallback = (entry: PerformanceEntry) => void; /** * Hook method for applying PerformanceObserver * * @param {UsePerformanceObserverCallback} callback: Callback method * @param {PerformanceObserverInit} options: Options */ export function usePerformanceObserver( callback: UsePerformanceObserverCallback, options?: PerformanceObserverInit ): void { useEffect(() => { const po = new PerformanceObserver((entries) => { entries.getEntries().forEach(callback); }); po.observe(options); return () => { po.disconnect(); }; }, [callback, options]); }
The full code is as above.
A simple example has been implemented in CodeSandbox.
🖼️ Lighthouse performance measurement
Using PerformanceObserver, you can measure a page's performance metrics. If configured appropriately, you could implement something similar to a web performance measurement service like Lighthouse.
However, the reality is that there are already many open-source or commercial tools that provide similar or better functionality. Also, unlike the three observers covered before, this one is much less versatile for feature development, which means there isn't a lot of related information available — a downside.
The last observer we'll cover is ReportingObserver.