-
Notifications
You must be signed in to change notification settings - Fork 7.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: migrate React.dev to the App Router #7437
Merged
rickhanlonii
merged 39 commits into
reactjs:main
from
feedthejim:feedthejim/app-router-migration
Feb 1, 2025
Merged
Changes from all commits
Commits
Show all changes
39 commits
Select commit
Hold shift + click to select a range
7e62576
update version to latest + move folders around
feedthejim afc2f86
getting home page working
feedthejim 82ce63a
make the mdx setup work
feedthejim 84e4e75
bypass mdxname
feedthejim 521e058
split out mdx components
feedthejim 78eb453
re-add meta mdx logic
feedthejim 227ca33
replace mdxName usage
feedthejim 58893e2
fix code blocks
feedthejim bb73bef
fix max width
feedthejim 5f0c400
convert mdx post processing to actual plugins
feedthejim 54ed2f7
fix tailwind
feedthejim da986d3
fix incorrect iframe props
feedthejim 57e93aa
cleanup mdx dic
feedthejim c388c7a
make it actually build
feedthejim 07a6965
align fonts
feedthejim fbc4ad3
fix uwu script
feedthejim c240a23
fix search
feedthejim 2d21046
remove _app
feedthejim abd3e7a
make it actually build
feedthejim c17d55b
replace next-watch-remote with custom setup
feedthejim 5992b25
clean up logs + clean up inline scripts
feedthejim 6266d2a
add rss handler
feedthejim abe7942
remove rss generation
feedthejim 01b2bdd
remove rss generation
feedthejim c4840c9
support MDX components for TOC
feedthejim c6b7f38
clean up log + bump cache
feedthejim ce85254
fix toc
feedthejim 4bad08d
add back translations + add new overlay
feedthejim c0961e4
use MDX link instead of Next.js links for translation
feedthejim 5617362
fix analytics
feedthejim 6bca962
add myself to the contributors
feedthejim 662ca7e
fix blinking sidebar
feedthejim cb7be41
avoid rendering toc on the client
feedthejim 74a6251
plugin metadata
feedthejim d623e65
simplify metadata
feedthejim cc15fe1
fix title
feedthejim 552ce46
clean up metadata
feedthejim 58ce525
add back error decoder
feedthejim 2638b6e
Update src/content/learn/index.md
rickhanlonii File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
This file was deleted.
Oops, something went wrong.
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,172 @@ | ||
import fs from 'fs/promises'; | ||
import path from 'path'; | ||
import {Page} from 'components/Layout/Page'; | ||
import sidebarHome from '../../sidebarHome.json'; | ||
import sidebarLearn from '../../sidebarLearn.json'; | ||
import sidebarReference from '../../sidebarReference.json'; | ||
import sidebarCommunity from '../../sidebarCommunity.json'; | ||
import sidebarBlog from '../../sidebarBlog.json'; | ||
import {generateMDX} from '../../utils/generateMDX'; | ||
|
||
import {generateMetadata as generateSeoMetadata} from '../../utils/generateMetadata'; | ||
|
||
import {getRouteMeta, RouteItem} from 'components/Layout/getRouteMeta'; | ||
import {LanguageItem} from 'components/MDX/LanguagesContext'; | ||
import {cache} from 'react'; | ||
|
||
function getActiveSection(pathname: string) { | ||
if (pathname === '/') { | ||
return 'home'; | ||
} else if (pathname.startsWith('/reference')) { | ||
return 'reference'; | ||
} else if (pathname.startsWith('/learn')) { | ||
return 'learn'; | ||
} else if (pathname.startsWith('/community')) { | ||
return 'community'; | ||
} else if (pathname.startsWith('/blog')) { | ||
return 'blog'; | ||
} else { | ||
return 'unknown'; | ||
} | ||
} | ||
|
||
async function getRouteTree(section: string) { | ||
switch (section) { | ||
case 'home': | ||
case 'unknown': | ||
return sidebarHome; | ||
case 'learn': | ||
return sidebarLearn; | ||
case 'reference': | ||
return sidebarReference; | ||
case 'community': | ||
return sidebarCommunity; | ||
case 'blog': | ||
return sidebarBlog; | ||
default: | ||
throw new Error(`Unknown section: ${section}`); | ||
} | ||
} | ||
|
||
const getPageContent = cache(async function getPageContent( | ||
markdownPath: any[] | ||
) { | ||
const rootDir = path.join(process.cwd(), 'src/content'); | ||
let mdxPath = markdownPath?.join('/') || 'index'; | ||
let mdx; | ||
|
||
try { | ||
mdx = await fs.readFile(path.join(rootDir, mdxPath + '.md'), 'utf8'); | ||
} catch { | ||
mdx = await fs.readFile(path.join(rootDir, mdxPath, 'index.md'), 'utf8'); | ||
} | ||
|
||
return await generateMDX(mdx, mdxPath, {}); | ||
}); | ||
|
||
// This replaces getStaticPaths | ||
export async function generateStaticParams() { | ||
const rootDir = path.join(process.cwd(), 'src/content'); | ||
|
||
async function getFiles(dir: string): Promise<string[]> { | ||
const entries = await fs.readdir(dir, {withFileTypes: true}); | ||
const files = await Promise.all( | ||
entries.map(async (entry) => { | ||
const res = path.resolve(dir, entry.name); | ||
return entry.isDirectory() | ||
? getFiles(res) | ||
: res.slice(rootDir.length + 1); | ||
}) | ||
); | ||
|
||
return files | ||
.flat() | ||
.filter( | ||
(file: string) => file.endsWith('.md') && !file.startsWith('errors/') | ||
); | ||
} | ||
|
||
function getSegments(file: string) { | ||
let segments = file.slice(0, -3).replace(/\\/g, '/').split('/'); | ||
if (segments[segments.length - 1] === 'index') { | ||
segments.pop(); | ||
} | ||
return segments; | ||
} | ||
|
||
const files = await getFiles(rootDir); | ||
|
||
return files.map((file: any) => ({ | ||
markdownPath: getSegments(file), | ||
})); | ||
} | ||
|
||
export default async function WrapperPage({ | ||
params, | ||
}: { | ||
params: Promise<{markdownPath: string[]}>; | ||
}) { | ||
const {markdownPath} = await params; | ||
|
||
// Get the MDX content and associated data | ||
const {content, toc, meta} = await getPageContent(markdownPath); | ||
|
||
const pathname = '/' + (markdownPath?.join('/') || ''); | ||
const section = getActiveSection(pathname); | ||
const routeTree = await getRouteTree(section); | ||
|
||
// Load the list of translated languages conditionally. | ||
let languages: Array<LanguageItem> | null = null; | ||
if (pathname.endsWith('/translations')) { | ||
languages = await ( | ||
await fetch( | ||
'https://raw.githubusercontent.com/reactjs/translations.react.dev/main/langs/langs.json' | ||
) | ||
).json(); // { code: string; name: string; enName: string}[] | ||
} | ||
|
||
// Pass the content and TOC directly, as `getPageContent` should already return them in the correct format | ||
return ( | ||
<Page | ||
toc={toc} // Pass the TOC directly without parsing | ||
routeTree={routeTree as RouteItem} | ||
meta={meta} | ||
section={section} | ||
pathname={pathname} | ||
languages={languages}> | ||
{content} | ||
</Page> | ||
); | ||
} | ||
// Configure dynamic segments to be statically generated | ||
export const dynamicParams = false; | ||
|
||
export async function generateMetadata({ | ||
params, | ||
}: { | ||
params: Promise<{markdownPath: string[]}>; | ||
}) { | ||
const {markdownPath} = await params; | ||
const pathname = '/' + (markdownPath?.join('/') || ''); | ||
const section = getActiveSection(pathname); | ||
const routeTree = await getRouteTree(section); | ||
const {route, order} = getRouteMeta(pathname, routeTree as RouteItem); | ||
const { | ||
title = route?.title || '', | ||
description = route?.description || '', | ||
titleForTitleTag, | ||
} = await getPageContent(markdownPath).then(({meta}) => meta); | ||
|
||
return generateSeoMetadata({ | ||
title, | ||
isHomePage: pathname === '/', | ||
path: pathname, | ||
description, | ||
titleForTitleTag, | ||
image: `/images/og-${section}.png`, | ||
searchOrder: | ||
section === 'learn' || (section === 'blog' && pathname !== '/blog') | ||
? order | ||
: undefined, | ||
}); | ||
} |
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
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not a server component?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
error page must be a client component https://nextjs.org/docs/app/api-reference/file-conventions/error