[0:00] I’ve got a Markdown file here that I want to treat as MDX so I can have interactive counter components or whatever other components that I want in the instructions for the workshops. As you can see here, that’s not being processed as MDX.

[0:16] This is just being treated as Markdown, and if you dive through this, you can see where that is being treated as just like a regular string, rather than being treated as MDX, which I want it to be. I’ve got this whole, big setup here and this compile-mdx.server with a bunch of plugins and all of this stuff, even caches and stuff.

[0:37] It’s really difficult to work in this. Whenever you run into a situation where it’s difficult to make changes and see your changes live and everything, I find it’s always best to try and reproduce the problem that you’re having in a completely separate environment, and then you have fewer moving parts.

[0:58] What we’re going to do is, I’m going to come down here. We’re going to make a new directory called test.ignored. That’s my global gitignore, just ignores everything that has a .ignore in the file name. Inside of this, we’re going to make a test.ts, and we’re going to also make whatever else we need.

[1:18] In my case, I need a README.md and also, let’s see, a component.tsx. I’m going to make a counter component to export that. We’ll import React and then in my README, I’m going to import the Counter from the component, and we’ll say this is my counter, Counter. All right, great.

[1:53] That should work with what I’m trying to do, and then we’ll make our test. We’ll say import path from ‘path’ and bundleMdx. No, that’s not it. mdx-bundler, and we’ll make a function, because I can’t use top-level await because these aren’t native ESM. If it was native ESM, you don’t need to make this go function. You just do await at the root.

[2:25] Now, I can say bundleMdx. I think bundleMDX in [laughs] all caps, and we’ll say file: path.join and I’m going to say _dirname. That will go right there, _dirname. We’re actually going to be processing the README.md.

[2:49] You take as few of the pieces of your actual code as possible to reproduce the problem. You narrow the problem down as much as possible. We’ll get our result from that await, and then we’ll console.log the result.code.

[3:06] You know what, another thing that we’ll do is in here, we’ll make it obvious when it has been processed properly by adding a bunch of exclamation points. Now, we’re going to run tsx watch ./test.ignored/test.ts. Let’s move this out of the way and take a look at what we’ve got here.

[3:32] Expected value for process.env. That’s interesting. I could rerun the script with setting the app, but we’ll say process.env. NODE_ENV= ‘development,’ which is what I’m running when I’m running my server.

[3:47] That’s kind of weird that it requires that, but that’s OK, because I add that additional aspect to my actual environment until I get to the point where I’m reproducing the problem. I am reproducing the problem.

[4:00] You don’t see any all caps exclamation points, and in fact, there’s the import right there. [laughs] This is not great. Now, we can go through docs and different configuration options, and I’m going to skip all that because I actually did that already.

[4:19] The thing that’s going to fix this for us is there’s this mdxOptions (options) with mdx-bundler, and options.mdxExtensions. We need to treat our Markdown files as MDX. Actually, one other thing that we could do before we get to this is, let’s test a theory that if this were an MDX file, that it would be treated as such. Boom, there it is.

[4:47] All we need to do is tell our mdx-bundler or MDX that we need to treat .md files as .mdx files. Now we can switch this back to an .md. We switch this to .md. Of course, we need to return the options there. Oh no, it’s still not giving us all those exclamation points in here.

[5:12] The other thing that we need to add is options.format, and we’re going to force it to say, “Hey, I want the format of this thing to be MDX.” That’s going to force it, and now we are solid.

[5:25] Then the other thing that actually bothered me is I saw this fileName stuff in here. In production mode, that is all going to get removed, because these are debugging helpers and stuff. For my use case, I actually don’t want that, and so I also am going to add development is false, and I can very quickly see, those are all gone.

[5:50] I’m able to take this now over to my actual source code and add the pieces that were just the couple of lines that make all of the difference, and now I can come over to my running app, and indeed, it does run, and I can tab over to the button and, boom, boom, boom, boom, boom, boom. The button is totally working, so huzzah.

[6:11] Next time you run into something that is there’s so many moving pieces you have no idea what could be causing the problem, try to move to a separate environment and slowly add, add, add until you’ve reproduced the problem, and then you can work within that environment. It’s way, way faster.

[6:28] I hope that helps. Have an awesome day.

Read More