swyxio / swyxdotio

This is the repo for swyx's blog - Blog content is created in github issues, then posted on swyx.io as blog pages! Comment/watch to follow along my blog within GitHub
https://swyx.io
MIT License
342 stars 45 forks source link

Shortcodes vs MDX #293

Closed swyxio closed 2 years ago

swyxio commented 2 years ago

source: devto devToUrl: "https://dev.to/swyx/shortcodes-vs-mdx-3d4e" devToReactions: 15 devToReadingTime: 5 devToPublishedAt: "2021-03-26T21:40:42.355Z" devToViewsCount: 934 title: Shortcodes vs MDX published: true description: Comparing the two popular custom dynamic content solutions! tags: writing, shortcodes, react canonical_url: https://www.swyx.io/shortcodes-vs-mdx-3d4e

There are two prevalent solutions for injecting dynamic content into markdown: Shortcodes and MDX. I think most people should use shortcodes, but there are also valid cases for picking MDX. Here's my breakdown.

There's some confusion between these content formats (Gatsby's docs for shortcodes literally just make them synonyms for MDX) so I figure it is worth setting some definitons upfront.

Defining Shortcodes

The earliest instance I can find of Shortcodes is in WordPress. The whole goal is that you can continue writing in standard plain text, but insert special components just by using a special syntax that wouldn't show up in normal writing:

These are mostly used for inserting anything from Tweet embeds to YouTube videos to GitHub gists to image galleries. But there's really no limit to what you can define for your shortcodes, to cover anything from simple Tip and Alert displays to interactive Quiz components!

Shortcodes are the plaintext analog of Web Components - where a <custom-element> might extend HTML, shortcodes extend plaintext (typically Markdown). You could write your shortcodes in React or Vue or Web Components - it doesn't matter, because they are inserted after the fact.

Defining MDX

MDX, introduced in 2018, inverts this model of content vs code. It renders your markdown as a React component (or Svelte component, with MDsveX), so it is very natural to add more React components inline:

import Video from '../components/video'

# My blog post

Here's a video:
<Video width={300} src="video.mp4" />

MDsveX goes a little further, offering layouts, frontmatter, syntax highlighting, styling, and state. But MDX is by far more popular because of React. In my 2020 survey of the React ecosystem, all blogging documentation tools now offer MDX support by default.

Comparing the Two

Superficially, both Shortcodes and MDX do the same job, which is why it feels a little silly to write up a blogpost like this. But they do have important differences, that I myself did not appreciate until Nick Reese converted me when I was arguing for MDsveX in Elder.js.

Conclusion

I think most developer bloggers spring for MDX because they enjoy using JSX, but they end up using the same 3-4 components on every single post or document they write. In those scenarios, they are accepting the downsides of MDX, without really benefiting from the customizability.

In fact, I think you can go pretty far with shortcodes. Does it really matter if you have 30 components that you pull in via shortcodes? Not really, amount of components isn't really a motivating factor. I think this covers most bloggers. Most bloggers should use shortcodes.

However, there are still valid usecases of MDX.

For a design system or frontend component library, one might argue that MDX allows you to display the exact components that you are documenting:

import Button from './components/Button'

# Button

This is our default Button!

<Button />

This is our secondary Button!

<Button type="ghost" />

However for backend code, or for complex-enough frontend code that you'd like to run integration tests on, you may wish to transclude from a source file, and that may use shortcodes. Storybook's Component Story Format also provides a nice convention that keeps your documentation agnostic of MDX.

Because MDX compiles to a React component, you could build tooling that can typecheck MDX (as far as I know this doesn't yet exist, hence this point is all the way down here). The same is doable for shortcodes, but since there is very little restriction on how shortcodes are processed, it is far less likely that successful shared tooling will arise.

Finally, there's the question of customization. If you need to compose components inline as you write, then MDX is unquestionably the right choice. This is why Hashicorp went with MDX, and you can listen in on my conversation with Jeff Escalante for more on this.

My final "quote" on this, if you will, is this:

Appendix: Structured Content

Perhaps a third "alternative" to Shortcodes vs MDX is structured content - discrete "blocks" of content rendered inside of a CMS, like you see in Notion, Sanity.io or in WordPress Gutenberg. I don't have a lot of personal experience with this, but my sense is that it locks you in to these systems, in exchange for WYSIWYG and no-code editing. In a way, structured content is what would happen if your writing is entirely made up of data inside shortcodes.