Skip to content

Commit

Permalink
Ensure no race conditions
Browse files Browse the repository at this point in the history
  • Loading branch information
bttf committed Apr 22, 2024
1 parent d838cea commit 414a268
Show file tree
Hide file tree
Showing 12 changed files with 51 additions and 31 deletions.
9 changes: 7 additions & 2 deletions next-js/src/app/client/page.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
"use client";
import { useEffect } from "react";
import { GrowthBookProvider } from "@growthbook/growthbook-react";
import { useEffect } from "react";
import Cookies from "js-cookie";
import gb from "@/lib/growthbook/client";
import { createGB } from "@/lib/growthbook";
import ClientComponent from "./ClientComponent";

const gb = createGB({
// client-side feature
subscribeToChanges: true,
});

export default function ClientPage() {
useEffect(() => {
const load = async () => {
Expand Down
7 changes: 6 additions & 1 deletion next-js/src/app/server/combo/ClientComponent.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
"use client";
import Cookies from "js-cookie";
import gb from "@/lib/growthbook/client";
import { createGB } from "@/lib/growthbook";
import { FeatureDefinition } from "@growthbook/growthbook";

const gb = createGB({
// client-side feature
subscribeToChanges: true,
});

export default function ClientComponent({
gbFeatures,
}: {
Expand Down
5 changes: 4 additions & 1 deletion next-js/src/app/server/combo/page.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import gb from "@/lib/growthbook/server";
import { createGB } from "@/lib/growthbook";
import { cookies } from "next/headers";
import ClientComponent from "./ClientComponent";

export default async function ServerDynamic() {
// create instance per request, server-side
const gb = createGB();

await gb.loadFeatures({ timeout: 1000 });

const cookieStore = cookies();
Expand Down
7 changes: 6 additions & 1 deletion next-js/src/app/server/dynamic/ClientComponent.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
"use client";
import { useEffect, useState } from "react";
import Cookies from "js-cookie";
import gb from "@/lib/growthbook/client";
import { createGB } from "@/lib/growthbook";

const gb = createGB({
// client-side feature
subscribeToChanges: true,
});

export default function ClientPage() {
const [isLoading, setIsLoading] = useState(false);
Expand Down
5 changes: 4 additions & 1 deletion next-js/src/app/server/dynamic/page.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import gb from "@/lib/growthbook/server";
import { createGB } from "@/lib/growthbook";
import { cookies } from "next/headers";

export default async function ServerDynamic() {
// create instance per request, server-side
const gb = createGB();

await gb.loadFeatures({ timeout: 1000 });

const cookieStore = cookies();
Expand Down
3 changes: 2 additions & 1 deletion next-js/src/app/server/static/page.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import gb from "@/lib/growthbook/server";
import { createGB } from "@/lib/growthbook";
export default async function ServerStatic() {
const gb = createGB();
await gb.loadFeatures({ timeout: 1000 });
gb.setAttributes({
country: "US",
Expand Down
5 changes: 4 additions & 1 deletion next-js/src/app/server/streaming/AsyncComponent.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import gb from "@/lib/growthbook/server";
import { createGB } from "@/lib/growthbook";
import { cookies } from "next/headers";

export default async function AsyncComponent() {
// create instance per request, server-side
const gb = createGB();

await gb.loadFeatures({ timeout: 1000 });

const cookieStore = cookies();
Expand Down
4 changes: 2 additions & 2 deletions next-js/src/app/server/streaming/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ const Loading = () => {
};
export default async function ServerStreaming() {
return (
<div>
<>
<div className="text-4xl my-4">Server Component - Streaming Render</div>
<Suspense fallback={<Loading />}>
<AsyncComponent />
</Suspense>
</div>
</>
);
}
12 changes: 12 additions & 0 deletions next-js/src/lib/growthbook.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { GrowthBook, Context } from "@growthbook/growthbook";

// It's important to create a new instance per request when server-side to prevent
// race condtions from occurring between different user requests.
export const createGB = (args: Partial<Context> = {}) => {
return new GrowthBook({
apiHost: process.env.NEXT_PUBLIC_GROWTHBOOK_API_HOST,
clientKey: process.env.NEXT_PUBLIC_GROWTHBOOK_CLIENT_KEY,
decryptionKey: process.env.NEXT_PUBLIC_GROWTHBOOK_DECRYPTION_KEY,
...args,
});
};
11 changes: 0 additions & 11 deletions next-js/src/lib/growthbook/client.ts

This file was deleted.

9 changes: 0 additions & 9 deletions next-js/src/lib/growthbook/server.ts

This file was deleted.

5 changes: 4 additions & 1 deletion next-js/src/middleware.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";
import { cookies } from "next/headers";
import gb from "@/lib/growthbook/server";
import { createGB } from "@/lib/growthbook";

export async function middleware(request: NextRequest) {
// create instance per request, server-side
const gb = createGB();

await gb.loadFeatures({ timeout: 1000 });

const cookieStore = cookies();
Expand Down

0 comments on commit 414a268

Please sign in to comment.