Skip to content

Commit 4845d87

Browse files
authored
refactor: stream the analytics provider (#2637)
1 parent 19077cd commit 4845d87

File tree

3 files changed

+42
-18
lines changed

3 files changed

+42
-18
lines changed

core/app/[locale]/layout.tsx

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,15 @@ import { cache, PropsWithChildren } from 'react';
1010

1111
import '../../globals.css';
1212

13+
import { Streamable } from '@/vibes/soul/lib/streamable';
1314
import { fonts } from '~/app/fonts';
1415
import { CookieNotifications } from '~/app/notifications';
1516
import { Providers } from '~/app/providers';
1617
import { client } from '~/client';
1718
import { graphql } from '~/client/graphql';
1819
import { revalidate } from '~/client/revalidate-target';
1920
import { WebAnalyticsFragment } from '~/components/analytics/fragment';
20-
import { AnalyticsProvider } from '~/components/analytics/provider';
21+
import { StreamableAnalyticsProvider } from '~/components/analytics/streamable-provider';
2122
import { ContainerQueryPolyfill } from '~/components/polyfills/container-query';
2223
import { ScriptManagerScripts, ScriptsFragment } from '~/components/scripts';
2324
import { routing } from '~/i18n/routing';
@@ -100,7 +101,7 @@ interface Props extends PropsWithChildren {
100101
export default async function RootLayout({ params, children }: Props) {
101102
const { locale } = await params;
102103

103-
const { data } = await fetchRootLayoutMetadata();
104+
const rootData = await fetchRootLayoutMetadata();
104105
const toastNotificationCookieData = await getToastNotification();
105106

106107
if (!routing.locales.includes(locale)) {
@@ -111,30 +112,41 @@ export default async function RootLayout({ params, children }: Props) {
111112
// https://next-intl-docs.vercel.app/docs/getting-started/app-router#add-setRequestLocale-to-all-layouts-and-pages
112113
setRequestLocale(locale);
113114

115+
const streamableAnalyticsData = Streamable.from(async () => {
116+
const { data } = await fetchRootLayoutMetadata();
117+
118+
return {
119+
channelId: data.channel.entityId,
120+
settings: data.site.settings,
121+
};
122+
});
123+
114124
return (
115125
<html className={clsx(fonts.map((f) => f.variable))} lang={locale}>
116126
<head>
117127
<ScriptManagerScripts
118-
scripts={data.site.content.headerScripts}
128+
scripts={rootData.data.site.content.headerScripts}
119129
strategy="afterInteractive"
120130
/>
121131
</head>
122132
<body className="flex min-h-screen flex-col">
123133
<NextIntlClientProvider>
124134
<NuqsAdapter>
125-
<AnalyticsProvider channelId={data.channel.entityId} settings={data.site.settings}>
126-
<Providers>
127-
{toastNotificationCookieData && (
128-
<CookieNotifications {...toastNotificationCookieData} />
129-
)}
130-
{children}
131-
</Providers>
132-
</AnalyticsProvider>
135+
<StreamableAnalyticsProvider data={streamableAnalyticsData} />
136+
<Providers>
137+
{toastNotificationCookieData && (
138+
<CookieNotifications {...toastNotificationCookieData} />
139+
)}
140+
{children}
141+
</Providers>
133142
</NuqsAdapter>
134143
</NextIntlClientProvider>
135144
<VercelComponents />
136145
<ContainerQueryPolyfill />
137-
<ScriptManagerScripts scripts={data.site.content.footerScripts} strategy="lazyOnload" />
146+
<ScriptManagerScripts
147+
scripts={rootData.data.site.content.footerScripts}
148+
strategy="lazyOnload"
149+
/>
138150
</body>
139151
</html>
140152
);

core/components/analytics/provider.tsx renamed to core/components/analytics/streamable-provider.tsx

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
'use client';
22

3-
import { PropsWithChildren } from 'react';
3+
import { Suspense } from 'react';
44

5+
import { Streamable, useStreamable } from '@/vibes/soul/lib/streamable';
56
import { FragmentOf } from '~/client/graphql';
67
import { Analytics } from '~/lib/analytics';
78
import { GoogleAnalyticsProvider } from '~/lib/analytics/providers/google-analytics';
@@ -36,8 +37,17 @@ const getAnalytics = (
3637
return null;
3738
};
3839

39-
export function AnalyticsProvider({ children, settings, channelId }: PropsWithChildren<Props>) {
40+
export function StreamableAnalyticsProvider({ data }: { data: Streamable<Props> }) {
41+
return (
42+
<Suspense fallback={null}>
43+
<StreamableAnalyticsProviderResolved data={data} />
44+
</Suspense>
45+
);
46+
}
47+
48+
function StreamableAnalyticsProviderResolved({ data }: { data: Streamable<Props> }) {
49+
const { channelId, settings } = useStreamable(data);
4050
const analytics = getAnalytics(channelId, settings);
4151

42-
return <AnalyticsProviderLib analytics={analytics ?? null}>{children}</AnalyticsProviderLib>;
52+
return <AnalyticsProviderLib analytics={analytics ?? null} />;
4353
}

core/lib/analytics/react/index.tsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,19 @@
11
'use client';
22

3-
import { createContext, useContext, useEffect } from 'react';
3+
import { createContext, PropsWithChildren, useContext, useEffect } from 'react';
44

55
import { type Analytics } from '../types';
66

77
const AnalyticsContext = createContext<Analytics | null>(null);
88

99
interface AnalyticsProviderProps {
1010
analytics: Analytics | null;
11-
children: React.ReactNode;
1211
}
1312

14-
export const AnalyticsProvider = ({ children, analytics }: AnalyticsProviderProps) => {
13+
export const AnalyticsProvider = ({
14+
children,
15+
analytics,
16+
}: PropsWithChildren<AnalyticsProviderProps>) => {
1517
useEffect(() => {
1618
analytics?.initialize();
1719
}, [analytics]);

0 commit comments

Comments
 (0)