Updating to gatsbyv5 with mdx2

Troublesome upgrade

Upgrading from the previous version of MDX was a little tricky as my implementation was poorly/naively executed.

The features that I considered necessary requirements were to

  • write my notes using .md as opposed to .mdx.
  • Rather than storing my mdx pages via the src/pages I wanted to use gatsby-plugin-mdx config options to pull the .md from a subdirectory 'mdx-content/posts'.
  • I needed the shortcodes feature for syntax highlighting
  • I also wanted to abstract the mdx logic into its own theme, as this would be simpler to maintain.

Anyhow, when I updated to Gatsby-v5 and gatsby-plugin-mdx it became apparent that this wasn't going to be as simple to fix due to my dodgy impementation and the updated changes in the gatsby-plugin-mdx and MDX2. The most obvious of these (not including mdx1-to-mdx2 errors) is the changes to how the gatsby-node api deals with the createPage path and the default Layout.

mdxPosts.forEach(({ node }) => {
createPage({
// will take account of folder/directory structure
path: node.frontmatter.slug,
// - FAILs WITH THEME CONFIG AT BUILD, SEEMS TO FAIL TO FIND COMPONENT OF MDX/COMPONENT TEMPLATE
// (right at bundling stage of Gatsby build) conditionally render custom page templates???
component: `${require.resolve(
`./src/templates/mdx-post-template.jsx`
)}?__contentFilePath=${node.internal.contentFilePath}`,
// if gatsby site opposed to theme
// component: `${path.resolve(`${__dirname}/src/templates/mdx-post-template.jsx`)}?__contentFilePath=${node.internal.contentFilePath}`
// component: ... as in docs
// mdxPostTemplate + `?__contentFilePath=${node.internal.contentFilePath}`,
context: { id: node.id },
});
});

Once the MDX1-to-MDX2 errors had been corrected things seemed to build in development mode, but I found that using a default layout set via gatsby-node would fail at build time, at the HTML bundling stage. The error itself requesting a issue be setup over at the gatsby repo and not providing much detail on what went wrong. Something about Gatsby not finding the pageContext of graphql query.

At first I thought that this might be because I was wrapping my .md content with a Layout component from another sibling theme. A sitewide layout. I tried moving the gatsby-plugin-mdx logic back into the theme containing the Layout but the build still failed. It then dawned on me that I hadn't accounted that the new implementation didn't require an MDXProvider component. However, using this Component was a requirement as my implementation made use of component shortcodes for things like code-syntax highlighting.

I decided that the path of least resistantce was to import the necessary Layout in each .md file, rather than try and pass the Layout through at the createPage gatsby-node API. This functionality is an updated feature of MDX2.

export { default } from "../../../src/components/Layout/DefaultMdxLayout.js"

Enabling a Layout component like so,

// DefaultMdxLayout.js
import React from "react";
// import site layout from another theme, don't necessarily always need this
import SiteLayout from "../../../../gatsby-theme-websume-2021/src/components/site-wide/Layout/Layout";
import { MDXProvider } from "@mdx-js/react";
// overrule mdx components via 'shortco des'
export const components = {
p: ({ children }, props) => (
<p style={{ color: "var(--color-text)" }} {...props}>
{children}
</p>
),
};
//
function Layout({ children }, props) {
return (
<SiteLayout>
<div className="wrapper">
<div className="mdx-content">
<MDXProvider components={components}>
<article>{children}</article>
</MDXProvider>
</div>
</div>
</SiteLayout>
);
}
export { Layout };
export default Layout;

Things seemed to be looking up, I could specify different Layout components and their shortcode components, if i wanted to make use of shortcode codesplitting, which wasn't as simple in mdx1. Most imporantly my build process was successful.

I thought everything was functioning properly but on further inspection I noticed that some of the mdx links on the mdx archive page were returning 404 errors. This seemed to be being caused by naming differences, if either of the two frontmatter used for creating the path did NOT match the file name or parent directory, then a 404 error occured. In the new and updated config the frontmatter used to create the initial page slug (during gatsby-node) didn't seem to be having ayn effect. The page itself was created at where it resided in the parent mdx directory and the filename of the slug. In the previous configuration, this was the exact use-case I was trying to break. IE a URL structure (slug) decided at the .md level, from the frontmatter.

Rather persevere with my dubious fileUnder/slug frontmatter for creating page-paths I decided just to use the default gatsby-node API. The 'vanilla' MDX2 has actually dropped default support for frontmatter, and looks to have moved to ESM(? or is it the other one?) import/export syntax. Managing the page slug implicitly from the file name seemed like the simplest, least error prone solution. One source of truth and all that. Nevertheless Gatsby has included frontmatter implementation with gatsby-plugin-mdx.