Migrating from Monaco Editor to CodeMirror (2023)

Some developers argue about the best text editors and IDEs, but what about editors for the web?

We recently migrated Monaco's Sourcegraph.com, the code editor component that powers VS Code, to CodeMirror. CodeMirror is one of the first web-based code editors that recently released a new version (CodeMirror 6) which is gaining popularity but still lags far behind Monaco for now.

Migrating from Monaco Editor to CodeMirror (1)

Monaco is a popular choice when you need to embed a code editor in a browser. It worked well enough for most of our needs, and since it was maintained by Microsoft and built into VS Code, we knew we could rely on it for the foreseeable future, so why did we change it?

TL;DR

  • Monaco offers many options out of the box, but it is very difficult to configure or reduce unneeded features.
  • Monaco documentation isn't great, so we couldn't always find out if it was possible to do what we needed to do.
  • Monaco has a global reference model, making it difficult to run multiple instances on the same page with minor configuration differences.
  • In terms of code size, Monaco made up a whopping 40% of our external dependencies.
  • CodeMirror has already been adopted by other big projects like developer tools Replit and Chrome, suggesting it's not going away anytime soon.

We're still learning about CodeMirror, but so far it's solved all of the above issues and it's been a pleasure to use. It's been the default component for our research input since May 2022 and we'll be using it a lot more in future versions of Sourcegraph!

An amazingly simple text input: our search field

As a research company, you might be wondering why we need a code editor. When you visit Google.com you will see the famous minimalism of an empty text entry on a blank page, and when you visit ithttps://sourcegraph.com/search(our public Sourcegraph instance that lets you search millions of open source repositories) probably looks more like the Google home page than a coding IDE that Monaco and CodeMirror were built for.

Migrating from Monaco Editor to CodeMirror (2)

But this bar hides many functions that you are probably used to from your IDE.

Searches get tricky, so we provide syntax highlighting to help you navigate through the different components (e.g. "lang" is highlighted because it defines a filter, and escape brackets are highlighted to indicate that it is is a matched pair).

We also need tooltips so our users can hover over the options on the right or over the components of the query they are entering to get more information and suggestions.

(Video) Migration to CodeMirror 6 in JupyterLab

Finally, we need auto-completion and error diagnosis to help developers write queries as quickly as possible and preemptively warn them before sending invalid queries.

We achieved most of that with Monaco for years, thoughmainlyIt worked, there were many small problems that we wanted to solve for years.

Defense of a paraphrase

Suggesting a paraphrase is never the easiest thing, as paraphrasing is often a tempting but wrong option. as engineer ofproduct research team, I suggested an experiment in which we should explore other options before investing more time and effort in adapting Monaco to our needs.

After following ourProcess RFCcreateRFC-637, I was able to complete a proof of concept and use CodeMirror to replace 90% of our current Monaco functionality in just two business days. I was immediately drawn to CodeMirror and knew it would be a much better option as I saw the potential to replace not only our search typing but also our dynamic notebooks and file reader.

Using CodeMirror was like playing with Lego - I had this set of bricks and felt like I could build anything I needed.

Although similar, CodeMirror turned out to be Monaco's polar opposite in many ways. Monaco offers a full IDE by default. These include a multi-line editor and a code "minimap" - an expanded view of the entire open file that allows you to more easily navigate to a specific location in the file. These are great features, but we didn't need them for our search input, and with Monaco it wasn't even obvious how to get a single-line input instead of a multi-line editor.

On the other hand, CodeMirror is more minimalist and modular. You don't get that much by default, but you can create exactly what you want by adding and configuring various components. EITHERfirst CodeMirror PROnly a few hundred lines of JavaScript and CSS changes, plus a few additional changes, were required to implement various editor options as a feature flag.

The issues we had with Monaco and how CodeMirror fixed them

Many of the issues we had with Monaco weren't inherently issues, which is why we've been using the component for so long. But together, the irritants added up. Some of the key issues we encountered with our implementation in Monaco included:

  • size: Monaco has increased the amount of JavaScript code we download to ourssearch pagea 6MB.
  • one-line editor: Unlike most IDEs, our search input is a single line input... most of the time.
  • CSS-Integration: To customize the look and feel of Monaco, we had to hard code hex color codes into our JavaScript instead of being able to use our CSS classes and variables site-wide.
  • global setting: It's cumbersome to render multiple instances of Monaco per page, each with slightly different settings.
  • marker text: There is a long-standing issue with Monaco requesting a function to enable a placeholder or default value.
  • code cleanup: We had some nasty tricks to get Monaco to do what we wanted.

If you are interested in the details, we will cover each point in detail below.

Size: Reduced JavaScript downloads by 43% on our search page

Migrating from Monaco Editor to CodeMirror (3)

Over time, this code grew to 6 MB. Even with modern browsers and advanced caching techniques, this can affect performance. Although we optimized our Monaco package to remove features we didn't use, Monaco itself alone has a total download of 2.4MB, which is 40% of all JavaScript on our search page.

Our original plan was to use CodeMirror instead of Monaco for our search box, but we're so impressed that we're replacing all instances of Monaco with CodeMirror.

(Video) Building your own code editor with Monaco = Tomasz Łakomy

By removing Monaco as a dependency, we reduced our JavaScript download to 3.4 MB—a 43% improvement with just a single dependency change.

While there are ways to further optimize Monaco's packet size, we love the fact that we don't get anything we don't need with CodeMirror.Originally, so you don't have to spend time and effort extracting parts of the library to save valuable bytes.

Switch between single-line and multi-line editing

Monaco offers a full multi-line editor by default and it's not obvious how to turn it into a single-line editor that we need for our search input. Although we figured out how to do that, noforeverYou want a single line of input. On devices with a small screen, our search input is scaled to multiple lines. In this case, we always place the search controls (e.g. turning regexp mode on or off) as well as the actual search button in a row below the input, but more importantly, the search also intelligently groups the query in such a way that The input must transition seamlessly from one line to multiple lines.

In the image below you can see how our mobile search input grows as needed to serve a long query compared to the same query in a one-line editor on our desktop website.

Migrating from Monaco Editor to CodeMirror (4)

That was hard to get right with Monaco. We had to add some custom configuration tricks, and even then it didn't work as well as we'd like. We expected this to be a challenge with CodeMirror as well, but to our surprise it worked by default.

Integration with our CSS framework

We have hundreds of websites and pages on Sourcegraph. Our CSS is organized in classes and variables, with all the colors we use defined in one place. This means our designers can easily make cosmetic tweaks or theme updates across our entire web presence with a single change.

The only exception? Monaco.

To customize the colors in Monaco, you need to define hexadecimal codes in JavaScript. Because we wrote mockups and demos of various features in HTML and CSS, we had to manually sync all changes between our global color file and Monaco.

This process was error prone and on more than one occasion resulted in errors where the Monaco configuration was not updated or updated with different colors than our global CSS.

With CodeMirror we can easily integrate our color file and now all theme updates are automatically applied on our marketing pages and in our live editor.

CodeMirror allows us to eliminate a lot of code related to color settings and also simplify it. Below is an example of our Monaco color configuration code on the left (actually there is much more to seeon here) and how much could be simplified with CodeMirror on the right.

(Video) Build a SQL Playground with Flask and Codemirror.js

Migrating from Monaco Editor to CodeMirror (5)

Global language setting x per instance

Monaco and CodeMirror handle configuration slightly differently. Monaco has a common global status for setting the language, and that language affects syntax highlighting, auto-completion, and other parts of the editor.

This is not a problem for our search page, where we only use a single instance of the editor. But in oursnotebooks, we have different blocks on the same page. However, our notebooks have different types of search blocks (e.g. we could have a single notebook with a regular search box and an icon search box).

These different blocks use slightly different configurations, but since the Monaco instances share a global state, we need to register each configuration separately with a unique language ID, even if the configuration differences are quite small.

With CodeMirror, each instance on a page is completely independent and only uses the local state for that instance, so configuring the different search blocks is much easier.

This also eliminates an entire potential class of bugs where adding a new block with slightly different settings could affect previously added blocks on the same page.

Add placeholder text

For Monaco, we were unable to display the placeholder text in our search input. It wasn't a big issue for us, but it's a great example of one of the many small, insignificant issues we had with Monaco that added up to making it finally make sense to move on. there wasan open problemabout it in the Monaco repository since 2017, and the hacky solution is to overlay elements to simulate placeholder text.

Migrating from Monaco Editor to CodeMirror (6)

clean code

There are a number of minor workarounds that were required for our Monaco implementation, but they all add up. For example, we didn't want to use standard Monaco keyboard shortcuts, such as B. Using Ctrl + F to search in the editor. There's no point in using Ctrl+F to search within a single-line input like our search box, and we had to disable thata confusing solution.

CodeMirror still allows us to add the keyboard shortcuts we want, but we don't have to disable the ones we don't need, so workarounds like this can be removed.

We can do a lot more with CodeMirror

Although this started as a project to improve our search input, we love CodeMirror so much that we've moved everywhere we've used Monaco before.

As mentioned above, we've already replaced all of our laptops with CodeMirror, but we're also starting to find new uses for it.

(Video) Styling CodeMirror v6 with Material UI | #DevLog 005

Rewriting our file viewer with CodeMirror

After completing a Sourcegraph search, you can open the relevant files and view them directly. For historical reasons, we don't use a code editor for this file viewer. It's a read-only view, so loading an entire editor for each file was pointless. At the same time, however, we need many of the same features when viewing files, including syntax highlighting, line numbers, and code navigation.

Another benefit of using a code editor for a file viewer is when viewing large files. When opening a file with thousands or millions of lines, a code editor like CodeMirror does not load or process an entire file. Instead, it intelligently displays only what's on the user's screen.

One ofCodeMirror samplesIt shows how the editor can effortlessly instantly load a document with a few million lines and show the highlight only as far as the user scrolls.

We haven't released our new file viewer yet, but we hope to see it in a future release!

The open source software business model

Outside of tech circles, it's unclear how much software worldwide depends on open-source projects like CodeMirror, or how difficult it is to make these projects sustainable. Often these are passion projects that are mainly handled by a single person who has another full-time job.

If these caregivers step aside, the consequences could be enormous and difficult to predict. Large commercial projects may not even depend on them directly, but on another (commercial) project that depends on another, and so on, until you find the open-source dependency that precariously underpins everything, as illustrated inXKCD2347.

Migrating from Monaco Editor to CodeMirror (7)

The MIT license used by many open source projects, including CodeMirror, is very permissive and allows open source code to be used in commercial projects as well. But CodeMirror is one of several projects actively positioning itself to remind companies to give back to the ecosystem they depend on and benefit from.

CodeMirror explains on its website:

If you use CodeMirror commercially, there is a social (but not legal) expectation that you help fund maintenance.

Sourcegraph has followed this societal expectation and has made monthly donations to CodeMirror since it began using CodeMirror. We also sponsor your facilityobrigado.dev.

Comment on this post on our Discord

(Video) CodeMirror Tutorial | Create A Fully Functional Text Editor


Special thanks toTracy Johnson, miFabiana Castellanosfor the help with this post.

More posts like this

  • Overhaul of the design approach of the Zig programming language
  • A developer's view of developer productivity

Videos

1. How to setup CodeMirror - step by step guide | CodeMirror #01
(Yusuf Shakeel)
2. How to Code a Vim Tutor with React and CodeMirror
(Suboptimal Engineer)
3. How To Build CodePen With React
(Web Dev Simplified)
4. How to build a Markdown editor using Electron, ReactJS, Vite, CodeMirror, and Remark
(devaslife)
5. Introduction to TypeScript with Josh Goldberg
(Codecademy)
6. React Typescript Simple Code Editor
(Fullyworld Web Tutorials)
Top Articles
Latest Posts
Article information

Author: Arielle Torp

Last Updated: 07/11/2023

Views: 5881

Rating: 4 / 5 (41 voted)

Reviews: 88% of readers found this page helpful

Author information

Name: Arielle Torp

Birthday: 1997-09-20

Address: 87313 Erdman Vista, North Dustinborough, WA 37563

Phone: +97216742823598

Job: Central Technology Officer

Hobby: Taekwondo, Macrame, Foreign language learning, Kite flying, Cooking, Skiing, Computer programming

Introduction: My name is Arielle Torp, I am a comfortable, kind, zealous, lovely, jolly, colorful, adventurous person who loves writing and wants to share my knowledge and understanding with you.