Skip to content

Commit

Permalink
Merge pull request #105 from sanity-io/next-ssg
Browse files Browse the repository at this point in the history
Statically Generated Sites & webhook-based on-demand page revalidation
  • Loading branch information
j0nas committed Mar 9, 2022
2 parents 1bed7c3 + 4f67644 commit 3b1d979
Show file tree
Hide file tree
Showing 4 changed files with 191 additions and 252 deletions.
4 changes: 3 additions & 1 deletion web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,11 @@
"dependencies": {
"@portabletext/react": "^1.0.2",
"@sanity/client": "^3.0.3",
"@sanity/webhook": "^1.0.2",
"clsx": "^1.1.1",
"date-fns": "^2.28.0",
"date-fns-tz": "^1.3.0",
"next": "12.0.8",
"next": "12.1.0",
"next-sanity": "^0.4.0",
"next-seo": "^5.1.0",
"proper-url-join": "^2.1.1",
Expand All @@ -23,6 +24,7 @@
"react-gtm-module": "^2.0.11"
},
"devDependencies": {
"@types/node": "^14.18.12",
"@types/proper-url-join": "^2.1.1",
"@types/react": "^17.0.38",
"autoprefixer": "^10.4.2",
Expand Down
25 changes: 20 additions & 5 deletions web/pages/[[...slug]].tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import clsx from 'clsx';
import { GetServerSideProps } from 'next';
import { GetStaticPaths, GetStaticProps } from 'next';
import { groq } from 'next-sanity';
import urlJoin from 'proper-url-join';
import { useEffect, useState } from 'react';
import Hero from '../components/Hero';
import TextBlock from '../components/TextBlock';
Expand All @@ -12,12 +13,12 @@ import Nav from '../components/Nav';
import MetaTags from '../components/MetaTags';
import { usePreviewSubscription } from '../lib/sanity';
import client from '../lib/sanity.server';
import { Figure } from '../types/Figure';
import { Slug } from '../types/Slug';
import { Section } from '../types/Section';
import { Hero as HeroProps } from '../types/Hero';
import { mainEventId } from '../util/entityPaths';
import styles from './app.module.css';
import { Figure } from '../types/Figure';

const QUERY = groq`
{
Expand Down Expand Up @@ -241,11 +242,25 @@ const Route = ({ data: initialData, slug, preview }: RouteProps) => {
);
};

export const getServerSideProps: GetServerSideProps = async ({
params,
export const getStaticPaths: GetStaticPaths = async () => {
const allSlugsQuery = groq`*[defined(slug.current) && _type == 'route'][].slug.current`;
const pages = await client.fetch(allSlugsQuery);
const paths = pages.map((slug) => ({
params: {
slug: [urlJoin(slug, { leadingSlash: false })].filter(Boolean),
},
}));

return { paths, fallback: 'blocking' };
};

export const getStaticProps: GetStaticProps = async ({
params: { slug: slugParam },
preview = false,
}) => {
const slug = params?.slug?.[0] || '/';
const slug = Array.isArray(slugParam)
? urlJoin.apply(null, [...slugParam, { leadingSlash: false }])
: slugParam || '/';
const data = await client.fetch(QUERY, { slug });
if (!data?.route?.page) {
return { notFound: true };
Expand Down
63 changes: 63 additions & 0 deletions web/pages/api/revalidate.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { NextApiRequest, NextApiResponse } from 'next';
import urlJoin from 'proper-url-join';
import { isValidRequest } from '@sanity/webhook';
import client from '../../lib/sanity.server';

const SECTION_UPDATED_QUERY = `
*[_type == "page" && references($id)] {
"slug": *[_type == "route" && references(^._id)].slug.current
}["slug"][]`;
const PAGE_UPDATED_QUERY = `*[_type == "route" && references($id)].slug.current`;
const ROUTE_UPDATED_QUERY = `*[_type == "route" && _id == $id].slug.current`;

const getQueryForType = (type: string) => {
switch (type) {
case 'route':
return ROUTE_UPDATED_QUERY;
case 'page':
return PAGE_UPDATED_QUERY;
default:
return SECTION_UPDATED_QUERY;
}
};

const log = (msg: string, error?: boolean) =>
console[error ? 'error' : 'log'](`[revalidate] ${msg}`);

export default async function revalidate(
req: NextApiRequest,
res: NextApiResponse
) {
if (!isValidRequest(req, process.env.SANITY_STUDIO_REVALIDATE_SECRET)) {
const invalidRequest = 'Invalid request';
log(invalidRequest, true);
return res.status(401).json({ message: invalidRequest });
}

const { _id: id, _type } = req.body as { _id: string; _type: string };
if (typeof id !== 'string' || !id) {
const invalidId = 'Invalid _id';
log(invalidId, true);
return res.status(400).json({ message: invalidId });
}

log(`Querying for _id '${id}', type '${_type}' ..`);
const relatedRoutes = await client.fetch(getQueryForType(_type), { id });
if (!Array.isArray(relatedRoutes) || !relatedRoutes.length) {
const noUpdatedObjects = 'No pages reference updated object';
log(noUpdatedObjects, true);
return res.status(200).json({ message: noUpdatedObjects });
}

try {
await Promise.all(
relatedRoutes.map((route) => res.unstable_revalidate(urlJoin(route)))
);
const updatedRoutes = `Updated routes: ${relatedRoutes.join(', ')}`;
log(updatedRoutes);
return res.status(200).json({ message: updatedRoutes });
} catch (err) {
log(err.message, true);
return res.status(500).json({ message: err.message });
}
}

2 comments on commit 3b1d979

@vercel
Copy link

@vercel vercel bot commented on 3b1d979 Mar 9, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vercel
Copy link

@vercel vercel bot commented on 3b1d979 Mar 9, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

structured-content-2022-studio – ./studio

admin.structuredcontent.live
structured-content-2022-studio-git-main.sanity.build
structured-content-2022-studio.sanity.build

Please sign in to comment.