Every product with a “JSON config” screen eventually needs a code editor in the browser, and that is exactly where teams make a decision they will live with for years. Monaco (46,570 stars) powers VS Code and brings a full IDE to the web; CodeMirror (7,822 stars in its development repo) is the modular, tiny core behind countless note apps and data tools; Ace (27,144 stars) is the battle-scarred veteran from the Cloud9 era. They are not interchangeable: Monaco ships megabytes of features, CodeMirror ships a philosophy of small composable packages, and Ace ships simplicity with a dated architecture. Choosing wrong means rebuilding your editor surface two releases later.

Quick Verdict: Which Browser Code Editor Should You Use?

If you want an IDE-grade experience — completion, go-to-definition, multi-cursor editing, and 40+ languages — with zero assembly, choose Monaco. It is the heaviest option and the only one that needs worker configuration, but it is the closest thing to VS Code in a browser. If you are building a custom editor into an existing product with strict bundle budgets, choose CodeMirror 6 — it is the modular choice, where you compose @codemirror/state, @codemirror/view, and language packages and pay for exactly what you use. If you need a simple, dependency-free editor that “just works” and you already know its API, Ace is still fine in 2026 — just accept that its extension model predates modern JavaScript tooling. For new projects, the realistic decision is Monaco vs CodeMirror.

Head-to-Head: Feature Comparison

FeatureMonacoCodeMirror 6Ace
GitHub stars (Aug 2026)46,5707,822 (dev repo)27,144
Last push2026-08-182026-04-152026-08-13
First released2015 (VS Code)2018 (v6 rewrite; project since 2007)2010 (Cloud9)
ArchitectureMonolithic, worker-basedModular npm packages, no workersMonolithic, single file builds
Min+gzip size~2.9 MB full / ~800 kB corePay-for-what-you-use (core ~200 kB)~350 kB core
Language support40+ bundledCommunity language packages120+ modes (many stale)
Syntax highlighting engineMonarch tokenizer + TextMate via addonLezer parser systemCustom highlight rules
Web workersRequired (language services)None neededOptional
Mobile / touch supportNo (README states unsupported)YesPartial
LicenseMITMITBSD-3-Clause

Monaco’s star count reflects its VS Code pedigree more than its web footprint; CodeMirror’s dev repo star count understates a project that is embedded in hundreds of thousands of applications.

Decision Matrix: Match the Editor to Your Use Case

Use CaseRecommended EditorWhy
Admin panel needs a JSON/YAML editor with validationMonacoJSON schema validation and error squiggles work out of the box
Notebook/docs app, editor is one component among manyCodeMirrorTiny core, tree-shakable, plays well with React/Svelte/vue
API playground / REPL-style UIMonacoCompletion + hover + inline errors feel like an IDE
Strict bundle budget, single syntax highlight neededCodeMirror~50 kB with one language package
Embedding a read-only code display with line numbersCodeMirrorEditorState.readOnly is a first-class extension
Legacy product already on Ace, no budget to migrateAceStable API; migration cost exceeds benefit
Mobile-first editor surfaceCodeMirrorOnly one of the three with real touch support

Monaco: The IDE in a Browser

Monaco is generated directly from VS Code’s sources, which is both its superpower and its tax. You get the full editor experience — IntelliSense-style completion, hover documentation, go-to-definition, find-and-replace with regex, multi-cursor, minimap, and 40+ bundled languages — by writing almost nothing:

1
2
3
4
5
6
import * as monaco from 'monaco-editor';

monaco.editor.create(document.getElementById('container'), {
  value: ['function x() {', '\tconsole.log("Hello world!");', '}'].join('\n'),
  language: 'javascript'
});

The cost is architectural. Monaco is organized around models (the document), URIs (every model has one), providers (completion and hover services), and disposables (everything returns a .dispose()), and its language services run in web workers — which means you must configure a worker bundler (the official monaco-editor-webpack-plugin or equivalent Vite/Vitest setup) or nothing will work at runtime. The official README is blunt about limits: no mobile browser support, no TextMate grammars without an oniguruma addon, and no VS Code extensions in the browser. If your app can afford the bundle and the worker plumbing, nothing else comes close.

CodeMirror: The Modular Small Core

CodeMirror 6 is a complete rewrite of the classic CodeMirror 5, and its defining trait is modularity: the editor core is a composition of small packages — @codemirror/state, @codemirror/view, @codemirror/language, plus a language package per syntax — so your bundle contains only what you actually render. The official demo shows the minimal setup:

1
2
3
4
5
6
7
import {EditorView, basicSetup} from "codemirror";
import {html} from "@codemirror/lang-html";

const editor = new EditorView({
  extensions: [basicSetup, html()],
  parent: document.body,
});

Syntax highlighting uses the Lezer parser system, a real incremental parser rather than a tokenizer, which gives you proper nested-tree highlighting and error detection. Everything is an extension: read-only mode, line numbers, search, autocompletion, linting, and even your own custom UI inside the editor gutter are all extensions array entries. CodeMirror works without workers, supports touch and mobile reasonably well, and integrates cleanly with React through a thin wrapper component. The trade-off is assembly: you configure what Monaco gives you free, and the package ecosystem (language packs, addons) varies in quality across the 100+ community language packages.

Ace: The Veteran That Still Works

Ace began life as the editor inside Cloud9 and shipped in the era of script-tag builds, and it still carries that DNA: one ace.js file, a global ace object, and a simple imperative API:

1
2
3
4
5
6
7
var editor = ace.edit("editor");
editor.setTheme("ace/theme/monokai");
editor.session.setMode("ace/mode/javascript");

// later, when the component unmounts:
editor.destroy();
editor.container.remove();

It bundles a huge catalog of language modes and themes, supports find/replace, snippets, and autocompletion, and its API has been stable for over a decade — the definition of boring reliability. The downsides are structural: modes are regex-based highlight rules rather than real parsers, many of the 120+ modes are unmaintained, the build system is a custom dryice script, and the architecture predates modern bundlers, which makes tree-shaking impossible. Teams running Ace in production today usually keep it for the same reason teams keep jQuery: it works, everyone knows it, and the migration cost is not justified by the features gained.

Pitfalls: What Nobody Tells You About Browser Code Editors

  1. Monaco’s workers are not optional. The most common “my editor shows a blank box” issue is a missing worker configuration. If you use Vite, import the workers explicitly or use monaco-editor’s ESM entry with MonacoEnvironment.getWorker wired up; on webpack, the official plugin does it. Budget a day for this integration, not an hour.
  2. Bundle size is the hidden migration cost. Monaco’s full ESM build is multi-megabyte; CodeMirror’s philosophy is the opposite. Measure with a bundle analyzer before committing — and remember that @codemirror/lang-* packages pull in their own parser dependencies, so five languages cost more than five times one.
  3. Memory leaks from missing disposables. Monaco models, editors, and providers all implement .dispose(). In a SPA where users open many editor instances (per-row editors in a data grid, for example), forgetting to dispose leaks entire documents. Keep a single reusable model per document URI and dispose the editor on unmount.
  4. Read-only ≠ non-interactive. If your goal is pretty syntax-highlighted code (config previews, API responses), a read-only CodeMirror instance with EditorState.readOnly is lighter than a full editor — but it still processes input events, so disable it fully or use the editor’s display-only mode to avoid focus flicker.
  5. Highlighting engines differ in correctness. Monaco’s Monarch tokenizer and Ace’s regex modes produce approximate coloring; Lezer produces parse-tree-accurate highlighting. If you display code that users will copy into real editors, mismatched highlighting is a trust issue — the same lesson as in our syntax highlighting libraries comparison.
  6. Virtual scrolling is already solved inside these editors. Both Monaco and CodeMirror render only visible lines; if you are embedding thousands of lines in a different UI component, borrow the pattern from our virtual scroll libraries comparison rather than rendering everything.
  7. “Editor” scope creep is real. The moment you need diff views, minimaps, or multi-file tabs, you are rebuilding VS Code. For multi-file editing experiences, consider a full code playground platform instead — we compare the self-hosted options in our code playgrounds guide.

FAQ

What is the difference between Monaco, CodeMirror, and Ace?

Monaco is the VS Code editor extracted for web use — IDE features, heavy, worker-based. CodeMirror is a modular, lightweight editor where you compose small packages (the current CodeMirror 6 is a full rewrite). Ace is the legacy Cloud9 editor: single-file, simple API, huge mode catalog, minimal maintenance activity.

Which browser code editor has the most GitHub stars?

Monaco leads with ~46,570 stars, followed by Ace at ~27,144 and CodeMirror’s development repo at ~7,822. CodeMirror’s count is misleading — its npm packages power far more applications than its star total suggests.

Does Monaco Editor work on mobile browsers?

No. The official Monaco README states mobile browsers are not supported. For touch-first interfaces, CodeMirror is the only one of the three with practical mobile support.

Is CodeMirror 6 worth migrating to from CodeMirror 5?

Usually yes: CodeMirror 6 has a real parser (Lezer), a clean extension system, and is actively maintained, while CodeMirror 5 is in maintenance-only mode. The migration is a rewrite of editor setup code, not of your app logic, and community packages exist for the most common features.

Can I use Monaco Editor with React?

Yes — either through the community @monaco-editor/react wrapper or by creating editors manually in a useEffect with proper disposal in the cleanup function. The same pattern applies to CodeMirror and Ace: create on mount, destroy on unmount, and keep the editor instance in a ref.

Which code editor is best for a JSON configuration screen?

Monaco, because its JSON language service provides schema-based validation, completion, and hover documentation out of the box — a genuine differentiator for admin panels. CodeMirror is the lighter alternative if bundle size matters more than schema validation.


💰 想测试你的市场判断力?我用 Polymarket 做预测市场交易——这是全球最大的预测市场平台,从大选结果到技术监管时间线,什么都可以押注。和赌博不同,这是真正的信息市场:你懂的信息越多,胜率越高。我靠预测技术相关事件的走向已经赚了不少。用我的邀请链接注册:Polymarket.com