diff --git a/pages/items/[itemId]/index.tsx b/pages/items/[itemId]/index.tsx index 9b7971d2..b0b06cf4 100644 --- a/pages/items/[itemId]/index.tsx +++ b/pages/items/[itemId]/index.tsx @@ -1,7 +1,11 @@ +import { GetServerSideProps } from "next"; import ItemSearchPageToolbar from "../../../src/app/components/ItemSearchPageToolbar"; import ItemPage from "../../../src/app/ItemPage"; import PageLayout from "../../../src/app/PageLayout"; +import { gql, loadGraphqlQuery } from "../../../src/server/ssr-graphql"; import type { NextPageWithLayout } from "../../_app"; +// @ts-ignore doesn't understand module.exports +import { oneDay, oneWeek } from "../../../src/server/util"; const ItemPageWrapper: NextPageWithLayout = () => { return ; @@ -16,4 +20,49 @@ ItemPageWrapper.renderWithLayout = (children) => { ); }; +export const getServerSideProps: GetServerSideProps = async ({ + params, + res, +}) => { + if (params?.itemId == null) { + throw new Error(`assertion error: itemId param is missing`); + } + + // Load the most important, most stable item data to get onto the page ASAP. + // We'll cache it real hard, to help it load extra-fast for popular items! + const { errors, graphqlState } = await loadGraphqlQuery({ + query: gql` + query ItemsIndex_GetServerSideProps($itemId: ID!) { + item(id: $itemId) { + id + name + thumbnailUrl + description + isNc + isPb + createdAt + } + } + `, + variables: { itemId: params.itemId }, + }); + if (errors) { + console.warn( + `[SSR: /items/[itemId]] Skipping GraphQL preloading, got errors:` + ); + for (const error of errors) { + console.warn(`[SSR: /items/[itemId]]`, error); + } + return { props: { graphqlState: {} } }; + } + + // Cache this very aggressively, because it's such stable data! + res.setHeader( + "Cache-Control", + `public, s-maxage=${oneDay}, stale-while-revalidate=${oneWeek}` + ); + + return { props: { graphqlState } }; +}; + export default ItemPageWrapper; diff --git a/pages/outfits/new.tsx b/pages/outfits/new.tsx index fc9d0199..84c85fce 100644 --- a/pages/outfits/new.tsx +++ b/pages/outfits/new.tsx @@ -19,7 +19,7 @@ export const getServerSideProps: GetServerSideProps = async ({ query }) => { // with it! We add it as a special `pageProps` key named `graphqlState`, // which the `App` component intercepts and gives to the Apollo client. const outfitState = readOutfitStateFromQuery(query); - const res = await loadGraphqlQuery({ + const { errors, graphqlState } = await loadGraphqlQuery({ query: gql` query OutfitsNew_GetServerSideProps( $speciesId: ID! @@ -49,17 +49,17 @@ export const getServerSideProps: GetServerSideProps = async ({ query }) => { wornItemIds: outfitState.wornItemIds, }, }); - if (res.errors) { + if (errors) { console.warn( `[SSR: /outfits/new] Skipping GraphQL preloading, got errors:` ); - for (const error of res.errors) { + for (const error of errors) { console.warn(`[SSR: /outfits/new]`, error); } return { props: { graphqlState: {} } }; } - return { props: { graphqlState: res.state } }; + return { props: { graphqlState } }; }; export default WardrobePageWrapper; diff --git a/src/app/ItemPage.js b/src/app/ItemPage.js index 8584b7b0..bbed293a 100644 --- a/src/app/ItemPage.js +++ b/src/app/ItemPage.js @@ -41,7 +41,6 @@ import { logAndCapture, MajorErrorMessage, useLocalStorage, - usePageTitle, } from "./util"; import HTML5Badge, { layerUsesHTML5 } from "./components/HTML5Badge"; import { @@ -59,6 +58,7 @@ import SpeciesFacesPicker, { colorIsBasic, } from "./ItemPage/SpeciesFacesPicker"; import { useRouter } from "next/router"; +import Head from "next/head"; function ItemPage() { const { query } = useRouter(); @@ -95,8 +95,6 @@ export function ItemPageContent({ itemId, isEmbedded = false }) { { variables: { itemId }, returnPartialData: true } ); - usePageTitle(data?.item?.name, { skip: isEmbedded }); - if (error) { return ; } @@ -104,19 +102,26 @@ export function ItemPageContent({ itemId, isEmbedded = false }) { const item = data?.item; return ( - - - - - - {isLoggedIn && } + <> + {!isEmbedded && item?.name && ( + + {item?.name} | Dress to Impress + + )} + + + + + + {isLoggedIn && } + + {!isEmbedded && } - {!isEmbedded && } - - + + ); } diff --git a/src/server/ssr-graphql.js b/src/server/ssr-graphql.js index d0391c18..c16117a5 100644 --- a/src/server/ssr-graphql.js +++ b/src/server/ssr-graphql.js @@ -19,11 +19,11 @@ async function loadGraphqlQuery({ query, variables = {} }) { // a whole client!) const cache = new InMemoryCache(); cache.writeQuery({ query, variables, data }); - const state = cache.extract(); + const graphqlState = cache.extract(); // We return the data, errors, and cache state: we figure callers will almost // always want the errors and state, and may also want the data! - return { data, errors, state }; + return { data, errors, graphqlState }; } /**