In this article, I'll show you how to migrate your regular Gatsby Markdown blog to use MDX.
Setting up our MDX blog
MDX lets you use JSX with Markdown. If you have an existing Gatsby blog using Markdown, here's a quick guide for migrating to MDX.
As a starting point, we'll use Gatsby starter blog to quickly set up our blog. Let's turn this regular Markdown blog to use MDX.
First, open up the terminal and create a new site with gatsby-starter-blog
template.
gatsby new my-blog https://github.com/gatsbyjs/gatsby-starter-blog
Now navigate to the site's directory.
cd my-blog
Adding The MDX Plugin
First, we need to add MDX support for our blog. Let's install the gatsby-plugin-mdx
plugin and its dependencies. Also, remove the existing gatsby-transformer-remark
plugin.
npm install @mdx-js/mdx@v1 @mdx-js/react@v1 gatsby-plugin-mdx
npm remove gatsby-transformer-remark
You should install the correct versions; otherwise, it wouldn't work.
Now we need to update the gatsby-config.js
file. Replace gatsby-transformer-remark
with gatsby-plugin-mdx
and change the plugins
option to gatsbyRemarkPlugins
.
// gatsby-config.js
{
- resolve: `gatsby-transformer-remark`,
+ resolve: `gatsby-plugin-mdx`,
options: {
- plugins: [
+ gatsbyRemarkPlugins: [
{
resolve: `gatsby-remark-images`,
options: {
maxWidth: 630,
},
},
// Other Gatsby remark plugins
],
},
}
Updating gatsby-node.js
Next, we need to tell Gatsby to use MDX. Go to gatsby-node.js
and in the GraphQL query replace allMarkdownRemark
with allMdx
.
// gatsby-node.js
const result = await graphql(
`
{
- allMarkdownRemark
+ allMdx(
sort: { fields: [frontmatter___date], order: ASC }
limit: 1000
) {
nodes {
id
fields {
slug
}
}
}
}
`
)
Also, change the posts
constant.
// gatsby-node.js
- const posts = result.data.allMarkdownRemark.nodes
+ const posts = result.data.allMdx.nodes
Additionally, we need to change onCreateNode
to use Mdx
instead of MarkdownRemark
.
// gatsby-node.js
exports.onCreateNode = ({ node, actions, getNode }) => {
const { createNodeField } = actions
- if (node.internal.type === `MarkdownRemark`) {
+ if (node.internal.type === `Mdx`) {
const value = createFilePath({ node, getNode })
createNodeField({
name: `slug`,
node,
value,
})
}
}
Finally, on the createSchemaCustomization
hook, change MarkdownRemark
to Mdx
// gatsby-node.js
exports.createSchemaCustomization = ({ actions }) => {
const { createTypes } = actions
createTypes(`
// Previous types
- type MarkdownRemark implements Node {
+ type Mdx implements Node {
frontmatter: Frontmatter
fields: Fields
}
// Other stuff
`)
}
Updating the Blog Post Template
Next, we need to update our blog post template in src/templates/blog-post.js
. The MDXRenderer
component renders the contents of the .mdx
file, so let's import it.
// src/templates/blog-post.js
import { MDXRenderer } from 'gatsby-plugin-mdx';
Now in the GraphQL query, replace all occurrences of markdownRemark
with mdx
and change the html
field to body
.
// src/templates/blog-post.js
export const pageQuery = graphql`
query BlogPostBySlug(
$id: String!
$previousPostId: String
$nextPostId: String
) {
site {
siteMetadata {
title
}
}
- markdownRemark(id: { eq: $id }) {
+ mdx(id: { eq: $id }) {
id
excerpt(pruneLength: 160)
- html
+ body
frontmatter {
title
date(formatString: "MMMM DD, YYYY")
description
}
}
- previous: markdownRemark(id: { eq: $previousPostId }) {
+ previous: mdx(id: { eq: $previousPostId }) {
fields {
slug
}
frontmatter {
title
}
}
- next: markdownRemark(id: { eq: $nextPostId }) {
+ next: mdx(id: { eq: $nextPostId }) {
fields {
slug
}
frontmatter {
title
}
}
}
`
Remove the section
tag and add the MDXRenderer
component. Then change the post
constant to use mdx
.
// src/templates/blog-post.js
- <section dangerouslySetInnerHTML={{ __html: post.html }} itemProp="articleBody"/>
+ <MDXRenderer>{post.body}</MDXRenderer>
// src/templates/blog-post.js
- const post = data.markdownRemark
+ const post = data.mdx
Updating the Home Page
The src/pages/index.js
file, which renders the home page needs to be changed. So similar to what we did in src/templates/blog-post.js
, we need to change all occurrences of allMarkdownRemark
with allMdx
.
First, change the posts
constant
// src/pages/index.js
- const posts = data.allMarkdownRemark.nodes
+ const posts = data.allMdx.nodes
Then change the GraphQL query.
// src/pages/index.js
export const pageQuery = graphql`
query {
site {
siteMetadata {
title
}
}
- allMarkdownRemark(sort: { fields: [frontmatter___date], order: DESC }) {
+ allMdx(sort: { fields: [frontmatter___date], order: DESC }) {
nodes {
excerpt
fields {
slug
}
frontmatter {
date(formatString: "MMMM DD, YYYY")
title
description
}
}
}
}
`
Check whether any pages use allMarkdownRemark
and change them to allMdx
.
Updating File Extensions
Since we don't have any .mdx
files, let's tell Gatsby to accept both .md
and .mdx
extensions, so we can still use our existing .md
files. In gatsby-config.js
add the extensions
option to gatsby-plugin-mdx
and pass it an array of extensions.
// gatsby-config.js
{
resolve: `gatsby-plugin-mdx`,
options: {
+ extensions: [`.md`, `.mdx`],
// Other options
},
},
Now you just need to hit gatsby develop
and see your wonderful
MDX blog up and running.
Fixing Errors
Ok, that probably didn't work. So here're some errors I've faced and
how I fixed them.
1. GraphQL error
You probably missed one of the above steps. Go through it again and find out what you missed. Also, check whether all GraphQL queries are valid.
2.Error: MDB_PROBLEM: Unexpected problem - txn should abort
Make sure you changed the createSchemaCustomization
to use Mdx
instead of MarkdownRemark
. If this didn't work, try clearing the Gatsby cache.
gatsby clean
In my case, the issue still persisted, so I had to clear the npm
cache.
npm cache clean --force
3. Unknown: Unterminated JSX contents.
Make sure you have valid JSX. Here's a couple of things (not an exhaustive list) to look out for:
- Change the
class
attribute toclassName
. - Make sure all
<img/>
and<br/>
tags are self closing. - Write inline styles as objects.
4. Error: EPERM: operation not permitted
Try running gatsby clean
before setting up the development server with gatsby develop
.
Conclusion
And that's it! We got our MDX blog up and running. Enter gatsby develop
and see your brand new MDX blog. Now you can use any React component in your .mdx
files. Happy Blogging!
Top comments (0)