next.js: "getStaticProps is not defined" with mdx files
Bug report
I’m trying to use nextjs and mdx to build a simple site. When I export getStaticProps, I get an “undefined” error. It looks like an issue that happens client side.
To Reproduce
I followed the “with-mdx” example to add mdx pages to my application. https://github.com/zeit/next.js/tree/canary/examples/with-mdx
I try to generate static props from the mdx using exports (https://mdxjs.com/getting-started#exports)
// src/pages/index.mdx
# Helloworld
Content is here!
export function getStaticProps() {
return {
props: {hello: 'world'}
}
}
// src/_app.tsx
...
export default function App(app: AppProps) {
const { Component, pageProps } = app;
return (<MDXProvider components={components}>
<pre>{JSON.stringify(pageProps)}</pre>
<Component {...pageProps} />
</MDXProvider>
);
}
I get an undefined error:
ReferenceError: getStaticProps is not defined
Module../src/pages/index.mdx
./src/pages/index.mdx:25
22 | const layoutProps = {
23 | layout,
24 | hello,
> 25 | getStaticProps
26 | };
27 | const MDXLayout = "wrapper"
28 | export default function MDXContent({
The <pre>{hello: "world"}</pre>
appears on my webpage. It looks like this error is client side only, and the code behave as expect on the server.
Screenshot of the full error below.
Expected behavior
I expect to see the props and the content.
Screenshots
System information
- OS: macOS
- Version of Next.js: 9.3.4
- Version of Node.js: 12.14.0
"@mdx-js/loader": "^1.5.8",
"@next/mdx": "^9.3.5",
"cors": "^2.8.5",
"dotenv": "^8.2.0",
"isomorphic-unfetch": "^3.0.0",
"next": "^9.3.4",
"pg": "^8.0.2",
"react": "^16.13.1",
"react-dom": "^16.13.1",
"swr": "^0.2.0",
"unfetch": "^4.1.0"
Thanks for supporting this project!
About this issue
- Original URL
- State: closed
- Created 4 years ago
- Reactions: 13
- Comments: 23 (12 by maintainers)
The problem is that MDX adds
getStaticProps
tolayoutProps
, but thennext/babel
removes the export, so now the reference is missing. I think you can patch the issue by creating this Babel plugin, which removes all data fetching functions fromlayoutProps
:Then add it to your Babel configuration, let’s say we call it
babel-plugin-nextjs-mdx-patch.js
:I get a similar issue, but with
async
, after writing:Rewriting to:
Just the same as you:
You have to export
getStaticProps
from the MDX page itself, not layout.There is one syntax that seems to circumvent this incompatibility between MDX and Next.js:
But I’d say that it’s somewhat of a bug in MDX that this works because all exports are meant to be passed as props to layout, e.g.
export const meta = { ... }
is a common pattern, and I’d expectexport { meta } from './other-data
to behave the same, but it doesn’t.Spent some time trying to figure this out and can confirm that MDX V2 does fix this issue. If you’re ok being on the
next
version, you just need to install"@mdx-js/loader": "next"
and set the loader up yourself.I have some work I want to do in
getStaticProps
for all of my mdx pages (much like @kud, I think).Providing a custom renderer for
@mdx-js/loader
seems like a promising approach.next.config.js
layout.tsx
The static props seem to get passed into my layout just like I wanted, but I haven’t thoroughly tested yet.
My next thought is whether I can export additional static prop getter functions from mdx pages to merge into the
getStaticProps
function defined in the mdx renderer.No problem, glad it could help! In case you need extra markdown features like rendering tables, I ran into this issue switching to latest. You can fix it by adding remark-gfm:
@souporserious Thanks for this! I installed the
next
version and I’m able to now exportgetStaticProps
from my mdx pages, making life much easier. I’m fine with working around any stability issues as this is for a small personal blog anyway.I’ve noticed that with
@mdx-js/loader
(latest
ornext
) andxdm
, usinggetStaticProps
in.mdx
files isn’t equivalent to a.tsx
file.For example, suppose I do something like what @leerob does with
next-mdx-remote
, but in my.mdx
file:https://github.com/leerob/leerob.io/blob/9992324086e07c1dfb31e8b0629a034da1810a03/pages/blog/[slug].js#L41-L42
I’ll get this error, presumably because
getStaticProps
and it’s imports aren’t being stripped from the client-side bundle:For comparison, a vanilla
test.tsx
page can use the utilities just fine and Next.js seems to stripgetStaticProps
and its dependencies:Thank you so much for this explanation, and for your time. I’ll give a try of this!
This remark plugin could look something like this (adjust the logic accordingly because
file.path
is a full path):Now you saved it to
file.data
, and you could build a separate plugin that inserts anexport
statement into your MDX file, you can copy my remark-mdx-export-file-data.Then you would apply these two plugins like this:
Now your MDX file will both export
fromNow
and provide it to the layout, if one is provided. Notice that you can use remark-mdx-export-file-data for exporting anything attached tofile.data
.But this is obviously a temporary solution, MDX should provide a much better interface to do stuff like this. I haven’t been following closely, but I think that’s what MDX v2 will do.
I didn’t try to solve this problem before, so I don’t know if there’s a way. 🤷
Super interesting! Thank you very much @silvenon
Definitely annoying! This is why I went a little nuts in my configuration by building custom unified plugins for MDX, for example:
Depending on what you want you might find them useful, they are written to be reusable and the tests should help you figure out how they work. I was planning to publish them, but it seems like MDX v2 is moving towards this direction anyway.
No,
getInitialProps
is run by the server. 😕