I am struggling a bit to find a minimal runnable example that just runs from the CDN, as opposed to the existing in-tree examples which mostly use local servers.
After Googling a bit I found https://jsfiddle.net/developit/bwgkr6uq/ which just works with unpkg.com, and so I mostly just adapted it to cdnjs, here is a single working HTML file:
index.html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Monaco editor</title>
<link rel="stylesheet" data-name="vs/editor/editor.main" href="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.20.0/min/vs/editor/editor.main.min.css">
</head>
<body>
<div id="container" style="height:400px;border:1px solid black;"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.26.1/min/vs/loader.min.js"></script>
<script>
// require is provided by loader.min.js.
require.config({ paths: { 'vs': 'https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.26.1/min/vs' }});
require(["vs/editor/editor.main"], () => {
monaco.editor.create(document.getElementById('container'), {
value: `function x() {
console.log("Hello world!");
}`,
language: 'javascript',
theme: 'vs-dark',
});
});
</script>
</body>
</html>
Live: http://cirosantilli.com/web-cheat/monaco-editor.html
https://jsfiddle.net/developit/bwgkr6uq was also setting window.MonacoEnvironment
to some hacky looking stuff, but things now seem to work without it.
Using less loader magic
Inspired from: how to use monaco editor without node.js
less-loader.html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Monaco editor no loader</title>
<link rel="stylesheet" data-name="vs/editor/editor.main" href="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.26.1/min/vs/editor/editor.main.min.css">
</head>
<body>
<div id="container" style="height:400px;border:1px solid black;"></div>
<script>var require = { paths: { 'vs': 'https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.26.1/min/vs' } }</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.26.1/min/vs/loader.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.26.1/min/vs/editor/editor.main.nls.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.26.1/min/vs/editor/editor.main.js"></script>
<script>
monaco.editor.create(document.getElementById('container'), {
value: `function x() {
console.log("Hello world!");
}`,
language: 'javascript',
theme: 'vs-dark',
});
</script>
</body>
</html>
Live: http://cirosantilli.com/web-cheat/monaco-editor-no-loader.html
Do it without the loader
Dedicated question: how to use monaco editor without node.js
I don't know how to do it entirely without the ugly loader thing.
By looking at the Network inspector tab in Chrome, we see that the following are loaded when opening the above HTML:
so we might try:
no-loader.html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Monaco editor no loader TODO</title>
<link rel="stylesheet" data-name="vs/editor/editor.main" href="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.20.0/min/vs/editor/editor.main.min.css">
</head>
<body>
<div id="container" style="height:400px;border:1px solid black;"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.20.0/min/vs/editor/editor.main.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.20.0/min/vs/editor/editor.main.nls.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.20.0/min/vs/language/typescript/tsMode.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.20.0/min/vs/basic-languages/javascript/javascript.js"></script>
<script>
let editor = monaco.editor.create(document.getElementById('container'), {
value: `function x() {
console.log("Hello world!");
}`,
language: 'javascript',
theme: 'vs-dark',
});
</script>
</body>
</html>
but that fails because all .js files rely on a global define(
function being present, which is defined in the loader.
If we add the loader back to the above, the editor seems to work, but a bunch of errors show on the JavaScript console, as it appears that some of those files are trying to dynamically load other files in the local filesystem.
Webpack integration
For anything remotely serious, this will be the way to go.
Since their library distribution is so complex, they have this Webpack plugin to help: https://github.com/microsoft/monaco-editor-webpack-plugin
Minimal example that seems to work fine, just note that there is a JavaScript error "Unexpected usage at EditorSimpleWorker.loadForeignModule" when running from file://
: https://github.com/microsoft/monaco-editor-webpack-plugin/issues/157 so presumably the loader is still used for dynamic resources. Build and view:
npm install
npm run build
python3 -m http.server
and then visit http://localhost:8080
package.json
{
"name": "monaco-editor-webpack-plugin-demo",
"version": "1.0.0",
"private": true,
"dependencies": {
"css-loader": "5.2.4",
"file-loader": "^6.2.0",
"monaco-editor": "0.26.1",
"monaco-editor-webpack-plugin": "4.1.1",
"style-loader": "2.0.0",
"webpack": "5.36.1",
"webpack-cli": "4.6.0"
},
"scripts": {
"build": "webpack",
"start": "webpack serve --open --config webpack.config.js"
}
}
index.js
import * as monaco from 'monaco-editor'
// or import * as monaco from 'monaco-editor/esm/vs/editor/editor.api';
// if shipping only a subset of the features & languages is desired
monaco.editor.create(document.getElementById('container'), {
value: `function x() {
console.log("Hello world!");
}`,
language: 'javascript',
theme: 'vs-dark',
});
index.html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Monaco editor webpack plugin</title>
</head>
<body>
<div id="container" style="height:400px;border:1px solid black;"></div>
<script src="dist/index.js"></script>
</body>
</html>
This example could also be somewhat extracted from their upstream test under: https://github.com/microsoft/monaco-editor-webpack-plugin/tree/2459e4a023f9026ae5796a6e92f584c5d38e583e/test That test uses the package.json
from the package itself however, and you have to extract some devDependencies
from their into your own package.json
, since they are not really devDependencies
. Full run with:
git clone https://github.com/microsoft/monaco-editor-webpack-plugin
cd monaco-editor-webpack-plugin
npm install
npm run prepublishOnly
npm test
chromium test/dist/index.html
A mode: 'production'
build is extremely slow, about 50 seconds on my Lenovo P51.
'development'
is much faster, only 5s, so the problem is presumably the optimization of all the assets.
The plugin offers options to select a subset of features to speed things up and make the bundle smaller, some I've tried:
new MonacoWebpackPlugin({
languages: ['javascript', 'typescript'],
})
Might save a few seconds, not very noticeable. As mentioned in the docs, typescript
is mandatory when using javascript
.
languages: [],
: 22s
languages: [], features: [],
: also 22s, features: []
made no difference
Get it to work with Next.js
Just when I thought the fight was over... but no! The above webpack setup did not work with Next.js 11, was failing as asked at: Monaco editor with nextjs but I managed to work around by using: https://github.com/suren-atoyan/monaco-react
Specifically, you probably want https://github.com/microsoft/monaco-editor/blob/main/docs/integrate-amd-cross.md
<script type="text/javascript" src="https://unpkg.com/monaco-editor@latest/min/vs/loader.js"></script>
<script>
require.config({ paths: { 'vs': 'https://unpkg.com/monaco-editor@latest/min/vs' }});
// Before loading vs/editor/editor.main, define a global MonacoEnvironment that overwrites
// the default worker url location (used when creating WebWorkers). The problem here is that
// HTML5 does not allow cross-domain web workers, so we need to proxy the instantiation of
// a web worker through a same-domain script
window.MonacoEnvironment = {
getWorkerUrl: function(workerId, label) {
return `data:text/javascript;charset=utf-8,${encodeURIComponent(`
self.MonacoEnvironment = {
baseUrl: 'https://unpkg.com/monaco-editor@latest/min/'
};
importScripts('https://unpkg.com/monaco-editor@latest/min/vs/base/worker/workerMain.js');`
)}`;
}
};
require(["vs/editor/editor.main"], function () {
monaco.editor.create(document.querySelector('.monaco-editor-container'), {
value: `function x() {
console.log("Hello world!");
}`,
language: 'javascript',
theme: 'vs-dark',
});
});
</script>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With