Skip to content

Commit

Permalink
perf: add static param generation + prefetch (#241)
Browse files Browse the repository at this point in the history
  • Loading branch information
alexgoff committed Aug 1, 2024
1 parent f72e800 commit a0616ce
Show file tree
Hide file tree
Showing 16 changed files with 197 additions and 49 deletions.
57 changes: 51 additions & 6 deletions app/[locale]/[investigation]/[page]/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { PropsWithChildren, ReactNode } from "react";
import { RootLayoutParams } from "../../layout";
import { FunctionComponent, PropsWithChildren, ReactNode } from "react";
import { RootParams } from "../../layout";
import { InvestigationParams } from "../layout";
import { graphql } from "@/gql/public-schema";
import { queryAPI } from "@/lib/fetch";
Expand All @@ -20,7 +20,8 @@ export interface InvestigationPageParams {
}

export interface InvestigationPageProps {
params: RootLayoutParams & InvestigationParams & InvestigationPageParams;
params: RootParams & InvestigationParams & InvestigationPageParams;
searchParams: Record<string, string | Array<string> | undefined>;
reference: ReactNode;
}

Expand All @@ -33,9 +34,53 @@ const Query = graphql(`
}
`);

const InvestigationPageLayout: (
props: PropsWithChildren<InvestigationPageProps>
) => Promise<JSX.Element> = async ({
export const generateStaticParams = async ({
params: { locale, investigation },
}: InvestigationPageProps) => {
const site = getSite(locale);

const InvestigationParamsQuery = graphql(`
query InvestigationPageParams($site: [String], $slug: [String]) {
entry(site: $site, slug: $slug) {
children {
... on investigations_default_Entry {
slug
}
... on investigations_investigationSectionBreakChild_Entry {
slug
}
}
}
}
`);

const { data } = await queryAPI({
query: InvestigationParamsQuery,
variables: {
site: [site],
slug: [investigation],
},
});

return data?.entry?.children?.map((entry) => {
if (
entry?.__typename === "investigations_default_Entry" ||
entry?.__typename ===
"investigations_investigationSectionBreakChild_Entry"
) {
const { slug } = entry;

return { page: slug };
}
});
};

// show 404 for any investigation not pre-defined
export const dynamicParams = false;

const InvestigationPageLayout: FunctionComponent<
PropsWithChildren<InvestigationPageProps>
> = async ({
children,
reference,
params: { locale, investigation, page },
Expand Down
6 changes: 2 additions & 4 deletions app/[locale]/[investigation]/[page]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { Metadata } from "next";
import { graphql } from "@/gql/public-schema";
import { draftMode } from 'next/headers';
import { draftMode } from "next/headers";
import { notFound } from "next/navigation";
import {
getAuthCookies,
Expand Down Expand Up @@ -54,9 +54,7 @@ export async function generateMetadata({
return title ? { title, twitter: { title } } : {};
}

const InvestigationPage: (
props: InvestigationPageProps
) => Promise<JSX.Element> = async ({
const InvestigationPage: FunctionComponent<InvestigationPageProps> = async ({
params: { locale, investigation, page },
searchParams,
}) => {
Expand Down
52 changes: 41 additions & 11 deletions app/[locale]/[investigation]/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Metadata } from "next";
import { RootLayoutParams } from "../layout";
import { PropsWithChildren } from "react";
import { RootParams } from "../layout";
import { FunctionComponent, PropsWithChildren } from "react";
import { queryAPI } from "@/lib/fetch";
import { graphql } from "@/gql/public-schema";
import StudentStoredAnswers from "@/components/student-schema/StoredAnswersWrapper";
Expand All @@ -18,8 +18,9 @@ export interface InvestigationParams {
investigation: string;
}

export interface InvestigationLandingProps {
params: RootLayoutParams & InvestigationParams;
export interface InvestigationProps {
params: RootParams & InvestigationParams;
searchParams: Record<string, string | Array<string> | undefined>;
}

const InvestigationMetadataQuery = graphql(`
Expand All @@ -34,7 +35,7 @@ const InvestigationMetadataQuery = graphql(`

export async function generateMetadata({
params: { investigation, locale },
}: InvestigationLandingProps): Promise<Metadata> {
}: InvestigationProps): Promise<Metadata> {
const site = getSite(locale);

const { data } = await queryAPI({
Expand All @@ -50,6 +51,38 @@ export async function generateMetadata({
return { title, twitter: { title } };
}

export const generateStaticParams = async ({
params: { locale },
}: InvestigationProps) => {
const site = getSite(locale);

const InvestigationParamsQuery = graphql(`
query InvestigationParams($site: [String]) {
investigationsEntries(site: $site, level: 1) {
... on investigations_investigationParent_Entry {
slug
}
}
}
`);

const { data } = await queryAPI({
query: InvestigationParamsQuery,
variables: {
site: [site],
},
});

return data?.investigationsEntries?.map((entry) => {
if (entry?.__typename === "investigations_investigationParent_Entry") {
return { investigation: entry.slug };
}
});
};

// show 404 for any investigation not pre-defined
export const dynamicParams = false;

const InvestigationIdQuery = graphql(`
query InvestigationId($site: [String], $uri: [String]) {
entry(site: $site, uri: $uri) {
Expand Down Expand Up @@ -111,12 +144,9 @@ const InvestigationIdQuery = graphql(`
}
`);

const InvestigationLandingLayout: (
props: PropsWithChildren<InvestigationLandingProps>
) => Promise<JSX.Element> = async ({
children,
params: { locale, investigation },
}) => {
const InvestigationLandingLayout: FunctionComponent<
PropsWithChildren<InvestigationProps>
> = async ({ children, params: { locale, investigation } }) => {
const site = getSite(locale);

const { data } = await queryAPI({
Expand Down
7 changes: 3 additions & 4 deletions app/[locale]/[investigation]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import { notFound } from "next/navigation";
import { graphql } from "@/gql/public-schema";
import { draftMode } from "next/headers";
import { InvestigationLandingProps } from "./layout";
import { InvestigationProps } from "./layout";
import {
getAuthCookies,
getUserFromJwt,
} from "@/components/auth/serverHelpers";
import { queryAPI } from "@/lib/fetch";
import InvestigationLandingPageTemplate from "@/components/templates/InvestigationLandingPage";
import { getSite } from "@/helpers";
import { FunctionComponent } from "react";

const Query = graphql(`
query InvestigationPage($site: [String], $uri: [String]) {
Expand All @@ -19,9 +20,7 @@ const Query = graphql(`
}
`);

const InvestigationLanding: (
props: InvestigationLandingProps
) => Promise<JSX.Element> = async ({
const InvestigationLanding: FunctionComponent<InvestigationProps> = async ({
params: { locale, investigation },
searchParams,
}) => {
Expand Down
4 changes: 2 additions & 2 deletions app/[locale]/[investigation]/reference/[slug]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { graphql } from "@/gql/public-schema";
import { queryAPI } from "@/lib/fetch";
import { fallbackLng } from "@/lib/i18n/settings";
import { InvestigationParams } from "../../layout";
import { RootLayoutParams } from "@/app/[locale]/layout";
import { RootParams } from "@/app/[locale]/layout";
import { notFound } from "next/navigation";
import ReferenceContentPage from "@/components/templates/ReferenceContentPage";
import { getSite } from "@/helpers";
Expand All @@ -12,7 +12,7 @@ interface ReferencePageParams {
}

export interface ReferencePageProps {
params: RootLayoutParams & InvestigationParams & ReferencePageParams;
params: RootParams & InvestigationParams & ReferencePageParams;
}

const Query = graphql(`
Expand Down
4 changes: 2 additions & 2 deletions app/[locale]/[investigation]/review/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { FunctionComponent, PropsWithChildren } from "react";
import { RootLayoutParams } from "../../layout";
import { RootParams } from "../../layout";
import { InvestigationParams } from "../layout";
import { ProgressProvider } from "@/contexts/Progress";
import Header from "@/page/Header/Header";
Expand All @@ -10,7 +10,7 @@ import {
} from "@/components/auth/serverHelpers";

export interface ReviewPageProps {
params: RootLayoutParams & InvestigationParams;
params: RootParams & InvestigationParams;
}

const ReviewLayout: FunctionComponent<
Expand Down
23 changes: 14 additions & 9 deletions app/[locale]/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import "focus-visible";
import "@/styles/styles.scss";
import { PropsWithChildren } from "react";
import { FunctionComponent, PropsWithChildren } from "react";
import { Metadata } from "next";
import { notFound } from "next/navigation";
import Script from "next/script";
import { graphql } from "@/gql/public-schema";
import { SourceSansPro } from "@/lib/fonts";
import StyledComponentsRegistry from "@/lib/registry";
import GlobalStyles from "@/lib/styles";
import { fallbackLng } from "@/lib/i18n/settings";
import { fallbackLng, languages } from "@/lib/i18n/settings";
import { queryAPI } from "@/lib/fetch";
import { GlobalDataProvider, GlobalData } from "@/contexts/GlobalData";
import { AuthDialogManagerProvider } from "@/contexts/AuthDialogManager";
Expand All @@ -18,12 +18,13 @@ import { getSite } from "@/helpers";
import AuthDialogs from "@/components/auth/AuthDialogs";
import { getAuthCookies } from "@/components/auth/serverHelpers";

export interface RootLayoutParams {
export interface RootParams {
locale: string;
}

interface RootLayoutProps {
params: RootLayoutParams;
export interface RootProps {
params: RootParams;
searchParams: Record<string, string | Array<string> | undefined>;
}

const PLAUSIBLE_DOMAIN = process.env.NEXT_PUBLIC_PLAUSIBLE_DOMAIN;
Expand Down Expand Up @@ -77,16 +78,20 @@ const getGlobals = async (locale = "en"): Promise<GlobalData | undefined> => {

export async function generateMetadata({
params: { locale },
}: RootLayoutProps): Promise<Metadata> {
}: RootProps): Promise<Metadata> {
const globalData = await getGlobals(locale);
const description = globalData?.siteInfo?.siteDescription;

return { description };
}

const RootLayout: (
props: PropsWithChildren<RootLayoutProps>
) => Promise<JSX.Element> = async ({
export const generateStaticParams = () => {
return languages.map((locale) => {
return { locale };
});
};

const RootLayout: FunctionComponent<PropsWithChildren<RootProps>> = async ({
params: { locale = fallbackLng },
children,
}) => {
Expand Down
10 changes: 3 additions & 7 deletions app/[locale]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { graphql } from "@/gql/public-schema";
import { draftMode } from "next/headers";
import { RootLayoutParams } from "./layout";
import { RootProps } from "./layout";
import HomePageTemplate from "@/templates/HomePage";
import { notFound } from "next/navigation";
import SignOut from "@/components/auth/buttons/SignOut";
Expand All @@ -10,14 +10,10 @@ import {
} from "@/components/auth/serverHelpers";
import { queryAPI } from "@/lib/fetch";
import { getSite } from "@/helpers";
import { FunctionComponent } from "react";

const CRAFT_HOMEPAGE_URI = "__home__";

interface HomePageProps {
params: RootLayoutParams;
searchParams: any;
}

export const revalidate = 60;

const Query = graphql(`
Expand All @@ -29,7 +25,7 @@ const Query = graphql(`
}
`);

const HomePage: (props: HomePageProps) => Promise<JSX.Element> = async ({
const HomePage: FunctionComponent<RootProps> = async ({
params: { locale },
searchParams,
}) => {
Expand Down
1 change: 1 addition & 0 deletions components/auth/investigation/SignedIn.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ const SignedIn: FunctionComponent<{
url={firstPage}
isInactive={status !== "active"}
isBlock
prefetch
/>
<SignOut redirectTo={signOutRedirect} />
</>
Expand Down
1 change: 1 addition & 0 deletions components/auth/investigation/SignedOut.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ const SignedOut: FunctionComponent<{
styleAs="tertiary"
url={firstPage}
text={t("auth.continue_wo_login_button")}
prefetch
/>
<Styled.LinkLabel>{t("auth.continue_wo_login_label")}</Styled.LinkLabel>
<SignUp />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,7 @@ const InvestigationGrid: FunctionComponent<InvestigationGridProps> = ({

return (
<li key={id}>
<Styled.MixedLink
aria-disabled={isInactive}
url={url}
>
<Styled.MixedLink aria-disabled={isInactive} url={url} prefetch>
<Styled.ImageWrapper>
{image && <Image image={image} role="presentation" />}
</Styled.ImageWrapper>
Expand Down
1 change: 1 addition & 0 deletions components/page/Pager/Pager.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ const Pager: FunctionComponent<PagerProps> = ({
<Styled.PagerButton
href={isNextDisabled ? "#" : nextPage}
aria-disabled={isNextDisabled}
prefetch
>
{rightText || t("pager.next")}
</Styled.PagerButton>
Expand Down
Loading

0 comments on commit a0616ce

Please sign in to comment.