DEV Community

loading...

How to use the Remark Markdown converters with Next.js projects

jameswallis profile image James Wallis Updated on ・3 min read

Next.js is a React.js framework for server side rendering and static projects. It's easy to use and works extremely well when building a website which stores its content in Markdown. A feature called dynamic routes, which generates routes at build time, provides functionality to read a directory full of Markdown files and generate separate webpages for each file.

Remark-react is a package that converts Markdown into React and it works with a Next.js application. It differs from remark-html as it doesn't force the developer to use dangerouslySetInnerHTML.

Honestly, if you're wanting to use Markdown with Next.js I'd recommend you try out remark-react. If you do, you should also be aware of the following:

Remark-react will create all links using the <a> component whereas in Next.js you should be using the <Link> component from next/link.

Using the proper <Link> component in a Next.js project is important as it changes the content of the page and the URL without a full redirect, whereas when an anchor (<a>) tag is used the page will be reloaded and React will need to do a full render - this can cause your application to perform badly and appear slow.

 Configuring a Next.js application to use remark-react, properly

The example is taken from GitHub

Adding Markdown to React conversion

printMarkdown.js on GitHub

You'll need three NPM packages:

npm i -s unified remark-parse remark-react
Enter fullscreen mode Exit fullscreen mode

Once you've added them, import them all into your React app:

import unified from 'unified';
import parse from 'remark-parse';
import remark2react from 'remark-react';
Enter fullscreen mode Exit fullscreen mode

Next, add the following code to convert Markdown into React components:

const content = unified()
    .use(parse)
    .use(remark2react)
    .processSync(markdown).result;
Enter fullscreen mode Exit fullscreen mode

From the code blocks above, your Next.js application should now be rendering Markdown into React.

Adding a CustomLink to handle local and external linking

Now we can add a custom link component to the remark-react configuration to instruct it to use the <Link> component for local links and the <a> component for external links.

customLink.js on GitHub

Add a new component called customLink.js to your project with the contents:

import Link from 'next/link';

export default function CustomLink({ children, href }) {
  // If the link is local it will start with a "/"
  // Otherwise it'll be something like "https://"
  return href.startsWith('/') || href === '' ? (
    <Link href={href}>
      <a>
        {children}
      </a>
    </Link>
  ) : (
    <a
      href={href}
      target="_blank"
      rel="noopener noreferrer"
    >
      {children}
    </a>
  );
}
Enter fullscreen mode Exit fullscreen mode

The CustomLink component will render a <Link> if the href passed in has a local target such as /about but will render an <a> if it has an external target such as https://dev.to.

 Updating the Markdown converter to use the CustomLink component

Finally, we need to update the Markdown to React code to use the CustomLink component when rendering links. This can be done by adding a configuration object to the remark-react .use line:

  const content = unified()
    .use(parse)
    .use(remark2react, {
      remarkReactComponents: {
        // Use CustomLink instead of <a>
        a: CustomLink,
      },
    })
    .processSync(markdown).result;
Enter fullscreen mode Exit fullscreen mode

Summary

That's all you need to do to use React-remark in your Next.js project. Using the configuration object, you can add a custom component for more than just an anchor HTML tag, incase you want to swap the img tag for something more intelligent (image compression?) for example.

Drop me a reaction or comment if this has helped you.
Thanks for reading!

Discussion

pic
Editor guide
Collapse
adamreinmuller profile image
Adam Reinmuller

Dude I can't thank you enough for this article and the attached repo.
My guesstimate is that you saved me 20 hours at least... especially using the CustomLink method.
Cheers

Collapse
jameswallis profile image
James Wallis Author

Buzzing that the article helped, thanks!