Using CodeMirror in Gatsby

January 03, 2020

Our website DevToolsDaily is implemented on Gatsby and hosted in Netlify; and it has multiple pages that use CodeMirror for in-browser coding practices.

We use it for GraphViz Playground or Markdown Editor (as well as JSON/YAML converters)

If you try to simply import CodeMirror (or most of the other code editor) they will fail because navigator or window or something else doesn't exist.

Gatsby website has a guide for that which mentions 3 options:

  1. use different library
  2. load from CDN using <Helmet>
  3. use loadable-components
  4. use react-lazy

I went through all 4 options for that project, and the simplest and most elegant was "3. use loadable-components".


How we do that

We depend on the following open source libraries.

  1. loadable-components allows you to defer importing until the client side rendering, but you still can use it as if it was a normal component.
  2. react-codemirror2 is a react wrapper around CodeMirror

Usually if you need to use CodeMirror for a given language you need:

  1. CodeMirror itself
  2. language mode (like yaml or javascript or html)

loadable-components doesn't have a solution for multiple imports, so they recommend to wrap multiple imports into another module and import that one via loadable-components.

Here is how we did that:

import {Controlled} from 'react-codemirror2';
import 'codemirror/mode/markdown/markdown'

export default Controlled;

Then to use it:

import 'codemirror/lib/codemirror.css';
const CodeMirror = loadable(() => import('../components/code_markdown'));

<CodeMirror
    className="code-mirror"
    value={this.state.source}
    options={{
        mode: "markdown",
        theme: 'default',
        lineNumbers: true
    }}
    onBeforeChange={(editor, data, value) => {
        this.onSourceChanged(value);
    }}
    onChange={(editor, data, value) => {
    }}
/>

This article was originally published in DevToolsDaily blog