Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Describe how to use monaco Web Worker with the <Editor> #68

Closed
ppoulard opened this issue Apr 2, 2020 · 13 comments
Closed

Describe how to use monaco Web Worker with the <Editor> #68

ppoulard opened this issue Apr 2, 2020 · 13 comments

Comments

@ppoulard
Copy link

ppoulard commented Apr 2, 2020

Is your feature request related to a problem? Please describe.

In the console, I get those warnings :

backend.js:6 Could not create web worker(s). Falling back to loading web worker code in main thread, which might cause UI freezes. Please see https://github.com/Microsoft/monaco-editor#faq
backend.js:6 You must define a function MonacoEnvironment.getWorkerUrl or MonacoEnvironment.getWorker

Describe the solution you'd like

Since the UI is subject to freeze, I would rather create the expected monaco web worker

Describe alternatives you've considered

None

Additional context

I don't know how to use such worker ; it seems that monaco use it for language processing stuff. And I do have a language languages.IMonarchLanguage and conf languages.LanguageConfiguration.

Please could you add a snippet code in the doc ?

Thanks

@suren-atoyan
Copy link
Owner

Hello @ppoulard. By default, monaco tries to create webworkers to organize language processing (and not only) in other threads, rather than in the main thread to avoid blocking main (UI) thread. So, usually, when it starts to implement this behavior (it tries to create webworkers) and faces some problems during webworkers creation, it shows the error you've mentioned. To say short, probably, it couldn't manage to create webworkers in your environment; it can be related to your browser, version of the browser, maybe you manually/accidentally have disabled it. So, that's why, to understand your problem, first of all, provide me please, the parameters of your environment. It would be great if you could manage to create a reproducible code snippet.

@ppoulard
Copy link
Author

ppoulard commented Apr 6, 2020

Hello,

Here is the way I initialize it (observer() comes from MobX) :

import Editor, { monaco as Monaco } from '@monaco-editor/react';
import { editor, languages } from 'monaco-editor';

export const LaTeXEditor: FC = observer(() => {
    const [ed, setEditor] = useState<editor.IStandaloneCodeEditor>();
    return <Editor language='latex'
                   value={ store.latexContent }
                   editorDidMount={ (_, ed) => {
                       setEditor(ed);
                       ed.onDidChangeModelContent(ev => {
                           handleContentChanges(ed.getValue());
                       });
                   }}
    />
}
const latexLanguageConf: languages.LanguageConfiguration = {
    // ...
}
const latexLanguage = {
    // ...
}
(async () => {
    const monaco = await Monaco.init();
    monaco.languages.register({ id: 'latex' });
    monaco.languages.setMonarchTokensProvider('latex', latexLanguage);
    monaco.languages.setLanguageConfiguration('latex', latexLanguageConf);
})();

Do you see anything weird in that sequence ?
Thanks for your help

@suren-atoyan
Copy link
Owner

@ppoulard

I don't see anything weird from first glance but at the same time, I can't reproduce it. I would ask you to create a snippet in codesandbox, that I will be able to see the error.

@suren-atoyan
Copy link
Owner

@ppoulard

I don't see anything weird from first glance but at the same time, I can't reproduce it. I would ask you to create a snippet in codesandbox, that I will be able to see the error.

you can minimize your code for sandbox, remove mobix, use local state instead of store.

@suren-atoyan
Copy link
Owner

Hello @ppoulard. Do you still have the issue? Is it relevant?

@ppoulard
Copy link
Author

Hi @suren-atoyan , I've just upgraded to v3.3.1 and the issue still exist. I'm almost sure it is due to language registration (as shown in the code above). Unfortunately I didn't have the time to make a codesanbox sample, although it is still in my todo list !

@suren-atoyan
Copy link
Owner

@ppoulard, no worries, I just wanted to check the status. And thank you for quick response.

@sabine19
Copy link

Hey there,
any solutions yet? integrated this package in a CRA app and get the same issue.

Could not create web worker(s). Falling back to loading web worker code in main thread, which might cause UI freezes. Please see https://github.com/Microsoft/monaco-editor#faq

I'm not sure how to setup these web workers with the monaco-react package and I can not find a documentation.
My worker Url setup:

 (window as any).MonacoEnvironment = {
        getWorkerUrl(moduleId: string, label: string) {
            if (label === "yaml") {
                return "./yaml.worker.bundle.js";
            }
            return "./editor.worker.bundle.js";
        },
    };

The issue is he looks for the bundle, but cannot find them, as it doesn't get copied. But I don't know how to copy these files without a webpack config.

I would appreciate any point into the right direction! Thanks!

@ppoulard
Copy link
Author

This is still an issue for me. Some of my users are observing a strong latency in the editor.
I'm still looking for a recipe that let me bundle (with Rollup | Webpack) the language def apart, and load it in monaco worker.

@sabine19
Copy link

sabine19 commented Jan 30, 2021

I tested a lot with my CRA app to get the workers running. My findings have been that there are 2 solutions:

The first solution is to eject CRA app. (Then you have full control over your settings, but this isn't the sense of create-react-app or monaco-react). So I tried again...

My second solution uses react-app-rewired to get the possibility to override webpack settings. You have to place a config-overrides.js file in the root of the project. Then for easier configuration I install the monaco-editor-webpack-plugin.

/* config-overrides.js */
const MonacoWebpackPlugin = require("monaco-editor-webpack-plugin");

module.exports = function override(config, env) {
  config.plugins.push(
    new MonacoWebpackPlugin({
      languages: ["yaml"],
    })
  );
  return config;
};

My findings have been, that caution should be taken, which versions of the packages are installed as some of them have dependencies to specific monaco-editor versions. So my package.json looks like:

{
  "name": "monaco-editor-rewired",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@monaco-editor/react": "^4.0.9",
    "@testing-library/jest-dom": "^5.11.9",
    "@testing-library/react": "^11.2.3",
    "@testing-library/user-event": "^12.6.2",
    "@types/jest": "^26.0.20",
    "@types/node": "^12.19.15",
    "@types/react": "^16.14.2",
    "@types/react-dom": "^16.9.10",
    "monaco-editor": "^0.21.2",
    "monaco-editor-webpack-plugin": "^2.1.0",
    "react": "^17.0.1",
    "react-dom": "^17.0.1",
    "react-scripts": "4.0.1",
    "typescript": "^4.1.3",
    "web-vitals": "^0.2.4"
  },
  "scripts": {
    "start": "react-app-rewired start",
    "build": "react-app-rewired build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "devDependencies": {
    "react-app-rewired": "^2.1.8"
  }
}

If that doesn't work for you, you can update the config-overrides.js and add following line:

filename: "[name].worker.js", (default)

Therefore the worker file gets explicitly copied. Important ist that the file name, that you return in the getWorkerUrl is the same.

Hope this helps someone out there ;)

Update: newest version now fit together:
"@monaco-editor/react": "^4.0.9",
"monaco-editor": "^0.22.3",
"monaco-editor-webpack-plugin": "^3.0.0",
"react-app-rewired": "^2.1.8",

@ppoulard
Copy link
Author

Finally, I used craco to bundle the worker ; here is the code, somewhere in my app (before using the editor) :

// @ts-ignore
global.MonacoEnvironment = {
    getWorkerUrl(_: string, __: string) {
        // see monaco.webpack.config.js
        return '/static/editor.worker.bundle.js';
    },
};

the actual webpack config monaco.webpack.config.js :

const webpack = require('webpack');
const path = require('path');
const TerserPlugin = require('terser-webpack-plugin');
const mode  = process.env.NODE_ENV === 'production' ? 'production' : 'development';
console.log('Webpacking editor.worker for', mode);
module.exports = {
    mode,
    devtool: 'source-map',
    entry: {
        'editor.worker': 'monaco-editor/esm/vs/editor/editor.worker.js',
    },
    output: {
        globalObject: 'self',
        path: path.resolve(__dirname, 'public/static'),
        publicPath: '/build/',
        filename: '[name].bundle.js',
        chunkFilename: '[id].[hash].chunk.js',
    },
    node: {
        fs: 'empty',
        child_process: 'empty',
        net: 'empty',
        crypto: 'empty',
    },
    optimization: {
        noEmitOnErrors: true,
        minimize: process.env.NODE_ENV === 'production',
        minimizer: [
            new TerserPlugin({
                exclude: /eslint_bundle/,
                parallel: true,
            }),
        ],
    },
    plugins: [
        new webpack.IgnorePlugin(
          /^((fs)|(path)|(os)|(crypto)|(source-map-support))$/,
          /vs(\/|\\)language(\/|\\)typescript(\/|\\)lib/,
        ),
    ],
    resolve: {
        extensions: ['.tsx', '.ts', '.js'],
        alias: {
            vscode: 'monaco-languageclient/lib/vscode-compatibility',
        },
    },
};

the craco conf file craco.config.js:

module.exports = {
    webpack: {
        alias: {
            vscode: 'monaco-languageclient/lib/vscode-compatibility'
        }
    }
};

and some scripts added to package.json :

  "scripts": {
    "build:monaco-worker": "webpack --config monaco.webpack.config.js",
    "prebuild": "npm run lint && npm run build:monaco-worker",
  }

and of course CRA scripts are replaced by craco

@ppoulard
Copy link
Author

@suren-atoyan
Copy link
Owner

I am closing this due to inactivity, feel free to re-open it

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants