Feature Request: Building MDX Pages via `getStaticProps`
See original GitHub issueFeature request
Given that Next.js is investing efforts into static generation with the likes of getStaticProps
and getStaticPaths
, it would be great to leverage the full power of MDX without being tied to the Webpack loader’s (@next/mdx
) current constraints.
The current use of @next/mdx
has its limitations:
- Constrained to a single layout
- No ability to transform MDX to HTML for content feeds (e.g. RSS)
- No ability to parse frontMatter
- No ability to fetch from remote sources (e.g. CMS)
- Difficult to transform raw content
next-mdx-enhanced
does a great job of alleviating some of these concerns but still relies heavily on Webpack, rather than utilizing Next’s static functions.
This PR suggests @next/mdx
could be extended to offer users more flexibility (but hopefully still easy-to-follow) on how their pages are built. This suggestion aims to provide:
Describe the solution you’d like
Note: These examples would still rely on the consumer configuring their own MDXProvider (e.g. Theme-UI)
-
An
MDXRenderer
that allows for full control of layout:(Importing an
mdx
file would return an object containingfrontMatter
andmdxContent
)// e.g. src/pages/blog/[id].tsx import * as React from "react"; import { GetStaticProps, GetStaticPaths, NextPage } from "next"; import Error from "next/error"; import LayoutPost from "../layouts/post"; import { somePrivateFunctionToGlobMdxFileNames } from "./utils"; // but maybe this could be a function added to `@next/mdx` // Proposed: import { MDXRenderer } from "@next/mdx"; type BlogPostProps = { error?: boolean }; export const getStaticPaths: GetStaticPaths = async () => ({ paths: somePrivateFunctionToGlobMdxFileNames("../posts"), }); export const getStaticProps: GetStaticProps<BlogPostProps> = async ( context ) => { // this could also be a remote data source const res = await import(`../posts/${context.params.id}.mdx`); // const { frontMatter, mdxContent } = res return { props: res || { error: true } }; }; const BlogPost: React.FC<NextPage & BlogPostProps> = ({ error, ...props }) => error ? ( <Error statusCode={404} /> ) : ( <LayoutPost title={props.frontMatter.title}> <MDXRenderer {...props} /> </LayoutPost> ); export default BlogPostPage;
-
An
mdxToStaticMarkup
function that allows theMDXRenderer
to be converted to static HTML (for RSS feeds etc.).mdxToStaticMarkup(<MDXRenderer />);
With this approach the consumer would have the freedom to transform content if necessary.
Describe alternatives you’ve considered
One approach I tried back in january was to use MDX’s async API in the getStaticProps
method directly, but I hit a snag with this issue: https://github.com/mdx-js/mdx/issues/382#issuecomment-523014913
More importantly though, given Next.js does such a great job of reducing set-up complexity, it would be great to have something that makes MDX more flexible but still easy to use.
Additional context
As of now my availability is open and I would be more than happy to collaborate with the Next.js core team into spiking this as an option (if desired).
Issue Analytics
- State:
- Created 3 years ago
- Reactions:6
- Comments:12 (10 by maintainers)
Top GitHub Comments
Would love to see this implemented as well.
I tried using
next-mdx-remote
&next-mdx-enhanced
but ran into its limitations (specifically having images in the same folder as the posts that it cannot solve)I had to use hacks to solve MDX to HTML (for RSS) → https://github.com/vercel/next.js/discussions/17931
Gotcha, thanks for the explanation
Do the Next.js core team plan on integrating something similar to
next-mdx-remote
in the future?I do feel that something like this is more inline to what Next.js is achieving in other areas, it would be great to see this for MDX too