What is MDX? It's like "JSX in markdown". It lets you seamlessly write code in JSX in your markdown blog posts, for example.
Pros:
- Declarative, more straightforward concept
- Frontmatter and props support
- All power of markdown with power of react components
Cons:
- Non-informative error messages
- Need to restart development server after each added/changed import component
- Broken preview in vscode, github, gitlab(even with plugin)
Yes, it has some disadvantages. But nevertheless, I think mdx is the "new markdown". All these problems are temporary, and since it really cutting-edge technology, having all those problems are absolutely natural.
And if it's not production-ready yet, for personal blog or site it's absolute killer.
So, are you ready to discover future of tech blogging?
If you have no blog yet, just use gatsby-starter-blog-mdx, it has mdx support out of the box. Also you can check out official docs.
And for those who already have a blog and want to touch the awesomness of mdx, I will cover in details how to convert your markdown blog to mdx, let's go.
Check out files in this repo as an example
- Install all dependencies:
npm i gatsby-plugin-mdx @mdx-js/mdx @mdx-js/react
Optionally, add eslint mdx plugin:
npm i -D eslint-plugin-mdx
- Update Gatsby lifecycle files:
In gatsby-config, scroll to gatsby-transformer-remark, and replace:
gatsby-transformer-remark -> gatsby-plugin-mdx
plugins -> gatsbyRemarkPlugins
using following example:
module.exports = {
plugins: [
...
{
// line below changed
resolve: `gatsby-plugin-mdx`,
options: {
// line below changed
gatsbyRemarkPlugins: [
....
`gatsby-remark-smartypants`,
],
},
},
]
}
In gatsby-node, in GraphQL query replace "allMarkdownRemark" with "allMdx", and "MarkdownRemark" with "Mdx",
so it will look like this:
exports.createPages = async ({ graphql, actions }) => {
const { createPage } = actions
const blogPost = path.resolve(`./src/templates/blog-post.js`)
const result = await graphql(
`
{
allMdx(
sort: { fields: [frontmatter___date], order: DESC }
limit: 1000
) {
edges {
node {
...
const posts = result.data.allMdx.edges
...
if (node.internal.type === `Mdx`) {
const value = createFilePath({ node, getNode })
...
}
...
- Update post listing generation
In index.js(or where your posts listed), replace all "allMarkdownRemark" with "allMdx":
class BlogIndex extends React.Component {
render() {
const { data } = this.props
const posts = data.allMdx.edges
return (
<Layout location={this.props.location}>
<SEO title="All posts" />
<Bio />
{posts.map(({ node }) => {
...
})}
</Layout>
)
}
}
export default BlogIndex
export const pageQuery = graphql`
query {
allMdx(sort: { fields: [frontmatter___date], order: DESC }) {
edges {
...
}
}
}
`
- Update blog post template
In your /src/templates/blog-post.js (or similar), you need to do following changes:
- add import MDXRenderer
- replace dangerouslySetInnerHTML with MDXRenderer
- update query(change "markdown" to "mdx" and "html" to "body")
import { MDXRenderer } from 'gatsby-plugin-mdx';
class BlogPostTemplate extends React.Component {
render() {
const post = this.props.data.mdx
return (
<Layout title={post.frontmatter.title}>
<ContentSection
title={post.frontmatter.title}
subtitle={post.frontmatter.date}
color="white"
size="medium"
>
<article>
<MDXRenderer>{post.body}</MDXRenderer>
....
)
}
}
export default BlogPostTemplate
export const pageQuery = graphql`
query BlogPostBySlug($slug: String!) {
mdx(fields: { slug: { eq: $slug } }) {
id
excerpt(pruneLength: 160)
body
frontmatter {
...
}
}
}
`
- rename all your .md files to .mdx
- restart your development server:
gatsby develop
So far we changed:
gatsby-config
gatsby-node
blog-post.js
index.js(page)
Congratulations! you now have working mdx blog. Stay tuned.
Check out our themes and articles about Gatsby and subscribe!
Top comments (2)
Great introduction, thank you! :)
Does it make easy to use custom components in Markdown? Like
{% github name/repo no-readme %}
?