Skip to content

Commit

Permalink
chore: final code review changes
Browse files Browse the repository at this point in the history
  • Loading branch information
ovflowd committed Nov 23, 2023
1 parent a399fdd commit 919cc49
Show file tree
Hide file tree
Showing 13 changed files with 74 additions and 39 deletions.
8 changes: 7 additions & 1 deletion app/[locale]/[[...path]]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,13 @@ const getPage: FC<DynamicParams> = async ({ params }) => {
return notFound();
};

// Enforce that all these routes are compatible with SSR
// In this case we want to catch-all possible pages even to this page. This ensures that we use our 404
// and that all pages including existing ones are handled here and provide `next-intl` locale also
// @see https://nextjs.org/docs/app/api-reference/file-conventions/route-segment-config#dynamicparams
export const dynamicParams = true;

// Enforces that this route is used as static rendering
// @see https://nextjs.org/docs/app/api-reference/file-conventions/route-segment-config#dynamic
export const dynamic = 'error';

export default getPage;
15 changes: 9 additions & 6 deletions app/[locale]/feed/[feed]/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@ const locale = defaultLocale.code;
type StaticParams = { params: { feed: string; locale: string } };

// This is the Route Handler for the `GET` method which handles the request
// for Blog Feeds within the Node.js Website
// for the Node.js Website Blog Feeds (RSS)
// @see https://nextjs.org/docs/app/building-your-application/routing/router-handlers
export const GET = async (_: Request, { params }: StaticParams) => {
// Generate the Feed for the given feed type (blog, releases, etc)
const websiteFeed = await provideWebsiteFeeds(params.feed);

return new NextResponse(websiteFeed, {
Expand All @@ -22,13 +23,15 @@ export const GET = async (_: Request, { params }: StaticParams) => {
};

// This function generates the static paths that come from the dynamic segments
// `en/feeds/[feed]` and returns an array of all available static paths
// this is useful for static exports, for example.
// Note that differently from the App Router these don't get built at the build time
// only if the export is already set for static export
// `[locale]/feeds/[feed]` and returns an array of all available static paths
// This is used for ISR static validation and generation
export const generateStaticParams = async () =>
siteConfig.rssFeeds.map(feed => ({ feed: feed.file, locale }));

// Enforces that this route is used as static rendering
// Forces that only the paths from `generateStaticParams` are allowed, giving 404 on the contrary
// @see https://nextjs.org/docs/app/api-reference/file-conventions/route-segment-config#dynamicparams
export const dynamicParams = false;

// Enforces that this route is cached and static as much as possible
// @see https://nextjs.org/docs/app/api-reference/file-conventions/route-segment-config#dynamic
export const dynamic = 'error';
25 changes: 14 additions & 11 deletions app/[locale]/next-data/blog-data/[category]/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ const locale = defaultLocale.code;
type StaticParams = { params: { category: string; locale: string } };

// This is the Route Handler for the `GET` method which handles the request
// for generating our static data for the Node.js Website
// for providing Blog Posts, Pagination for every supported Blog Category
// this includes the `year-XXXX` categories for yearly archives (pagination)
// @see https://nextjs.org/docs/app/building-your-application/routing/router-handlers
export const GET = async (_: Request, { params }: StaticParams) => {
const { posts, pagination } = await provideBlogData(params.category);
Expand All @@ -19,21 +20,23 @@ export const GET = async (_: Request, { params }: StaticParams) => {
};

// This function generates the static paths that come from the dynamic segments
// `en/next-data/[type]` and returns an array of all available static paths
// this is useful for static exports, for example.
// Note that differently from the App Router these don't get built at the build time
// only if the export is already set for static export
// `[locale]/next-data/blog-data/[category]` and returns an array of all available static paths
// This is used for ISR static validation and generation
export const generateStaticParams = async () => {
const {
meta: { categories, pagination },
} = await provideBlogData();
// This metadata is the original list of all available categories and all available years
// within the Node.js Website Blog Posts (2011, 2012...)
const { meta } = await provideBlogData();

return [
...categories.map(category => ({ category, locale })),
...pagination.map(year => ({ category: `year-${year}`, locale })),
...meta.categories.map(category => ({ category, locale })),
...meta.pagination.map(year => ({ category: `year-${year}`, locale })),
];
};

// Enforces that this route is used as static rendering
// Forces that only the paths from `generateStaticParams` are allowed, giving 404 on the contrary
// @see https://nextjs.org/docs/app/api-reference/file-conventions/route-segment-config#dynamicparams
export const dynamicParams = false;

// Enforces that this route is cached and static as much as possible
// @see https://nextjs.org/docs/app/api-reference/file-conventions/route-segment-config#dynamic
export const dynamic = 'error';
12 changes: 7 additions & 5 deletions app/[locale]/next-data/release-data/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { defaultLocale } from '@/next.locales.mjs';
const locale = defaultLocale.code;

// This is the Route Handler for the `GET` method which handles the request
// for generating our static data for the Node.js Website
// for generating static data related to the Node.js Release Data
// @see https://nextjs.org/docs/app/building-your-application/routing/router-handlers
export const GET = async () => {
const releaseData = await provideReleaseData();
Expand All @@ -14,12 +14,14 @@ export const GET = async () => {
};

// This function generates the static paths that come from the dynamic segments
// `en/next-data/[type]` and returns an array of all available static paths
// this is useful for static exports, for example.
// Note that differently from the App Router these don't get built at the build time
// only if the export is already set for static export
// `[locale]/next-data/release-data/` and returns an array of all available static paths
// This is used for ISR static validation and generation
export const generateStaticParams = async () => [{ locale }];

// Forces that only the paths from `generateStaticParams` are allowed, giving 404 on the contrary
// @see https://nextjs.org/docs/app/api-reference/file-conventions/route-segment-config#dynamicparams
export const dynamicParams = false;

// Enforces that this route is used as static rendering
// @see https://nextjs.org/docs/app/api-reference/file-conventions/route-segment-config#dynamic
export const dynamic = 'error';
7 changes: 6 additions & 1 deletion components/Docs/NodeApiVersionLinks.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import type { FC } from 'react';

import getReleaseData from '@/next-data/releaseData';
import { DOCS_URL } from '@/next.constants.mjs';

const NodeApiVersionLinks = async () => {
// This is a React Async Server Component
// Note that Hooks cannot be used in a RSC async component
// Async Components do not get re-rendered at all.
const NodeApiVersionLinks: FC = async () => {
const releaseData = await getReleaseData();

// Gets all major releases without the 0x release as those are divided on 0.12x and 0.10x
Expand Down
3 changes: 3 additions & 0 deletions components/Downloads/DownloadReleasesTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ import getReleaseData from '@/next-data/releaseData';
import { getNodeApiLink } from '@/util/getNodeApiLink';
import { getNodejsChangelog } from '@/util/getNodeJsChangelog';

// This is a React Async Server Component
// Note that Hooks cannot be used in a RSC async component
// Async Components do not get re-rendered at all.
const DownloadReleasesTable: FC = async () => {
const releaseData = await getReleaseData();

Expand Down
3 changes: 3 additions & 0 deletions components/withNodeRelease.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ type WithNodeReleaseProps = {
children: FC<{ release: NodeRelease }>;
};

// This is a React Async Server Component
// Note that Hooks cannot be used in a RSC async component
// Async Components do not get re-rendered at all.
export const WithNodeRelease: FC<WithNodeReleaseProps> = async ({
status,
children: Component,
Expand Down
15 changes: 7 additions & 8 deletions layouts/BlogCategoryLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ const getCurrentCategory = (pathname: string) => {
return `year-${new Date().getFullYear()}`;
};

// This is a React Async Server Component
// Note that Hooks cannot be used in a RSC async component
// Async Components do not get re-rendered at all.
const BlogCategoryLayout: FC = async () => {
const { frontmatter, pathname } = getClientContext();
const category = getCurrentCategory(pathname);
Expand All @@ -44,14 +47,10 @@ const BlogCategoryLayout: FC = async () => {
<h2>{title}</h2>

<ul className="blog-index">
{posts.map(post => (
<li key={post.slug}>
<Time
date={post.date}
format={{ month: 'short', day: '2-digit' }}
/>

<Link href={post.slug}>{post.title}</Link>
{posts.map(({ slug, date, title }) => (
<li key={slug}>
<Time date={date} format={{ month: 'short', day: '2-digit' }} />
<Link href={slug}>{title}</Link>
</li>
))}
</ul>
Expand Down
3 changes: 3 additions & 0 deletions layouts/DocsLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ import type { FC, PropsWithChildren } from 'react';
import SideNavigation from '@/components/SideNavigation';
import getReleaseData from '@/next-data/releaseData';

// This is a React Async Server Component
// Note that Hooks cannot be used in a RSC async component
// Async Components do not get re-rendered at all.
const DocsLayout: FC<PropsWithChildren> = async ({ children }) => {
const releaseData = await getReleaseData();

Expand Down
6 changes: 4 additions & 2 deletions next-data/blogData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ import { ENABLE_STATIC_EXPORT, NEXT_DATA_URL } from '@/next.constants.mjs';
import type { BlogDataRSC } from '@/types';

const getBlogData = (category: string): Promise<BlogDataRSC> => {
// When we're using Static Exports the Next.js Server is not running (during build-time)
// hence the self-ingestion APIs will not be available. In this case we want to load
// the data directly within the current thread, which will anyways be loaded only once
// We use lazy-imports to prevent `provideBlogData` from executing on import
if (ENABLE_STATIC_EXPORT) {
// Loads the data dynamically with lazy-loading to prevent data-generation
// within the top level import
return import('@/next-data/providers/blogData').then(
({ default: provideBlogData }) => provideBlogData(category)
);
Expand Down
6 changes: 4 additions & 2 deletions next-data/releaseData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ import { ENABLE_STATIC_EXPORT, NEXT_DATA_URL } from '@/next.constants.mjs';
import type { NodeRelease } from '@/types';

const getReleaseData = (): Promise<NodeRelease[]> => {
// When we're using Static Exports the Next.js Server is not running (during build-time)
// hence the self-ingestion APIs will not be available. In this case we want to load
// the data directly within the current thread, which will anyways be loaded only once
// We use lazy-imports to prevent `provideBlogData` from executing on import
if (ENABLE_STATIC_EXPORT) {
// Loads the data dynamically with lazy-loading to prevent data-generation
// within the top level import
return import('@/next-data/providers/releaseData').then(
({ default: provideReleaseData }) => provideReleaseData()
);
Expand Down
8 changes: 6 additions & 2 deletions next.constants.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,14 @@ export const BASE_PATH = process.env.NEXT_PUBLIC_BASE_PATH || '';
/**
* This is used for fetching static next-data through the /en/next-data/ endpoint
*
* @note this is assumes that the Node.js Website is either running within Vercel Environment
* Note this is assumes that the Node.js Website is either running within Vercel Environment
* or running locally (either production or development) mode
*
* Note this variable can be overrided via a manual Environment Variable defined by us if necessary.
*/
export const NEXT_DATA_URL = VERCEL_ENV
export const NEXT_DATA_URL = process.env.NEXT_PUBLIC_DATA_URL
? process.env.NEXT_PUBLIC_DATA_URL
: VERCEL_ENV
? `${BASE_URL}${BASE_PATH}/en/next-data/`
: `http://localhost:3000/en/next-data/`;

Expand Down
2 changes: 1 addition & 1 deletion next.dynamic.constants.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ export const DEFAULT_METADATA = {
canonical: '',
languages: { 'x-default': '' },
types: {
'application/rss+xml': 'https://nodejs.org/en/feed/blog.xml',
'application/rss+xml': `${BASE_URL}${BASE_PATH}/en/feed/blog.xml`,
},
},
icons: { icon: siteConfig.favicon },
Expand Down

0 comments on commit 919cc49

Please sign in to comment.