remcohaszing/monaco-yaml

Cannot integrate in React App

mleitenbauer opened this issue · 7 comments

So I'm using the monaco yaml plugin in combination with for my react web app.

I integrated it as described in the manual. Everything looks good in the development build. The workers are working normally.
As soon as I try to deploy my app for production, and I open the editor it can't load the web workers correctly.
It always tells me it could not load the web workers and following that an unexpected usage as in. #1385

Can you tell me if I have any misconfiguration or am I missing something ?

(to Mention i use seperate instances of monaco editor but always destroy them before launching a new one)

I'm also using react-rewired to override the webpack config, as you described in Issue #1385

These are my worker inputs.
// eslint-disable-next-line import YamlWorker from 'worker-loader!monaco-yaml/yaml.worker'; // eslint-disable-next-line import EditorWorker from 'worker-loader!monaco-editor/esm/vs/editor/editor.worker'

window.MonacoEnvironment = { getWorker(workerId: string, label: string): string { if (label === 'yaml') { return new YamlWorker(); } return new EditorWorker(); },

new MonacoWebpackPlugin({ languages: ['yaml'], customLanguages: [ { label: 'yaml', entry: 'monaco-yaml', worker: { id: 'monaco-yaml/yamlWorker', entry: 'monaco-yaml/yaml.worker', }, }, ], })

Any ideas how I can fix this issue ? As i mentioned it only causes problems in production so I guess there is something wrong with my config.

Could you properly format your markdown? You reference non-existent issues, did you mean to reference external issues? Just use the full URL then. Also your code blocks are unreadable like this, please use actual code blocks, like this:

```js

```

I suggest to follow a markdown toturial to learn how to format content on GitHub, i.e. the commonmark tutorial.

Yes, sorry I was in a rush didnt expect the fast response. So here is the full formatted code.

config-overrides.js

const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin');
const path = require('path');

module.exports = function override(config, env) {
	const isEnvProduction = env === 'production';
	config.mode = 'production'
	config.output = {
		filename: isEnvProduction
		? 'static/js/[name].[contenthash:8].js'
		: 'static/js/[name].bundle.js'
	};
	config.node = {
		__dirname: true
	};
	config.plugins.push(
		new MonacoWebpackPlugin({
			customLanguages: [
				{
					label: 'yaml',
					entry: 'monaco-yaml',
					worker: {
						id: 'monaco-yaml/yamlWorker',
						entry: 'monaco-yaml/yaml.worker.js',
					},
				},
			],
		})
	);
	return config;
};

MonacoEditor.js

// eslint-disable-next-line
import 'monaco-editor';
// Monaco
import * as monaco from 'monaco-editor';

import { editor } from 'monaco-editor/esm/vs/editor/editor.api';

// eslint-disable-next-line
import YamlWorker from 'worker-loader!monaco-yaml/yaml.worker.js';
// eslint-disable-next-line
import EditorWorker from 'worker-loader!monaco-editor/esm/vs/editor/editor.worker.js';
import { setDiagnosticsOptions } from 'monaco-yaml';
// eslint-disable-next-line
self.MonacoEnvironment = {
  getWorker(workerId, label): string {
	  if (label === 'yaml') {
		  return new YamlWorker();
	  }
	  return new EditorWorker();
  },
};
const tempEditor = editor.create(document.getElementById(`editor-${id}`), {
  language: 'yaml',
  model: editor.createModel(yamlFile, 'yaml'),
  readOnly,
  schema,
  automaticLayout: true,
});

These are my currently used versions

    "monaco-editor": "^0.34.1",
    "monaco-editor-webpack-plugin": "^7.0.1",
    "monaco-yaml": "^4.0.3",

The Issue I referenced was meant to be this one:

microsoft/monaco-editor#1385

I always get these errors in production, while in development everything works perfectly.

image

image

What is also pretty interesting, as I said above I have several tabs in my react app, which load the monaco yaml editor. Sometimes it works, but most of the time the errors shut down the editor.

You seem to be combining two conflicting solutions. One using MonacoEnvironment and worker-loader, and one using monaco-editor-webpack-plugin. You should remove one of them.

Also you mentioned “to Mention I use seperate instances of monaco editor but always destroy them before launching a new one”.

What do you mean by that? Could you share the code?

Alright, which solution would you recommend for my case ?

Yes it's a bit tricky to explain:
We have several Tabs in our Application, which are kept alive by React-Activation.
Once I reload a tab, I use the following code to reevaluate the problems list.

	useActivate(() => {
		if(editorItem && typeof editorItem.getModel === 'function') {
			const resource = editorItem.getModel().uri;
			if(resource) {
				const markers = editor.getModelMarkers({resource});
				handleEditorValidation(markers);
			}
		}
	});

But I don't think this affects the editor, because it is also working well in development.

Thanks in advance

Personally I’m not a fan of relying on a framework-specific plugin for your bundler, so I recommend to use the method using MonacoEnvironment. However, if another method works for you, I’d say go with that.

Some people run into problems because they load the editor from a CDN. Some people aren’t even aware, because a wrapper library like @monaco-editor/react does that for them.

Also it’s important that a model and its uri represents a file on a (virtual) file system. You can’t create the same file twice. Also disposing an editor doesn’t dispose its model. I don’t think you’re running into this, but it’s something you should understand and pay attention to.

Alright, I just removed MonacoWebpackPlugin and went back loading the MonacoEnvironment through the URLs.

window.MonacoEnvironment = {
	getWorker(moduleId, label) {
		switch (label) {
			case 'editorWorkerService':
				return new Worker(new URL('monaco-editor/esm/vs/editor/editor.worker', import.meta.url));
			case 'yaml':
				return new Worker(new URL('monaco-yaml/yaml.worker', import.meta.url));
			default:
				throw new Error(`Unknown label ${label}`);
		}
	},
};

My new Webpack config looks like this now

const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
const HtmlWebPackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

module.exports =  {
	output: {
		filename: '[contenthash].js',
	},
	devtool: 'source-map',
	resolve: {
		extensions: ['.mjs', '.js', '.ts'],
	},
	module: {
		rules: [
			{
				test: /\.css$/,
				use: [MiniCssExtractPlugin.loader, 'css-loader'],
			},
			{
				// Monaco editor uses .ttf icons.
				test: /\.(svg|ttf)$/,
				type: 'asset/resource',
			},
			{
				test: /schema\.json$/,
				type: 'asset/resource',
			},
			{
				test: /\.ts$/,
				loader: 'ts-loader',
				options: { transpileOnly: true },
			},
		],
	},
	optimization: {
		minimizer: ['...', new CssMinimizerPlugin()],
	},
	plugins: [new HtmlWebPackPlugin(), new MiniCssExtractPlugin({ filename: '[contenthash].css' })],
};

As before it works totally fine in Development but I still get these Errors in my Production Build.
Could it be like a Problem with CORS ?

image

I was able to solve the problem, it hasn't had to do anything with monaco editor or with monaco yaml. The main problem was our setup with keycloak. CORS blocked the worker scripts.