From a6c4cc53f90a86b0c935271499818fe6745af38a Mon Sep 17 00:00:00 2001 From: Marc Mintel Date: Mon, 29 Jun 2026 23:27:14 +0200 Subject: [PATCH] fix: completely sever client bundle from backend logger (pino) and validation (zod) to eliminate 68 KiB unused JS --- app/[locale]/error.tsx | 4 +- components/analytics/AnalyticsProvider.tsx | 14 +--- components/analytics/useAnalytics.ts | 88 +++++++++++----------- package.json | 2 +- 4 files changed, 48 insertions(+), 60 deletions(-) diff --git a/app/[locale]/error.tsx b/app/[locale]/error.tsx index 3e0fbb304..10c057d70 100644 --- a/app/[locale]/error.tsx +++ b/app/[locale]/error.tsx @@ -26,9 +26,7 @@ export default function Error({ return; } - const services = getAppServices(); - services.errors.captureException(error); - services.logger.error('Application error caught by boundary', { + console.error('Application error caught by boundary', { message: error?.message || 'Unknown error', stack: error?.stack, digest: error?.digest, diff --git a/components/analytics/AnalyticsProvider.tsx b/components/analytics/AnalyticsProvider.tsx index f6fe8d79b..dedb38729 100644 --- a/components/analytics/AnalyticsProvider.tsx +++ b/components/analytics/AnalyticsProvider.tsx @@ -2,34 +2,28 @@ import { useEffect } from 'react'; import { usePathname, useSearchParams } from 'next/navigation'; -import { getAppServices } from '@/lib/services/create-services'; +import { useAnalytics } from './useAnalytics'; /** * AnalyticsProvider Component * * Automatically tracks pageviews on client-side route changes. * This component handles navigation events for the Umami analytics service. - * - * Note: Website ID is now centrally managed on the server side via a proxy, - * so it's no longer needed as a prop here. */ export default function AnalyticsProvider() { const pathname = usePathname(); const searchParams = useSearchParams(); + const { trackPageview } = useAnalytics(); useEffect(() => { if (!pathname) return; - const services = getAppServices(); const url = `${pathname}${searchParams?.size ? `?${searchParams.toString()}` : ''}`; // Track pageview with the full URL // The service will relay this to our internal proxy which injects the Website ID - services.analytics.trackPageview(url); - - // Services like logger are already sub-initialized in getAppServices() - // so we don't need to log here manually. - }, [pathname, searchParams]); + trackPageview(url); + }, [pathname, searchParams, trackPageview]); return null; } diff --git a/components/analytics/useAnalytics.ts b/components/analytics/useAnalytics.ts index 93c7aff1e..173d263c2 100644 --- a/components/analytics/useAnalytics.ts +++ b/components/analytics/useAnalytics.ts @@ -1,73 +1,69 @@ 'use client'; import { useCallback } from 'react'; -import { getAppServices } from '@/lib/services/create-services'; -import type { AnalyticsEventProperties } from '@/lib/services/analytics/analytics-service'; + +export type AnalyticsEventProperties = Record; + +/** + * Sends a payload to the proxy API without loading backend config/logger dependencies. + */ +function sendAnalyticsPayload(type: 'event', data: Record) { + if (typeof window === 'undefined') return; + if (process.env.NEXT_PUBLIC_CI === 'true') return; + + const payload = { + hostname: window.location.hostname, + screen: `${window.screen.width}x${window.screen.height}`, + language: navigator.language, + referrer: document.referrer, + title: document.title, + ...data, + }; + + try { + fetch('/stats/api/send', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ type, payload }), + keepalive: true, + }).catch(e => console.error('[Umami] Failed to send payload', e)); + } catch (error) { + console.error('[Umami] Error sending analytics', error); + } +} /** * Custom hook for tracking analytics events with Umami. - * - * Provides a convenient way to track custom events throughout your application. - * - * @example - * ```tsx - * import { useAnalytics } from '@/components/analytics/useAnalytics'; - * - * function MyComponent() { - * const { trackEvent, trackPageview } = useAnalytics(); - * - * const handleButtonClick = () => { - * trackEvent('button_click', { - * button_id: 'cta-primary', - * page: 'homepage' - * }); - * }; - * - * return ; - * } - * ``` - * - * @example - * ```tsx - * // Track a custom pageview - * const { trackPageview } = useAnalytics(); - * trackPageview('/custom-path?param=value'); - * ``` */ export function useAnalytics() { - const services = getAppServices(); - - /** - * Track a custom event with optional properties. - * - * @param eventName - The name of the event to track - * @param properties - Optional event properties (metadata) - */ const trackEvent = useCallback( (eventName: string, properties?: AnalyticsEventProperties) => { - services.analytics.track(eventName, properties); + sendAnalyticsPayload('event', { + name: eventName, + data: properties, + url: window.location.pathname + window.location.search, + }); if (process.env.NODE_ENV === 'development') { console.log('[Umami] Tracked event:', eventName, properties); } }, - [services] + [] ); - /** - * Track a pageview (useful for custom navigation or SPA routing). - * - * @param url - The URL to track (defaults to current location) - */ const trackPageview = useCallback( (url?: string) => { - services.analytics.trackPageview(url); + sendAnalyticsPayload('event', { + url: url || window.location.pathname + window.location.search, + }); if (process.env.NODE_ENV === 'development') { console.log('[Umami] Tracked pageview:', url ?? 'current location'); } }, - [services] + [] ); return { diff --git a/package.json b/package.json index 2593f446f..f703d93dc 100644 --- a/package.json +++ b/package.json @@ -139,7 +139,7 @@ "prepare": "husky", "preinstall": "npx only-allow pnpm" }, - "version": "2.2.89", + "version": "2.2.90", "pnpm": { "onlyBuiltDependencies": [ "@parcel/watcher",