Viteとmonaco-editorを使ってVSCodeと同じテキストエディタを作成しよう

今日はMicroSoft社のテキストエディタVSCodeで使われているmonaco-editorを紹介します。Viteと組み合わせることで今後VueやReactなどにも簡単に組み込むことが可能になります。

VSCodeはどんどん進化しており、Co Pilotも公開されてからAIで次のコードを推測して予測してくれる機能はどのテキストエディタにもかないません。

完成例はこのようになり、ユーザーがVSCodeと同じようにコードを書くことができます。

ちなみにVSCodeをブラウザ上で起動したい場合はhttps://vscode.dev/からアクセスしてコードを書くことができます。

今日紹介するmonaco editorはこちらのURLで試してみることができるので是非使ってみてください。

https://microsoft.github.io/monaco-editor/

まずはmonaco editorのGitHubリポジトリを見てみましょう。

https://github.com/microsoft/monaco-editor

このmonaco editorはオープンソースでMITライセンスになります。つまり。。。コードの商用、個人の利用に関わらず、改変でも、再配布でも、商用利用でも、有料販売でも、どんなことにでも自由に無料でつかうことができます。

Reactのコンポーネント

ちなみにReactのコンポーネントとして使いたい場合は下記のURLからどうぞ。ライブラリがあるのでそちらを使うと簡単にReactで細かい設定までできるようになります。

https://www.npmjs.com/package/@monaco-editor/react

monaco editorでできること

monaco editorはVSCodeのです。つまりVSCodeのテキストエディタの部分と同じことができるようになります。

  • キーボードのショートカットが使える(コメントアウト、カット、ペーストなど+)
  • 78言語のシンタックスをハイライトしてくれる
  • 元コードと比較して違う部分をハイライトしてくれる機能が使える
  • 次のコードを予測して提案してくれる

なぜVite

monaco editorはESMとAMDの2つのモジュールのバージョンが使えます。今回はESMの方を使います。

どちらにしてもWeb packというバンドラーが入っているのでそれを使わないといけません。

良いことにViteではビルドインのWeb packのworkerのサポートができます。Viteは軽量かつ完成度の高いビルドツールとして標準化されてきているので是非、使うことをお勧めします。

Viteのプロジェクトを作成

では、monaco editorをインストールする前にViteでJavaScriptのプロジェクトを作成していきましょう。

詳しいViteの使い方はこちらの記事を参照してください。

npm create vite@latest


✔ Project name: … monaco-app
✔ Select a framework: › Vanilla
✔ Select a variant: › JavaScript

Scaffolding project in /home/dan/Documents/public/monaco-app...

Done. Now run:

  cd monaco-app
  npm install
  npm run dev

monaco editorをインストール

では下記のコマンドでmonaco editorをインストールしてみましょう。

npm install monaco-editor

では、サンプルのcounter.jsを削除してmain.jsをこのように書きます。

import './style.css'
import * as monaco from 'monaco-editor'
import editorWorker from 'monaco-editor/esm/vs/editor/editor.worker?worker'
import jsonWorker from 'monaco-editor/esm/vs/language/json/json.worker?worker'
import cssWorker from 'monaco-editor/esm/vs/language/css/css.worker?worker'
import htmlWorker from 'monaco-editor/esm/vs/language/html/html.worker?worker'
import tsWorker from 'monaco-editor/esm/vs/language/typescript/ts.worker?worker'

self.MonacoEnvironment = {
  getWorker(_, label) {
    if (label === 'json') {
      return new jsonWorker()
    }
    if (label === 'css' || label === 'scss' || label === 'less') {
      return new cssWorker()
    }
    if (label === 'html' || label === 'handlebars' || label === 'razor') {
      return new htmlWorker()
    }
    if (label === 'typescript' || label === 'javascript') {
      return new tsWorker()
    }
    return new editorWorker()
  }
}

monaco.editor.create(document.getElementById('container'), {
  value: "function hello() {\n\talert('Hello world!');\n}",
  language: 'javascript'
})

こちらのコードはGitHubのmicrosoft/monaco-editorから引用しました。

ちなみにダークカラーにしたい場合、テキストエディタをRead Onlyにしたい場合などの細かい設定は下記のようにできます。その他の例は、monaco-editorのPlay Groundで確認してください。

monaco.editor.create(document.getElementById('container'), {
  value: "function hello() {\n\talert('Hello world!');\n}", // テキストエディタの初期値
  language: 'javascript', // テキストエディタの言語
	lineNumbers: "off", // テキストエディタの行番号を表示するかどうか
	roundedSelection: true, // 選択範囲を角丸にするかどうか
	scrollBeyondLastLine: false, // テキストエディタの最後の行を超えてスクロールするかどうか
	readOnly: false, // テキストエディタを読み取り専用にするかどうか
	theme: "vs-dark", // テキストエディタのテーマ
})

次にstyles.cssを適当に書きます。

重要なのは#contianerのサイズを指定しているところだけです。

このid=contianerにmonaco editorがレンダーされるようになるからです。

:root {
  font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
  font-weight: 400;
}

#container {
  height: 100svh;
  width: 100svw;
}

body {
  margin: 0;
  min-width: 320px;
  min-height: 100svh;
}

完成したコードはGitHubで確認してください。

お疲れ様でした。