/monaco-languageclient

NPM module to connect Monaco editor with language servers

Primary LanguageTypeScriptMIT LicenseMIT

Monaco Language Client & VSCode WebSocket Json RPC

Gitpod - Code Now PRs Welcome monaco-languageclient NPM Version NPM Download

Repository for NPM module to connect Monaco editor with language servers and NPM module which implements communication between a jsonrpc client and server over WebSocket.

Click here for a detail explanation how to connect the Monaco editor to your language server.

Getting started

On your local machine you can prepare your dev environment as follows. At first it is advised to build everything. Or, use a fresh dev environment in Gitpod by pressing the code now badge above. Locally, from a terminal do:

git clone https://github.com/TypeFox/monaco-languageclient.git
cd monaco-languageclient
npm i
# Cleans-up, compiles and builds everything
npm run build

Vite dev server

Start the Vite dev server. It serves all client code at localhost. You can go to the index.html and navigate to all client examples from there. You can edit the client example code directly (TypeScript) and Vite ensures it automatically made available:

npm run dev

As this is a npm workspace the main package.json contains script entries applicable to the whole workspace like watch, build and lint, but it also contains shortcuts for launching scripts from the childe packages like npm run build:examples.

If you want to change the libries and see this reflected directly, then you need to run the watch command that compiles all TypeScript files form both libraries and the examples:

npm run watch

Using monaco-languageclient

NEW with v7: Treemended monaco-editor

Since version 2 (see Important Project Changes) of this library we rely on @codingame/monaco-vscode-api to supply the vscode API. It evolved substantially since then and thesedays allows to use many vscode only services with monaco-editor.

Earlier in 2023 we started to treemend an existing monaco-editor dependency via a postinstall script. This adds back monaco-editor code that was removed during bundling/threeshaking (treemending). See the detailed explanation here. But, this introduced multiple problems.

Overrides instructions

With v7 we decided to use readily treemended version of monaco-editor called @codingame/monaco-editor-treemended, but this requires to add overrides (npm/pnpm) and resolutions (yarn) in your project. Setting these ensures that all dependencies to monaco-editor and vscode are aligned:

  "overrides": {
    "monaco-editor": "npm:@codingame/monaco-editor-treemended@>=1.85.5 <1.86.0",
    "vscode": "npm:@codingame/monaco-vscode-api@>=1.85.5 <1.86.0"
  },
  "resolutions": {
    "monaco-editor": "npm:@codingame/monaco-editor-treemended@>=1.85.5 <1.86.0",
    "vscode": "npm:@codingame/monaco-vscode-api@>=1.85.5 <1.86.0"
  }

In the following table you can see the effect when using npm list monaco-editor (here the angular client example was used to demonstrate it):

No overrides With overrides
No overrides With overrides

With overrides or resolutions configured any child depndencies with a another monaco-editor version will chnaged to the one you enforce.

This means some extra-configuration work, but removes the need for any postinstall scripts which lead to multiple package manager problems. It is now also very clear what is used and needed. Please see Monaco-editor / @codingame/monaco-vscode-api compatibility table for a complete overview.

Using services and extra packages from @codingame/monaco-vscode-api

The bespoke projects not only supplies the api, but it provides 100+ packages with additional services, default extensions and language packs. By default when initalizing monaco-languageclient via the required initServices the following services are always loaded:

  • languages and model services (always added by monaco-languagclient)
  • layout, environment, extension, files and quickAccess (always added by monaco-vscode-api)

Please check the following link for information about all services supplied by @codingame/monaco-vscode-api.

Please check our examples in the examples overview chapter as they demonstrate the usage (jump-start: python client for services and default extension usage or Langium Statemachine / Locale Loader)

textmate and monarch

If you use the textmate or theme services you are able to load textmate based grammars and theme definitions from vscode:

import getThemeServiceOverride from '@codingame/monaco-vscode-theme-service-override';
import getTextmateServiceOverride from '@codingame/monaco-vscode-textmate-service-override';

Once you those services you can no longer make use of monarch based grammars and themes.

Examples Overview

There are a couple of different examples that demonstrate how the monaco-languageclient can be used.

Main Examples

Important: Apart from the json-server and python-server process all other will be server by the Vite dev server. Some examples share common code to reduce the amount of redundant code.

Verification Examples

  • The webpack verification example located in ./packages/verify/webpack demonstrates how bundling can be achieved with webpack. You find the configuration here: webpack.config.js.

  • The vite verification example located in ./packages/verify/vite demonstrates how bundling can be achieved with vite. There is no configuration required.

Pure bundler verification

  • ./packages/verify/pnpm is not part of the npm workspace. It allows to test whether pnpm install works as expected and it allows to test @codingame/monaco-vscode-api treemending via pnpm run test:treemending.
  • ./packages/verify/yarn is not part of the npm workspace. It allows to test whether yarn install works as expected and it allows to test @codingame/monaco-vscode-api treemending via yarn run test:treemending.

Example usage

Server processes

JSON Language Server

For the json-client, react-client or the client-webpack examples you need to ensure the json-server example is running:

# start the express server with the language server running in the same process.
npm run start:example:server:json
Pyright Language Server

For the python-client example you need to ensure the python-server example is running:

# start the express server with the language server running as external node process.
npm run start:example:server:python
Groovy Language Server

For the groovy-client example you need to ensure the groovy-server example is running:

Preferred option

Use docker-compose which does not require any manual setup (Java/Gradle). From the project root run docker-compose -f ./packages/examples/resources/groovy/docker-compose.yml up -d. First start up will take longer as the container is built. Use docker-compose -f ./packages/examples/resources/groovy/docker-compose.yml down to stop it.

Secondary option

Preperation: In another directory run (Requires Gradle 7 and OpenJDK 17):

git clone https://github.com/GroovyLanguageServer/groovy-language-server
./gradlew build

Afterwards copy the jar file from from groovy-language-server/build/libs/groovy-language-server-all.jar to packages/examples/resources/external/groovy

# start the express server with the language server running as external Java process.
npm run start:example:server:groovy

Verification Example Servers

If you want to reach the verification examples from the vite dev server index page you need to run the following additional http-servers beforehand (this is also indicated on the page itself):

# Serve the webpack verification example on http://localhost:8081
npm run start:verify:webpack
# Serve the vite verification example on http://localhost:8082
npm run start:verify:vite

VSCode integration

You can as well run vscode tasks to start and debug the server in different modes and the client.

Featured projects

Troubleshooting

General

Again, if you use monaco-languageclient make sure you define matching Overrides instructions in your local project to override any mismatching monaco-editor or vscode versions with you dependency tree.

Ensure monaco-editor, vscode and monaco-languageclient are imported before you do any monaco-editor or vscode-api intialization or start using it. Please check the our python language client example to see how it should be done.

Dependency issues: monaco-editor / @codingame/monaco-editor-treemended

It is recommended to study this chapter first: NEW with v7: Treemended monaco-editor. If you have mutiple, possibly hundreds of compile errors resulting from missing functions deep in monaco-editor or vscode then it is very likely your package-lock.json or node_modules are dirty. Remove both and do a fresh npm install. Always npm list monaco-editor is very useful. If you see different or errornous versions, then this is an indicator something is wrong.

Current observation is: When using npm overrides upgrading them seems to be problematic. Best practices seems to be to remove package-lock.json or node_modules and do a full re-installation with npm i afterwards.

Volta

There are Volta instructions in the package.json files. When you have Volta available it will ensure the exactly specified node and npm versions are used.

Vite dev server troubleshooting

When you are using vite for development please be aware of this recommendation.

If you see the problem Assertion failed (There is already an extension with this id) you likely have mismatching dependencies defined for monaco-editor or @codingame/monaco-vscode-api. You should fix this or add the following entry to your vite config:

resolve: {
  dedupe: ['monaco-editor', 'vscode']
}

Serve all files required

@codingame/monaco-vscode-api requires json and other files to be served. In your project's web-server configuration you have to ensure you don't prevent this.

Bad Polyfills

buffer

If you see an error similar to the one below:

Uncaught Error: Unexpected non—whitespace character after JSON at position 2

SyntaxError: Unexpected non—whitespace character after JSON at position 2
    at JSON. parse («anonymous>)

It is very likely you have an old version of buffer interfering (see #538 and #546). You can enforce a current version by adding a resolution as shown below to your projects' package.json.

"resolutions": {
  "buffer": "~6.0.3",
}

monaco-editor-core

Originally monaco-languageclient was dependent on monaco-editor-core, but we changed this with version 1.0.0. If your project requires to use monaco-editor-core and you want to stay compatible with 1.0.0 of monaco-languageclient you can install monaco-editor-core as monaco-editor:

npm install monaco-editor@npm:monaco-editor-core

Or if you are using Webpack you can alternatively add this alias to its config:

resolve: {
  alias: {
    // This doesn't pull any languages into bundles and works as monaco-editor-core was installed
    'monaco-editor$': 'monaco-editor-core$',
    'monaco-editor/': 'monaco-editor-core/',
  }
}

If you use monaco-editor as dependency, but only want to have the content of monaco-editor-core than just only import:

import * as monaco from 'monaco-editor/esm/vs/editor/edcore.main.js';

@monaco-editor/react

Add the monaco-editor import at the top of your editor component file source:

import * as monaco from "monaco-editor";
import { loader } from "@monaco-editor/react";

loader.config({ monaco });

pnpm

If you use pnpm, you have to add vscode / @codingame/monaco-vscode-api as direct dependency (see the following table), otherwise the installation will fail.

"vscode": "npm:@codingame/monaco-vscode-api@>=1.85.5 <1.86.0"

Monaco-editor / @codingame/monaco-vscode-api compatibility table

This information has been moved here.

Important Project Changes

This information has been moved here.

Changelogs

CHANGELOG for monaco-languageclient is found here

CHANGELOG for vscode-ws-jsonrpc is found here

Licenses

  • monaco-languageclient: MIT
  • vscode-ws-jsonrpc: MIT