optimajet / formengine

Drag & Drop Form Builder Library for React.
https://formengine.io
27 stars 4 forks source link

Getting error with Monaco editor in Electron application #22

Open davidbrinton opened 1 week ago

davidbrinton commented 1 week ago

We're trying to use your formengine in an Electron application and we're getting an error that has been hard to pin down. Here is the error:

Uncaught (in promise) Error: ENOENT: no such file or directory, open 'C:\Users\myuser\source\repos\electron-app\https:\cdn.jsdelivr.net\npm\monaco-editor@0.43.0\min\vs\editor\editor.main.js'

It looks like the monaco editor is a dependency formengine needs. It's kind of hard figuring out what's happening since it's loading this as a dependency of a dependency but what I've found is that when the application is started a new script is injected into our HTML file that looks like this

<script src="https://cdn.jsdelivr.net/npm/monaco-editor@0.43.0/min/vs/loader.js"></script>

The BaseURL for the script tag is the location of our index.html file and since this is an Electron app, is in a location on the local file system.

When Chromium tries to load the script that was injected it treats the https://cdn.jsdelivr.net... as a relative path and appends it to the local file system directory.

A few questions here for you:

Appreciate your help

optimajet commented 1 week ago

Hello @davidbrinton,

The Monaco editor is used in many parts of the designer's package:

  1. JSON editor.
  2. CSS style editor.
  3. Action code editor.
  4. Validation code editor.
  5. Computable properties editor.
  6. Localization editor (Fluent).

Are you sure you don't need all those parts?

Is there a place we can see the source repository for formengine? It would make it a bit easier to see what's going on potentially.

We provide the product source code with the purchase (for some license types).

We think that the problem with Monaco embedding is solvable. If you are interested in buying FormEngine - the solution can be prioritized. You can contact sales@optimajet.com for more information.

davidbrinton commented 1 week ago

@optimajet No, I'm not certain we don't need all of those components and it would be better if it was just working the way it was supposed to be. We did plan on purchasing a license but we're in our proof of concept phase and this error is part of what's keeping us from saying it will work for us.

We think that the problem with Monaco embedding is solvable. If you are interested in buying FormEngine - the solution can be prioritized.

So you're thinking this is something that would need to be addressed in the FormEngine source code? I was maybe too optimistic to think it would have been solvable with a configuration change on our side.

We have a feature for our software that is due to release at the end of July (quarter 2). We can't release without this component working if we use FormEngine. It would be nice to use it to save us some time, but we do need to have something working by then.

optimajet commented 1 week ago

@davidbrinton We're looking into this issue.

optimajet commented 6 days ago

@davidbrinton Have you tried customizing Monaco according to Microsoft recommendations?

For example, here is this document: https://github.com/microsoft/monaco-editor/blob/main/docs/integrate-esm.md. If you are using Vite, customizing workers for Monaco is very easy, example file (monaco.settings.ts):

import {loader} from '@monaco-editor/react'
import * as monaco from 'monaco-editor'
import DefaultWorker from 'monaco-editor/esm/vs/editor/editor.worker.js?worker'
import CssWorker from 'monaco-editor/esm/vs/language/css/css.worker.js?worker'
import HtmlWorker from 'monaco-editor/esm/vs/language/html/html.worker.js?worker'
import JsonWorker from 'monaco-editor/esm/vs/language/json/json.worker.js?worker'
import TypeScriptWorker from 'monaco-editor/esm/vs/language/typescript/ts.worker.js?worker'

self.MonacoEnvironment = {
  getWorker: (_, label) => {
    switch (label) {
      case 'json':
        return new JsonWorker()
      case 'css':
      case 'scss':
      case 'less':
        return new CssWorker()
      case 'html':
      case 'handlebars':
      case 'razor':
        return new HtmlWorker()
      case 'typescript':
      case 'javascript':
        return new TypeScriptWorker()
      default:
        return new DefaultWorker()
    }
  }
}

loader.config({monaco})
monaco.languages.typescript.typescriptDefaults.setEagerModelSync(true)

Import the file before importing FormViewer/FormBuilder:

import './utils/monaco.settings'
import React from 'react'
import ReactDOM from 'react-dom'
import App from './App'

ReactDOM.render(
  <React.StrictMode>
    <App/>
  </React.StrictMode>,
  document.getElementById('root')
)

CRA (create-react-app) packaging can be more complicated, you may have to eject or use react-app-rewired. This link may be helpful - https://github.com/microsoft/monaco-editor/issues/82.

What build tool do you use?

davidbrinton commented 2 days ago

@optimajet We're using webpack as our build tool.

I may be missing something here but I have no experience with Monaco and didn't even know what it was before I started getting this error trying to run the Form Engine. I have seen people talking about how to successfully reference Monaco directly in an Electron project, and it seemed like an easy thing to do, but our issue is that we're not directly referencing it so it seems we don't have control over how it is being referenced.

If you are using Vite, customizing workers for Monaco is very easy, example file (monaco.settings.ts):

I'm not sure what Monaco workers are and wasn't intending to learn the library. If learning how to use Monaco will help me fix this error somehow I would be willing to read their tutorial documentation, it just didn't seem relevant before.

Import the file before importing FormViewer/FormBuilder

Are you saying if we import a Monaco settings file somewhere in our code before using Form Builder we will be able to control "worker" configuration and that will affect how Monaco is being loaded so that we no longer get this error? If so, I have no problem trying that out.

Thank you again for your help and attention to this!

optimajet commented 2 days ago

We have published a guide on how to use FormEngine in Electron - https://formengine.io/documentation/integration-with-electron. In this guide Webpack is used, we hope that with the help of this article you will be able to solve the packaging issue.