diff --git a/packages/core/index.ts b/packages/core/index.ts
index c9c541ddf08..66e21a82391 100644
--- a/packages/core/index.ts
+++ b/packages/core/index.ts
@@ -78,6 +78,7 @@ export * from './useOffsetPagination'
export * from './useOnline'
export * from './usePageLeave'
export * from './useParallax'
+export * from './usePerformanceObserver'
export * from './usePermission'
export * from './usePointer'
export * from './usePointerLock'
diff --git a/packages/core/usePerformanceObserver/demo.vue b/packages/core/usePerformanceObserver/demo.vue
new file mode 100644
index 00000000000..2491872face
--- /dev/null
+++ b/packages/core/usePerformanceObserver/demo.vue
@@ -0,0 +1,20 @@
+
+
+
+
+
+ {{ entrys }}
+
diff --git a/packages/core/usePerformanceObserver/index.md b/packages/core/usePerformanceObserver/index.md
new file mode 100644
index 00000000000..7956f653373
--- /dev/null
+++ b/packages/core/usePerformanceObserver/index.md
@@ -0,0 +1,20 @@
+---
+category: Browser
+---
+
+# usePerformanceObserver
+
+Observe performance metrics.
+
+## Usage
+
+```ts
+import { usePerformanceObserver } from '@vueuse/core'
+
+const entrys = ref([])
+usePerformanceObserver({
+ entryTypes: ['paint'],
+}, (list) => {
+ entrys.value = list.getEntries()
+})
+```
diff --git a/packages/core/usePerformanceObserver/index.ts b/packages/core/usePerformanceObserver/index.ts
new file mode 100644
index 00000000000..9e8bd89a5ba
--- /dev/null
+++ b/packages/core/usePerformanceObserver/index.ts
@@ -0,0 +1,54 @@
+import { tryOnScopeDispose } from '@vueuse/shared'
+import { useSupported } from '../useSupported'
+import type { ConfigurableWindow } from '../_configurable'
+import { defaultWindow } from '../_configurable'
+
+export type UsePerformanceObserverOptions = PerformanceObserverInit & ConfigurableWindow & {
+ /**
+ * Start the observer immediate.
+ *
+ * @default true
+ */
+ immediate?: boolean
+}
+
+/**
+ * Observe performance metrics.
+ *
+ * @see https://vueuse.org/usePerformanceObserver
+ * @param options
+ */
+export function usePerformanceObserver(options: UsePerformanceObserverOptions, callback: PerformanceObserverCallback) {
+ const {
+ window = defaultWindow,
+ immediate = true,
+ ...performanceOptions
+ } = options
+
+ const isSupported = useSupported(() => window && 'PerformanceObserver' in window)
+
+ let observer: PerformanceObserver | undefined
+
+ const stop = () => {
+ observer?.disconnect()
+ }
+
+ const start = () => {
+ if (isSupported.value) {
+ stop()
+ observer = new PerformanceObserver(callback)
+ observer.observe(performanceOptions)
+ }
+ }
+
+ tryOnScopeDispose(stop)
+
+ if (immediate)
+ start()
+
+ return {
+ isSupported,
+ start,
+ stop,
+ }
+}