Skip to content

Commit

Permalink
Fix static generation & switch to importing constituency json (#82)
Browse files Browse the repository at this point in the history
* Fix static generation & switch to importing constituency json

* The storyblok cache avoidance was breaking static serving of non-dynamic routes
* The unstable_cache for constituencydata import was causing issues with locally building for prod

* update comments & remove cache control variable as per asibs suggestions
  • Loading branch information
jms301 authored Mar 21, 2024
1 parent 351b806 commit 67dcdd3
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 68 deletions.
4 changes: 3 additions & 1 deletion app/[slug]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ export async function generateStaticParams() {
const files = await readdir(directory);

// Get rid of the .json extension
const slugs = files.map((file) => file.substring(0, file.indexOf(".")));
const slugs = files
.map((file) => file.substring(0, file.indexOf(".")))
.filter((slug) => slug !== "");
console.log("Top-level static slugs:", slugs);

return slugs.map((c) => ({
Expand Down
21 changes: 2 additions & 19 deletions app/api/constituencies/[slug]/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export const revalidate = false; // Never revalidate, always use cached version

// Return a list of `params` to populate the [slug] dynamic segment
export async function generateStaticParams() {
const constituencySlugs = await getConstituencySlugs();
const constituencySlugs = getConstituencySlugs();
return constituencySlugs.map((slug) => ({ slug: slug }));
}

Expand All @@ -21,26 +21,9 @@ export async function GET(
request: NextRequest,
{ params }: { params: { slug: string } },
) {
console.log(`GENERATING API RESPONSE FOR CONSTITUENCY ${params.slug}`);

// The cached version of constituency data doesn't seem to work in this file - because
// it's an API route perhaps?
const constituencyData: ConstituencyData = await getConstituencyData(
params.slug,
false,
);
console.log("Successfully fetched constituencies data");
const constituencyData: ConstituencyData = getConstituencyData(params.slug);

if (constituencyData) {
console.log(
`Found constituency data for ${params.slug},
constituencyIdentifiers ${constituencyData.constituencyIdentifiers},
partySlug ${constituencyData.recommendation.partySlug},
partyName ${partyNameFromSlug(
constituencyData.recommendation.partySlug,
)}`,
);

return Response.json({
constituencyIdentifiers: constituencyData.constituencyIdentifiers,
recommendation: {
Expand Down
30 changes: 20 additions & 10 deletions app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,27 @@ import StoryblokProvider from "@/storyblok/components/StoryblokProvider";
import StoryblokWrapper from "@/storyblok/components/StoryblokWrapper";
import { ComponentsMap } from "@/storyblok/components/ComponentsMap";

// Force next.js not to cache API calls by default. This means caching is OPT-IN rather than OPT-OUT.
// This avoids issues with the Storyblok js client, which has it's own built-in caching, and Next.js caching interferes with this...
export const revalidate = 0;
/*
* This line prevents caching when storyblok live editing is enabled:
* (revalidate = 0)
* Otherwise it sets the default for indefinite caching:
* (revalidate = false)
*/
export const revalidate =
process.env.ENABLE_STORYBLOK_LIVE_EDITING === "true" ? 0 : false;

storyblokInit({
accessToken: process.env.STORYBLOK_API_TOKEN,
use: [apiPlugin],
apiOptions: { region: "eu" },
components: ComponentsMap,
});
if (process.env.ENABLE_STORYBLOK_LIVE_EDITING === "true") {
storyblokInit({
accessToken: process.env.STORYBLOK_API_TOKEN,
use: [apiPlugin],
apiOptions: { region: "eu" },
components: ComponentsMap,
});
} else {
storyblokInit({
components: ComponentsMap,
});
}

export const metadata: Metadata = {
title: {
Expand Down Expand Up @@ -80,7 +91,6 @@ export default function RootLayout({
{children}
<StoryblokWrapper slug="layout/footer" />
</body>
<StoryblokBridgeLoader options={{}} />
</html>
);
}
Expand Down
46 changes: 8 additions & 38 deletions utils/constituencyData.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,7 @@
import { readFileSync } from "fs";
import path from "path";
import { unstable_cache } from "next/cache";
import getConfig from "next/config";
import constituencyJson from "@/data/constituency.json";

const { serverRuntimeConfig } = getConfig() || {};

const getConstituencyData = async (
constituencySlug: string,
cached: boolean = true,
): Promise<ConstituencyData> => {
const constituenciesData = await getConstituenciesData(cached);
const getConstituencyData = (constituencySlug: string) => {
const constituenciesData = getConstituenciesData();
const constituencyData = constituenciesData.find(
(c: ConstituencyData) =>
c.constituencyIdentifiers.slug === constituencySlug,
Expand All @@ -24,38 +16,16 @@ const getConstituencyData = async (
return constituencyData;
};

const getConstituencySlugs = async (
cached: boolean = true,
): Promise<string[]> => {
const constituenciesData = await getConstituenciesData(cached);
const getConstituencySlugs = (): string[] => {
const constituenciesData = getConstituenciesData();
return constituenciesData.map(
(c: ConstituencyData) => c.constituencyIdentifiers.slug,
);
};

const getConstituenciesData = async (
cached: boolean = true,
): Promise<ConstituencyData[]> => {
return cached
? await getConstituenciesDataCached()
: await getConstituenciesDataUncached();
};

const getConstituenciesDataCached = unstable_cache(
// Cache data function
async () => getConstituenciesDataUncached(),
// Cache key
[`data/constituency.json.${serverRuntimeConfig.appVersion}`],
// Cache options
{ revalidate: false }, // Cache will never refresh
);

const getConstituenciesDataUncached = async () => {
console.debug("constituencyData: fetching constituencies data");
const filePath = path.join(process.cwd(), "data", "constituency.json");
const fileContent = readFileSync(filePath, "utf8");
console.debug("constituencyData: fetched constituencies data from file");
return JSON.parse(fileContent);
const getConstituenciesData = (): ConstituencyData[] => {
// Have to typecast as the json load doesn't know about our enums
return constituencyJson as ConstituencyData[];
};

/**
Expand Down

0 comments on commit 67dcdd3

Please sign in to comment.