monaco-editor icon indicating copy to clipboard operation
monaco-editor copied to clipboard

[Feature Request] ESM build that can be loaded from CDNs

Open hatemhosny opened this issue 1 year ago • 4 comments

Context

  • [X] This issue is not a bug report. (please use a different template for reporting a bug)
  • [X] This issue is not a duplicate of an existing issue. (please use the search to find existing issues)

Description

This is a suggestion to provide an ESM build that can be loaded from CDN.

Currently, the recommended way is to build the editor with a bundler and host it with the page that needs to load it. In addition it requires the user to configure the MonacoEnvironment.getWorkerUrl

This is a bit cumbersome and exposes implementation details that the end-user does not need to be concerned with.

The other alternative is to use the loader, that loads an AMD version, which I think should no longer be the recommended way, with ESM being used across the whole eco-system. In addition, it is prone to conflicts with other libraries and getting such errors: Error: Can only have one anonymous define call per script file

My suggestion is something like this:

<div id="container" style="height: 200px;"></div>

<script type="module">
  import { monaco } from "https://cdn.jsdelivr.net/npm/monaco-editor-esm-cdn/monaco.js";

  monaco.editor.create(document.getElementById("container"), {
    value: `function x() {\n\tconsole.log("Hello world!");\n}`,
    language: "javascript",
  });
</script>

Try in LiveCodes playground

This works by using a simple workaround that allows using web workers from a CDN.

I believe this can make using Monaco editor much simpler. If you think this way is acceptable, I can start a PR to either provide such build that can just be published with the npm package or at least add docs for using something like this.

Please see the example repo: https://github.com/hatemhosny/monaco-editor-esm-cdn

Monaco Editor Playground Link

No response

Monaco Editor Playground Code

No response

hatemhosny avatar Jul 31 '24 00:07 hatemhosny

This is not a big deal to run it through esm.sh

import * as Monaco from 'https://esm.sh/[email protected]?bundle';
import EditorWorker from 'https://esm.sh/[email protected]/esm/vs/editor/editor.worker?worker';
import JsonWorker from 'https://esm.sh/[email protected]/esm/vs/language/json/json.worker?worker';
import CssWorker from 'https://esm.sh/[email protected]/esm/vs/language/css/css.worker?worker';
import HtmlWorker from 'https://esm.sh/[email protected]/esm/vs/language/html/html.worker?worker';
import TSWorker from 'https://esm.sh/[email protected]/esm/vs/language/typescript/ts.worker?worker';

async function loadCSS() {
    const css = await fetch(`https://esm.sh/[email protected]?css`).then(response => response.text());
    const style = document.createElement('style');

    style.id = 'monaco-css';
    style.innerHTML = css;

    document.getElementById('monaco-css')?.remove();
    document.head.appendChild(style);
}

self.monaco = monaco;
self.MonacoEnvironment = {
    getWorker(_, label) {
        if (label === 'json') {
            return new JsonWorker();
        }

        if (label === 'css' || label === 'scss' || label === 'less') {
            return new CssWorker();
        }

        if (label === 'html') {
            return new HtmlWorker();
        }

        if (label === 'typescript' || label === 'javascript') {
            return TSWorker();
        }

        return new EditorWorker();
    }
};

loadCSS();

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

But yes, it's really strange that Microsoft recommends using that silly require loader instead of ESM.

kachurun avatar Jul 31 '24 19:07 kachurun

The link is dead - the weird AMD solution is still available through e.g. https://log.schemescape.com/posts/web-development/embedding-monaco-from-cdn.html

phil294 avatar Sep 25 '25 11:09 phil294

Closing as duplicate of https://github.com/microsoft/monaco-editor/issues/886

hediet avatar Sep 26 '25 10:09 hediet

@hediet This issue is not just about loading CSS as discussed #886

It is everything related to loading Monaco from a CDN (separate origin), including loading web workers.

Currently to use the ESM setup, I have to manually build monaco and place all the built files on the same origin that uses it for web workers to work.

I'm proposing loading everything as ESM from a CDN as shown in the code snippet posted above which just works in any HTML page with no build steps: (demo: https://livecodes.io/?x=id/dgzkpnfzzbq)

<div id="container" style="height: 200px;"></div>

<script type="module">
  import { monaco } from "https://cdn.jsdelivr.net/npm/monaco-editor-esm-cdn/monaco.js";

  monaco.editor.create(document.getElementById("container"), {
    value: `function x() {\n\tconsole.log("Hello world!");\n}`,
    language: "javascript",
  });
</script>

hatemhosny avatar Sep 26 '25 11:09 hatemhosny