forked from nodejs/nodejs.org
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
meta: adopt next-intl and app router (nodejs#6092)
* meta: adopt next-intl and app router code: kept working on adoption of i18n feat: app router transition meta: renamed sections to containers due to fs casing fix: force static fix: minor fixes of build and caching feat: metadata of each page fix: tests and stuff fix: tiny type fix chore: updated link to guide chore: intl on stories chore: no usage of assert refactor: some more cleanups on codebase meta: some improvements and fixes refactor: more code review changes refactor: more standardisation next-intl chore: minor changes to 404 refactor: code cleanup and reusability fix: fixed tests and imports chore: minor fixes and test updates fix: sitemap generation and 404 ignore chore: cleanup activelocalizedlink chore: remove legacy sto-top chore: more cleanups chore: more cleanups chore: use right import chore: optimise generation of blog meta chore: small cleanup chore: updated collaborator guide meta: provide server and client version of hooks fix: tests imports fix: styles of blogcard * fix: fix eslint rules --------- Co-authored-by: Claudio Wunder <[email protected]>
- Loading branch information
Showing
188 changed files
with
4,831 additions
and
3,980 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
import { notFound } from 'next/navigation'; | ||
import { unstable_setRequestLocale } from 'next-intl/server'; | ||
import type { FC } from 'react'; | ||
|
||
import { setClientContext } from '@/client-context'; | ||
import { MDXRenderer } from '@/components/mdxRenderer'; | ||
import { WithLayout } from '@/components/withLayout'; | ||
import { DEFAULT_VIEWPORT, ENABLE_STATIC_EXPORT } from '@/next.constants.mjs'; | ||
import { dynamicRouter } from '@/next.dynamic.mjs'; | ||
import { availableLocaleCodes, defaultLocale } from '@/next.locales.mjs'; | ||
import { MatterProvider } from '@/providers/matterProvider'; | ||
|
||
type DynamicStaticPaths = { path: string[]; locale: string }; | ||
type DynamicParams = { params: DynamicStaticPaths }; | ||
|
||
// This is the default Viewport Metadata | ||
// @see https://nextjs.org/docs/app/api-reference/functions/generate-viewport | ||
export const viewport = DEFAULT_VIEWPORT; | ||
|
||
// This generates each page's HTML Metadata | ||
// @see https://nextjs.org/docs/app/api-reference/functions/generate-metadata | ||
export const generateMetadata = async (c: DynamicParams) => { | ||
const { path = [], locale = defaultLocale.code } = c.params; | ||
|
||
const pathname = dynamicRouter.getPathname(path); | ||
|
||
// Retrieves and rewriting rule if the pathname matches any rule | ||
const [, rewriteRule] = dynamicRouter.getRouteRewrite(pathname); | ||
|
||
return dynamicRouter.getPageMetadata( | ||
locale, | ||
rewriteRule ? rewriteRule(pathname) : pathname | ||
); | ||
}; | ||
|
||
// This provides all the possible paths that can be generated statically | ||
// + provides all the paths that we support on the Node.js Website | ||
export const generateStaticParams = async () => { | ||
const paths: DynamicStaticPaths[] = []; | ||
|
||
// We don't need to compute all possible paths on regular builds | ||
// as we benefit from Next.js's ISR (Incremental Static Regeneration) | ||
if (!ENABLE_STATIC_EXPORT) { | ||
return []; | ||
} | ||
|
||
for (const locale of availableLocaleCodes) { | ||
const routesForLanguage = await dynamicRouter.getRoutesByLanguage(locale); | ||
|
||
const mappedRoutesWithLocale = routesForLanguage.map(pathname => | ||
dynamicRouter.mapPathToRoute(locale, pathname) | ||
); | ||
|
||
paths.push(...mappedRoutesWithLocale); | ||
} | ||
|
||
return paths.sort(); | ||
}; | ||
|
||
// This method parses the current pathname and does any sort of modifications needed on the route | ||
// then it proceeds to retrieve the Markdown file and parse the MDX Content into a React Component | ||
// finally it returns (if the locale and route are valid) the React Component with the relevant context | ||
// and attached context providers for rendering the current page | ||
const getPage: FC<DynamicParams> = async ({ params }) => { | ||
const { path = [], locale = defaultLocale.code } = params; | ||
|
||
if (!availableLocaleCodes.includes(locale)) { | ||
// Forces the current locale to be the Default Locale | ||
unstable_setRequestLocale(defaultLocale.code); | ||
|
||
return notFound(); | ||
} | ||
|
||
// Configures the current Locale to be the given Locale of the Request | ||
unstable_setRequestLocale(locale); | ||
|
||
const pathname = dynamicRouter.getPathname(path); | ||
|
||
if (dynamicRouter.shouldIgnoreRoute(pathname)) { | ||
return notFound(); | ||
} | ||
|
||
// Retrieves and rewriting rule if the pathname matches any rule | ||
const [, rewriteRule] = dynamicRouter.getRouteRewrite(pathname); | ||
|
||
// We retrieve the source of the Markdown file by doing an educated guess | ||
// of what possible files could be the source of the page, since the extension | ||
// context is lost from `getStaticProps` as a limitation of Next.js itself | ||
const { source, filename } = await dynamicRouter.getMarkdownFile( | ||
locale, | ||
rewriteRule ? rewriteRule(pathname) : pathname | ||
); | ||
|
||
if (source.length && filename.length) { | ||
// This parses the source Markdown content and returns a React Component and | ||
// relevant context from the Markdown File | ||
const { MDXContent, frontmatter, headings } = | ||
await dynamicRouter.getMDXContent(source, filename); | ||
|
||
// Defines a shared Server Context for the Client-Side | ||
// That is shared for all pages under the dynamic router | ||
setClientContext({ frontmatter, headings, pathname }); | ||
|
||
return ( | ||
<MatterProvider matter={frontmatter} headings={headings}> | ||
<WithLayout layout={frontmatter.layout}> | ||
<MDXRenderer Component={MDXContent} /> | ||
</WithLayout> | ||
</MatterProvider> | ||
); | ||
} | ||
|
||
return notFound(); | ||
}; | ||
|
||
// Enforce that all these routes are compatible with SSR | ||
export const dynamic = 'error'; | ||
|
||
export default getPage; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
import NotFound from '@/app/not-found'; | ||
|
||
export default NotFound; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
import { Analytics } from '@vercel/analytics/react'; | ||
import { Source_Sans_3 } from 'next/font/google'; | ||
import { useLocale } from 'next-intl'; | ||
import type { FC, PropsWithChildren } from 'react'; | ||
|
||
import BaseLayout from '@/layouts/BaseLayout'; | ||
import { VERCEL_ENV } from '@/next.constants.mjs'; | ||
import { availableLocalesMap, defaultLocale } from '@/next.locales.mjs'; | ||
import { LocaleProvider } from '@/providers/localeProvider'; | ||
import { ThemeProvider } from '@/providers/themeProvider'; | ||
|
||
import '@/styles/old/index.css'; | ||
|
||
const sourceSans = Source_Sans_3({ | ||
weight: ['400', '600'], | ||
display: 'fallback', | ||
subsets: ['latin'], | ||
}); | ||
|
||
const RootLayout: FC<PropsWithChildren> = ({ children }) => { | ||
const locale = useLocale(); | ||
|
||
const { langDir, hrefLang } = availableLocalesMap[locale] || defaultLocale; | ||
|
||
return ( | ||
<html className={sourceSans.className} dir={langDir} lang={hrefLang}> | ||
<body> | ||
<LocaleProvider> | ||
<ThemeProvider> | ||
<BaseLayout>{children}</BaseLayout> | ||
</ThemeProvider> | ||
</LocaleProvider> | ||
|
||
{VERCEL_ENV && <Analytics />} | ||
|
||
<a rel="me" href="https://social.lfx.dev/@nodejs" /> | ||
</body> | ||
</html> | ||
); | ||
}; | ||
|
||
export default RootLayout; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import { useTranslations } from 'next-intl'; | ||
import type { FC } from 'react'; | ||
|
||
const NotFound: FC = () => { | ||
const t = useTranslations(); | ||
|
||
return ( | ||
<div className="container"> | ||
<h2>{t('pages.404.title')}</h2> | ||
<h3>{t('pages.404.description')}</h3> | ||
</div> | ||
); | ||
}; | ||
|
||
// This is a fallback Not Found Page that in theory should never be requested | ||
export const dynamic = 'force-dynamic'; | ||
|
||
export default NotFound; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import { cache } from 'react'; | ||
|
||
import type { ClientSharedServerContext } from './types'; | ||
|
||
// This allows us to have Server-Side Context's of the shared "contextual" data | ||
// which includes the frontmatter, the current pathname from the dynamic segments | ||
// and the current headings of the current markdown context | ||
export const getClientContext = cache(() => { | ||
const serverSharedContext: ClientSharedServerContext = { | ||
frontmatter: {}, | ||
pathname: '', | ||
headings: [], | ||
}; | ||
|
||
return serverSharedContext; | ||
}); | ||
|
||
// This is used by the dynamic router to define on the request | ||
// the current set of information we use (shared) | ||
export const setClientContext = (data: ClientSharedServerContext) => { | ||
getClientContext().frontmatter = data.frontmatter; | ||
getClientContext().pathname = data.pathname; | ||
getClientContext().headings = data.headings; | ||
}; |
Oops, something went wrong.