diff --git a/package.json b/package.json index a29c740d..74979585 100644 --- a/package.json +++ b/package.json @@ -51,6 +51,7 @@ "next-compose-plugins": "^2.2.1", "next-mdx-remote": "4.0.0-rc.1", "next-seo": "^5.1.0", + "next-sitemap": "^2.1.14", "next-themes": "^0.0.15", "next-transpile-modules": "^9.0.0", "node-fetch": "^3.2.0", diff --git a/pages/feed.atom.ts b/pages/feed.atom.ts index fea3923d..72dd043a 100644 --- a/pages/feed.atom.ts +++ b/pages/feed.atom.ts @@ -1,8 +1,6 @@ import { buildFeed } from "../lib/build-feed"; import type { GetServerSideProps } from "next"; -const AtomFeed = () => null; - export const getServerSideProps: GetServerSideProps = async (context) => { const feed = buildFeed(); const { res } = context; @@ -18,4 +16,5 @@ export const getServerSideProps: GetServerSideProps = async (context) => { }; }; -export default AtomFeed; +// eslint-disable-next-line import/no-anonymous-default-export +export default () => null; diff --git a/pages/feed.xml.ts b/pages/feed.xml.ts index bce94fcc..e8b87486 100644 --- a/pages/feed.xml.ts +++ b/pages/feed.xml.ts @@ -1,8 +1,6 @@ import { buildFeed } from "../lib/build-feed"; import type { GetServerSideProps } from "next"; -const RssFeed = () => null; - export const getServerSideProps: GetServerSideProps = async (context) => { const feed = buildFeed(); const { res } = context; @@ -18,4 +16,5 @@ export const getServerSideProps: GetServerSideProps = async (context) => { }; }; -export default RssFeed; +// eslint-disable-next-line import/no-anonymous-default-export +export default () => null; diff --git a/pages/sitemap.xml.ts b/pages/sitemap.xml.ts index 330f0e9f..ac88d840 100644 --- a/pages/sitemap.xml.ts +++ b/pages/sitemap.xml.ts @@ -1,72 +1,48 @@ -// WARNING: THIS FILE CONTAINS HISTORICAL LEVELS OF HACKINESS AND SHOULD NOT BE REPLICATED NOR ADMIRED. - +import { getServerSideSitemap } from "next-sitemap"; import { getAllNotes } from "../lib/parse-notes"; import { baseUrl } from "../lib/config"; import type { GetServerSideProps } from "next"; - -const Sitemap = () => null; - -type Page = { - relUrl: string; - priority?: number; - changeFreq?: string; - lastMod?: string | Date; -}; +import type { ISitemapField } from "next-sitemap"; export const getServerSideProps: GetServerSideProps = async (context) => { - // TODO: make this not manual (serverless functions can't see /pages at runtime) - const pages: Page[] = [ - { relUrl: "/", priority: 1.0, changeFreq: "weekly" }, // homepage - { relUrl: "/notes/", changeFreq: "weekly" }, - { relUrl: "/birthday/" }, - { relUrl: "/cli/" }, - { relUrl: "/contact/" }, - { relUrl: "/hillary/" }, - { relUrl: "/leo/" }, - { relUrl: "/license/", priority: 0.1, changeFreq: "yearly" }, - { relUrl: "/previously/" }, - { relUrl: "/privacy/", priority: 0.1, changeFreq: "yearly" }, - { relUrl: "/projects/", changeFreq: "daily" }, - { relUrl: "/uses/" }, - { relUrl: "/y2k/" }, + // TODO: make this not manual (serverless functions can't see filesystem at runtime) + const pages: ISitemapField[] = [ + { loc: "/", priority: 1.0, changefreq: "weekly" }, // homepage + { loc: "/notes/", changefreq: "weekly" }, + { loc: "/birthday/" }, + { loc: "/cli/" }, + { loc: "/contact/" }, + { loc: "/hillary/" }, + { loc: "/leo/" }, + { loc: "/license/", priority: 0.1, changefreq: "yearly" }, + { loc: "/previously/" }, + { loc: "/privacy/", priority: 0.1, changefreq: "yearly" }, + { loc: "/projects/", changefreq: "daily" }, + { loc: "/uses/" }, + { loc: "/y2k/" }, ]; // push notes separately and use their metadata const notes = getAllNotes(); notes.map((note) => pages.push({ - relUrl: `/notes/${note.slug}/`, + loc: `/notes/${note.slug}/`, // pull lastMod from front matter date - lastMod: note.date, + lastmod: note.date, + priority: 0.7, }) ); - const xml = ` - - ${pages - .map( - (page) => ` - - ${baseUrl}${page.relUrl} - ${page.priority ? page.priority.toFixed(1) : 0.7} - ${page.changeFreq || "monthly"} - ${page.lastMod || new Date().toISOString()} - ` - ) - .join("") - .trim()} -`; + // make all relative URLs absolute + pages.map((page) => (page.loc = `${baseUrl}${page.loc}`)); - const { res } = context; - res.setHeader("content-type", "application/xml; charset=utf-8"); // cache on edge for one hour + const { res } = context; res.setHeader("cache-control", "s-maxage=3600, stale-while-revalidate"); - res.write(xml); - res.end(); - return { - props: {}, - }; + // next-sitemap takes care of the rest of the response for us + return getServerSideSitemap(context, pages); }; -export default Sitemap; +// eslint-disable-next-line import/no-anonymous-default-export +export default () => null; diff --git a/yarn.lock b/yarn.lock index e7aefdec..95c26694 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1030,6 +1030,11 @@ "@babel/helper-validator-identifier" "^7.16.7" to-fast-properties "^2.0.0" +"@corex/deepmerge@^2.6.148": + version "2.6.148" + resolved "https://registry.yarnpkg.com/@corex/deepmerge/-/deepmerge-2.6.148.tgz#8fa825d53ffd1cbcafce1b6a830eefd3dcc09dd5" + integrity sha512-6QMz0/2h5C3ua51iAnXMPWFbb1QOU1UvSM4bKBw5mzdT+WtLgjbETBBIQZ+Sh9WvEcGwlAt/DEdRpIC3XlDBMA== + "@csstools/postcss-font-format-keywords@^1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@csstools/postcss-font-format-keywords/-/postcss-font-format-keywords-1.0.0.tgz#7e7df948a83a0dfb7eb150a96e2390ac642356a1" @@ -4843,6 +4848,14 @@ next-seo@^5.1.0: resolved "https://registry.yarnpkg.com/next-seo/-/next-seo-5.1.0.tgz#aa9fd6249a11bf93e6da06fa2a6bc89268936edf" integrity sha512-ampuQfNTOi1x+xtRIb6CZGunIo6rQXtMo2Tyu861d5GjJFIwfOXsA4lzCa4+e2rLkyXDyVpavNNUZWa3US9ELw== +next-sitemap@^2.1.14: + version "2.1.14" + resolved "https://registry.yarnpkg.com/next-sitemap/-/next-sitemap-2.1.14.tgz#d800a85c2d045dfdfe8982c8fdb3304087950515" + integrity sha512-7IqZjCGYSoA7csSc7B3m3m7hlFYd7Csg2PrNX97wH6/yJZ58nXiBR2JYQhHOZE3CzP3BAUKxwhiv2SlDiRzNXA== + dependencies: + "@corex/deepmerge" "^2.6.148" + minimist "^1.2.5" + next-themes@^0.0.15: version "0.0.15" resolved "https://registry.yarnpkg.com/next-themes/-/next-themes-0.0.15.tgz#ab0cee69cd763b77d41211f631e108beab39bf7d"