prevent i18n flickering on pages (#1308)

* prevent i18n flickering on pages

- 404
- `/cancel`
- `/success`

* ssg for 404

* comments

* tweak

* 404

Co-authored-by: Peer Richelsen <peeroke@gmail.com>
This commit is contained in:
Alex Johansson 2021-12-14 13:31:54 +01:00 committed by GitHub
parent 8e447ea4b5
commit ad8ffd3de4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 71 additions and 1 deletions

View File

@ -1,5 +1,6 @@
import { BookOpenIcon, CheckIcon, CodeIcon, DocumentTextIcon } from "@heroicons/react/outline";
import { ChevronRightIcon } from "@heroicons/react/solid";
import { GetStaticPropsContext } from "next";
import Link from "next/link";
import { useRouter } from "next/router";
import React from "react";
@ -8,6 +9,8 @@ import { useLocale } from "@lib/hooks/useLocale";
import { HeadSeo } from "@components/seo/head-seo";
import { ssgInit } from "@server/lib/ssg";
export default function Custom404() {
const { t } = useLocale();
const router = useRouter();
@ -170,3 +173,13 @@ export default function Custom404() {
</>
);
}
export const getStaticProps = async (context: GetStaticPropsContext) => {
const ssr = await ssgInit(context);
return {
props: {
trpcState: ssr.dehydrate(),
},
};
};

View File

@ -15,6 +15,8 @@ import CustomBranding from "@components/CustomBranding";
import { HeadSeo } from "@components/seo/head-seo";
import { Button } from "@components/ui/Button";
import { ssrInit } from "@server/lib/ssr";
export default function Type(props: inferSSRProps<typeof getServerSideProps>) {
const { t } = useLocale();
// Get router variables
@ -145,6 +147,7 @@ export default function Type(props: inferSSRProps<typeof getServerSideProps>) {
}
export const getServerSideProps = async (context: GetServerSidePropsContext) => {
const ssr = await ssrInit(context);
const session = await getSession(context);
const booking = await prisma.booking.findUnique({
where: {
@ -202,6 +205,7 @@ export const getServerSideProps = async (context: GetServerSidePropsContext) =>
booking: bookingObj,
cancellationAllowed:
(!!session?.user && session.user?.id === booking.user?.id) || booking.startTime >= new Date(),
trpcState: ssr.dehydrate(),
},
};
};

View File

@ -22,6 +22,8 @@ import CustomBranding from "@components/CustomBranding";
import { HeadSeo } from "@components/seo/head-seo";
import Button from "@components/ui/Button";
import { ssrInit } from "@server/lib/ssr";
dayjs.extend(utc);
dayjs.extend(toArray);
dayjs.extend(timezone);
@ -279,6 +281,7 @@ export default function Success(props: inferSSRProps<typeof getServerSideProps>)
}
export async function getServerSideProps(context: GetServerSidePropsContext) {
const ssr = await ssrInit(context);
const typeId = parseInt(asStringOrNull(context.query.type) ?? "");
if (isNaN(typeId)) {
@ -358,6 +361,7 @@ export async function getServerSideProps(context: GetServerSidePropsContext) {
hideBranding: eventType.team ? eventType.team.hideBranding : isBrandingHidden(eventType.users[0]),
profile,
eventType,
trpcState: ssr.dehydrate(),
},
};
}

43
server/lib/ssg.ts Normal file
View File

@ -0,0 +1,43 @@
import { GetStaticPropsContext } from "next";
import { i18n } from "next-i18next.config";
import { serverSideTranslations } from "next-i18next/serverSideTranslations";
import superjson from "superjson";
import prisma from "@lib/prisma";
import { appRouter } from "@server/routers/_app";
import { createSSGHelpers } from "@trpc/react/ssg";
/**
* Initialize static site rendering tRPC helpers.
* Provides a method to prefetch tRPC-queries in a `getStaticProps`-function.
* Automatically prefetches i18n based on the passed in `context`-object to prevent i18n-flickering.
* Make sure to `return { props: { trpcState: ssr.dehydrate() } }` at the end.
*/
export async function ssgInit<TParams extends { locale?: string }>(opts: GetStaticPropsContext<TParams>) {
const requestedLocale = opts.params?.locale || opts.locale || i18n.defaultLocale;
const isSupportedLocale = i18n.locales.includes(requestedLocale);
if (!isSupportedLocale) {
console.warn(`Requested unsupported locale "${requestedLocale}"`);
}
const locale = isSupportedLocale ? requestedLocale : i18n.defaultLocale;
const _i18n = await serverSideTranslations(locale, ["common"]);
const ssg = createSSGHelpers({
router: appRouter,
transformer: superjson,
ctx: {
prisma,
session: null,
user: null,
locale,
i18n: _i18n,
},
});
// always preload i18n
await ssg.fetchQuery("viewer.i18n");
return ssg;
}

View File

@ -6,6 +6,12 @@ import { createSSGHelpers } from "@trpc/react/ssg";
import { appRouter } from "../routers/_app";
/**
* Initialize server-side rendering tRPC helpers.
* Provides a method to prefetch tRPC-queries in a `getServerSideProps`-function.
* Automatically prefetches i18n based on the passed in `context`-object to prevent i18n-flickering.
* Make sure to `return { props: { trpcState: ssr.dehydrate() } }` at the end.
*/
export async function ssrInit(context: GetServerSidePropsContext) {
const ctx = await createContext(context);

View File

@ -38,7 +38,7 @@
"jest-playwright-preset",
"expect-playwright"
],
"allowJs": false,
"allowJs": true,
"incremental": true
},
"include": [