From 8d47958473d6ceb23339841c02e4d4d5e16d533d Mon Sep 17 00:00:00 2001 From: Jake Jarvis Date: Wed, 6 Jul 2022 03:32:55 -0400 Subject: [PATCH] fix `sitemap.xml` timeouts --- pages/notes/[slug].tsx | 4 ++-- pages/notes/index.tsx | 12 +++++------- pages/projects.tsx | 12 +++++------- pages/site.webmanifest.ts | 13 +++++++------ pages/sitemap.xml.ts | 26 +++++++++++++------------- 5 files changed, 32 insertions(+), 35 deletions(-) diff --git a/pages/notes/[slug].tsx b/pages/notes/[slug].tsx index e33dd8d2..79c535d6 100644 --- a/pages/notes/[slug].tsx +++ b/pages/notes/[slug].tsx @@ -9,10 +9,10 @@ import { getNoteSlugs } from "../../lib/helpers/parse-notes"; import { compileNote } from "../../lib/helpers/compile-note"; import * as config from "../../lib/config"; import { articleJsonLd, favicons } from "../../lib/config/seo"; -import type { GetStaticProps, GetStaticPaths } from "next"; +import type { GetStaticProps, GetStaticPaths, InferGetStaticPropsType } from "next"; import type { NoteWithSource, NoteFrontMatter } from "../../types"; -const Note = ({ frontMatter, source }: NoteWithSource) => { +const Note = ({ frontMatter, source }: InferGetStaticPropsType) => { return ( <> { +const Notes = ({ notesByYear }: InferGetStaticPropsType) => { return ( <> { ); }; -export const getStaticProps: GetStaticProps = async () => { +export const getStaticProps: GetStaticProps<{ + notesByYear: NotesByYear; +}> = async () => { // parse the year of each note and group them together const notes = await getAllNotes(); const notesByYear: NotesByYear = {}; diff --git a/pages/projects.tsx b/pages/projects.tsx index e16a493c..56e8b196 100644 --- a/pages/projects.tsx +++ b/pages/projects.tsx @@ -7,7 +7,7 @@ import RepositoryCard from "../components/RepositoryCard"; import { OctocatOcticon } from "../components/Icons"; import { styled } from "../lib/styles/stitches.config"; import { authorSocial } from "../lib/config"; -import type { GetStaticProps } from "next"; +import type { GetStaticProps, InferGetStaticPropsType } from "next"; import type { User, Repository } from "@octokit/graphql-schema"; import type { Project } from "../types"; @@ -42,11 +42,7 @@ const GitHubLogo = styled(OctocatOcticon, { fill: "$text", }); -type StaticProps = { - repos: Project[]; -}; - -const Projects = ({ repos }: StaticProps) => { +const Projects = ({ repos }: InferGetStaticPropsType) => { return ( <> { ); }; -export const getStaticProps: GetStaticProps = async () => { +export const getStaticProps: GetStaticProps<{ + repos: Project[]; +}> = async () => { // don't fail the entire site build if the required API key for this page is missing if (typeof process.env.GH_PUBLIC_TOKEN === "undefined" || process.env.GH_PUBLIC_TOKEN === "") { console.warn(`ERROR: I can't fetch any GitHub projects without "GH_PUBLIC_TOKEN" set! Skipping for now...`); diff --git a/pages/site.webmanifest.ts b/pages/site.webmanifest.ts index e4fa4c0e..f3dd42e3 100644 --- a/pages/site.webmanifest.ts +++ b/pages/site.webmanifest.ts @@ -3,6 +3,13 @@ import { favicons } from "../lib/config/seo"; import type { GetServerSideProps } from "next"; export const getServerSideProps: GetServerSideProps> = async (context) => { + const { res } = context; + + // https://developer.mozilla.org/en-US/docs/Web/Manifest#deploying_a_manifest + res.setHeader("content-type", "application/manifest+json; charset=utf-8"); + // cache on edge for one week + res.setHeader("cache-control", "public, max-age=0, s-maxage=604800, stale-while-revalidate"); + const manifest = { name: config.siteName, short_name: config.siteDomain, @@ -37,12 +44,6 @@ export const getServerSideProps: GetServerSideProps> = asy display: "browser", start_url: "/", }; - const { res } = context; - - // https://developer.mozilla.org/en-US/docs/Web/Manifest#deploying_a_manifest - res.setHeader("content-type", "application/manifest+json; charset=utf-8"); - // cache on edge for one week - res.setHeader("cache-control", "public, max-age=0, s-maxage=604800, stale-while-revalidate"); res.write(JSON.stringify(manifest)); res.end(); diff --git a/pages/sitemap.xml.ts b/pages/sitemap.xml.ts index f88e6f18..a01d2fa0 100644 --- a/pages/sitemap.xml.ts +++ b/pages/sitemap.xml.ts @@ -1,12 +1,20 @@ -import { SitemapStream, streamToPromise, SitemapItemLoose, EnumChangefreq } from "sitemap"; +import { SitemapStream, SitemapItemLoose, EnumChangefreq } from "sitemap"; import { getAllNotes } from "../lib/helpers/parse-notes"; import { baseUrl } from "../lib/config"; import { RELEASE_DATE } from "../lib/config/constants"; import type { GetServerSideProps } from "next"; export const getServerSideProps: GetServerSideProps> = async (context) => { + const { res } = context; const stream = new SitemapStream({ hostname: baseUrl }); + // cache on edge for 12 hours + res.setHeader("cache-control", "public, max-age=0, s-maxage=43200, stale-while-revalidate"); + res.setHeader("content-type", "application/xml; charset=utf-8"); + + // related: https://github.com/vercel/next.js/discussions/15453 + stream.pipe(res); + // TODO: make this not manual (serverless functions can't see filesystem at runtime) const pages: SitemapItemLoose[] = [ { @@ -32,13 +40,13 @@ export const getServerSideProps: GetServerSideProps> = asy // push notes separately and use their metadata const notes = await getAllNotes(); - notes.forEach((note) => + notes.forEach((note) => { pages.push({ url: `/notes/${note.slug}/`, // pull lastMod from front matter date lastmod: new Date(note.date).toISOString(), - }) - ); + }); + }); // set lastmod of /notes/ page to most recent post's date pages.push({ @@ -53,17 +61,9 @@ export const getServerSideProps: GetServerSideProps> = asy pages.forEach((page) => { stream.write(page); }); + stream.end(); - // cache on edge for 12 hours - const { res } = context; - res.setHeader("cache-control", "public, max-age=0, s-maxage=43200, stale-while-revalidate"); - res.setHeader("content-type", "application/xml; charset=utf-8"); - - // finally write the resulting XML - res.write(await streamToPromise(stream)); - res.end(); - return { props: {}, };