From c2ef5e4924a990f0ef9e95203326ea40f2266b67 Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Tue, 3 Dec 2024 10:12:07 +0000 Subject: [PATCH] feat(nuxt): print nuxt hook timings in browser devtools (#29922) --- .../plugins/browser-devtools-timing.client.ts | 42 +++++++++++++++++++ packages/nuxt/src/core/nuxt.ts | 6 +++ packages/schema/src/config/experimental.ts | 9 ++++ 3 files changed, 57 insertions(+) create mode 100644 packages/nuxt/src/app/plugins/browser-devtools-timing.client.ts diff --git a/packages/nuxt/src/app/plugins/browser-devtools-timing.client.ts b/packages/nuxt/src/app/plugins/browser-devtools-timing.client.ts new file mode 100644 index 0000000000..c740238880 --- /dev/null +++ b/packages/nuxt/src/app/plugins/browser-devtools-timing.client.ts @@ -0,0 +1,42 @@ +import { defineNuxtPlugin } from '../nuxt' + +export default defineNuxtPlugin({ + name: 'nuxt:browser-devtools-timing', + enforce: 'pre', + setup (nuxtApp) { + nuxtApp.hooks.beforeEach((event) => { + // @ts-expect-error __startTime is not a public API + event.__startTime = performance.now() + }) + + // After each + nuxtApp.hooks.afterEach((event) => { + performance.measure(event.name, { + // @ts-expect-error __startTime is not a public API + start: event.__startTime, + detail: { + devtools: { + dataType: 'track-entry', + track: 'nuxt', + color: 'tertiary-dark', + } satisfies ExtensionTrackEntryPayload, + }, + }) + }) + }, +}) + +type DevToolsColor = + 'primary' | 'primary-light' | 'primary-dark' | + 'secondary' | 'secondary-light' | 'secondary-dark' | + 'tertiary' | 'tertiary-light' | 'tertiary-dark' | + 'error' + +interface ExtensionTrackEntryPayload { + dataType?: 'track-entry' // Defaults to "track-entry" + color?: DevToolsColor // Defaults to "primary" + track: string // Required: Name of the custom track + trackGroup?: string // Optional: Group for organizing tracks + properties?: [string, string][] // Key-value pairs for detailed view + tooltipText?: string // Short description for tooltip +} diff --git a/packages/nuxt/src/core/nuxt.ts b/packages/nuxt/src/core/nuxt.ts index 52b286c31a..ec4d6f19fc 100644 --- a/packages/nuxt/src/core/nuxt.ts +++ b/packages/nuxt/src/core/nuxt.ts @@ -548,6 +548,12 @@ async function initNuxt (nuxt: Nuxt) { addPlugin(resolve(nuxt.options.appDir, 'plugins/debug')) } + // Add experimental Chrome devtools timings support + // https://developer.chrome.com/docs/devtools/performance/extension + if (nuxt.options.experimental.browserDevtoolsTiming) { + addPlugin(resolve(nuxt.options.appDir, 'plugins/browser-devtools-timing.client')) + } + for (const [key, options] of modulesToInstall) { await installModule(key, options) } diff --git a/packages/schema/src/config/experimental.ts b/packages/schema/src/config/experimental.ts index 71f465304a..c5fef8816e 100644 --- a/packages/schema/src/config/experimental.ts +++ b/packages/schema/src/config/experimental.ts @@ -572,5 +572,14 @@ export default defineUntypedSchema({ return val ?? ((await get('future') as Record).compatibilityVersion === 4) }, }, + + /** + * Enable timings for Nuxt application hooks in the performance panel of Chromium-based browsers. + * + * @see [the Chrome DevTools extensibility API](https://developer.chrome.com/docs/devtools/performance/extension#tracks) + */ + browserDevtoolsTiming: { + $resolve: async (val, get) => val ?? await get('dev'), + }, }, })