atularen / ngx-monaco-editor

Monaco Editor component for Angular 2 and Above
https://www.npmjs.com/package/ngx-monaco-editor
MIT License
428 stars 155 forks source link

NgxMonacoEditorConfig Not working in angular production build #49

Open Stevertus opened 6 years ago

Stevertus commented 6 years ago

I have the MonacoConfig in an extra file:

import { MonacoEditorModule, NgxMonacoEditorConfig } from 'ngx-monaco-editor';

const monacoConfig: NgxMonacoEditorConfig = {
  defaultOptions: {scrollBeyondLastLine: false},
  onMonacoLoad: () => {
    // Register a new language
    let monaco = (<any>window).monaco
    [...]

}
};
export default monacoConfig;

And I import it into app.module:

import monacoConfig from './editor/monaco-lang'
import { MonacoEditorModule, NgxMonacoEditorConfig } from 'ngx-monaco-editor';
...
imports: [
 MonacoEditorModule.forRoot(monacoConfig),
]

While serving and building everything acts normal, but when I build it as production the editor does not load and I am getting this error:

ERROR TypeError: Cannot read property 'defaultOptions' of null
    at e.set [as options] (main.d3395c8….bundle.js:1)
    at $r (main.d3395c8….bundle.js:1)
    at main.d3395c8….bundle.js:1
    at main.d3395c8….bundle.js:1
    at bi (main.d3395c8….bundle.js:1)
    at ro (main.d3395c8….bundle.js:1)
    at main.d3395c8….bundle.js:1
    at Object.updateDirectives (main.d3395c8….bundle.js:1)
    at Object.eo [as updateDirectives] (main.d3395c8….bundle.js:1)
    at _i (main.d3395c8….bundle.js:1)

Is my config wrong or is this a common issue?

  1. If I build it without --prod it works in the browser, but not in my electron app. I get this error:
    ERROR Error: Uncaught (in promise): TypeError: window.require.config is not a function
    TypeError: window.require.config is not a function
    at onGotAmdLoader (base-editor.js:50)
    at base-editor.js:68
    at new ZoneAwarePromise (zone-mix.js:891)
    at EditorComponent.webpackJsonp../node_modules/ngx-monaco-editor/base-editor.js.BaseEditor.ngAfterViewInit (base-editor.js:42)
    at callProviderLifecycles (core.js:12706)

    Is something wrong with the way I import my config?

DevidCIC commented 6 years ago

I think that you have to set the baseUrl. Something like:

const monacoEditorConfig: NgxMonacoEditorConfig = {
    onMonacoLoad,
    baseUrl: './assets'
};
Stevertus commented 6 years ago

Tried it already. Same problem. It also says property of null, so the whole object must be null. The same problems occures if I fix the baseUrl in the source code with the defaultOptions

WarcraftYax commented 6 years ago

@Stevertus did you find a fix for this? I'm getting the same issue.

Stevertus commented 6 years ago

not yet really. Had to upload my website in non-production build and it is pretty slow for some persons :(

WarcraftYax commented 6 years ago

@Stevertus The same error can be replicated in the example by moving monacoConfig to an external file and building for production.

Instead of uploading a non-production build, I'd recommend just in-lining your monacoConfig in your app.module.ts file. It'll look ugly, but it will work.

piotrjurczuk commented 6 years ago

No its not working. This problem existing only for external server. Some other solutions or ideas what i can do it?

1nv1n commented 6 years ago

I'm seeing the same issue, even with the basic example/sample provided in the README:

ERROR Error: Uncaught (in promise): TypeError: window.require.config is not a function TypeError: window.require.config is not a function.

Full trace: https://gist.github.com/1nv1n/34071e4c4fa9e37ceedd19872e939889

These are the dependencies in my package.json: https://gist.github.com/1nv1n/53b0fc655e0a9d70bbfaf4f8473373a2

And Angular config. JSON: https://gist.github.com/1nv1n/63ec946ee7b125799350b506c8281012

Any suggestions, @atul-wizni ?

piotrjurczuk commented 6 years ago

I fixed this issue a few days ago. You must add monaco config to app module with correct baseUrl. Do not forget attachment your config to providers.

1nv1n commented 6 years ago

@piotrjurczuk , I tried to do that just now (setting baseUrl in monacoConfig in app.module.ts & passing it as MonacoEditorModule.forRoot(monacoConfig) ) & although the stack trace is slightly different, the error is the same.

Error: Uncaught (in promise): TypeError: window.require.config is not a function.

When I debug through it, on line 50 in base-editor.ts, I see window.require.config as undefined.

These are all the updates I've done to the basic Angular app so far: https://gist.github.com/1nv1n/635d0e261a76f6c1ad4f6e3e220827db

Could you please provide a complete example?

piotrjurczuk commented 6 years ago

Okey but in my opinion this part of code is invalid: baseUrl: './assets/monaco/' so change it to: baseUrl: 'app/assets' or to another address where your folder is actually located.

app - your app name

ghost commented 6 years ago

Hi for all,

I tried @piotrjurczuk solution but I got same problem like above. Has anyone found a solution?

Thanks

ddikman commented 5 years ago

As mentioned above, I do think this looks as if the config becomes nulled once it's loaded into the editor. I chased it down in the source and I wonder if it's got to do with the provider scopes. Could it be that somehow when the module tries to add the new config it fails to provide it outside of the module, ending up making the default value null?

See affected code: https://github.com/atularen/ngx-monaco-editor/blob/master/src/platform/editor/editor.module.ts#L26

I tried setting the injector token directly in my main app.module.ts using the following and that worked perfectly:

import MonacoConfig from './monaco-config';
import { AppComponent } from './app.component';
import { EditorComponent } from './editor/editor.component';

@NgModule({
  declarations: [
    AppComponent,
    EditorComponent
  ],
  imports: [
    FormsModule,
    MonacoEditorModule.forRoot()
  ],
  providers: [
    { provide: NGX_MONACO_EDITOR_CONFIG, useValue: MonacoConfig }
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }
enginexon commented 5 years ago

providers: [ { provide: NGX_MONACO_EDITOR_CONFIG, useValue: MonacoConfig } ],

@ddikman Thank you very much. It really works

GlauberF commented 5 years ago

@ddikman I'm having the same problem, could you share what you have in monaco-config

ddikman commented 5 years ago

@ddikman I'm having the same problem, could you share what you have in monaco-config

@GlauberF sure, it isn't much though but this is how it looks:

import { NgxMonacoEditorConfig } from 'ngx-monaco-editor';
const MonacoConfig: NgxMonacoEditorConfig = {
  onMonacoLoad: function() {
    monaco.editor.defineTheme('appname', {
      base: 'vs-dark',
      inherit: true,
      rules: [],
      colors: {
        'editor.lineHighlightBackground': '#444444'
      }
    });
    monaco.editor.setTheme('appname');
  }
};

export default MonacoConfig;
ianadavies commented 4 years ago

Any updates on this.

I have tried all of the above and still not working for me :( BTW I am running this inside an Electron App so not sure if that has an impact?

JoBoDo commented 4 years ago

@ianadavies did you find anything out for this? I've the same issue inside of Electron.

ianadavies commented 4 years ago

@JoBoDo No found nothing that works for me yet. I did find this https://github.com/Teradata/covalent-code-editor-nightly Which is basically a wrapper around monaco for Angular and claims to work with Electron, but it didn't work for me. I had similar issues with require. Worth a go though, do let me know if it works for you.

ianadavies commented 4 years ago

@JoBoDo Actually just found this https://ngohungphuc.wordpress.com/2019/01/08/integrate-monaco-editor-with-angular/ Busy with something else atm but will try this myself in a few hours. Doesn't mention Electron, but I found it as a possible solution for integrating with Electron, it's a webpack based fix so maybe it removes all the issues with require and loader.js

darrenmothersele commented 4 years ago

I switched to using @materia-ui/ngx-monaco-editor as I found it much easier to get working in Angular v9 with Ivy. Perhaps this will also work in Electron? https://github.com/materiahq/ngx-monaco-editor#readme

alexboisselle-rd commented 4 years ago

Possible solution!

I was using SystemJS for some microfrontend stuff and SystemJS defines it's own "define" prop on global. The loader that monaco is trying to use has it's own conditions around a global "define". If it exists it will not create it's own ModuleManager.

My fix for this was to put a window['define'] = null somewhere before init'ing the editor.

This solved the issue however now I have side effects when using SystemJS which I'll have to sort out. Maybe other frameworks/libs are defining a "define" var for you guys as well.

Hope this helps!

markoj21 commented 4 years ago

Looks like there is a race condition while loading the loader.js in the ngAfterViewInit function and the browser sending the load event when the loader.js has been added to the dom, this should be addressed with simplifying and updating ngAfterViewInit. A workaround is adding the following to the angular.json file, the downside is the loader is always included and not lazy loaded.

        "scripts": [
            "./node_modules/ngx-monaco-editor/assets/monaco/vs/loader.js"
        ]
Infinity-Intellect commented 3 years ago

@markoj21 Thanks ! This worked.