react-ace icon indicating copy to clipboard operation
react-ace copied to clipboard

Could not load worker

Open sergibondarenko opened this issue 5 years ago • 34 comments

Problem

Couldn't load worker, JSON syntax validation doesn't work. I see Could not load worker warning in the browser console.

Also, I tried to import the json worker

import "ace-builds/src-noconflict/worker-json";

and got the error

TypeError: Cannot read property 'window' of undefined

Sample code to reproduce the issue

import React from "react";
import ReactDOM from "react-dom";
import AceEditor from "react-ace";

import "ace-builds/src-noconflict/ace";
import "ace-builds/src-noconflict/mode-json";
import "ace-builds/src-noconflict/theme-github";

let text =
  '{\n  "id": 0,\n  ' +
  '"script": """\n   function add(x, y) {\n      return x + y;\n   }\n   add(1, 2);\n   """' +
  ',\n   "descr": "add two numbers"\n}';

function App() {
  return (
    <div className="App">
      <h1>Code Editor Demo</h1>
      <AceEditor
        mode="json"
        theme="github"
        onChange={(value, stat) => {
          console.log("onChange", value, stat);
        }}
        value={text}
        name="UNIQUE_ID_OF_DIV"
        editorProps={{ $blockScrolling: true }}
      />
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

References

Codesandbox https://codesandbox.io/embed/ace-worker-3-vrr68

sergibondarenko avatar Oct 15 '19 20:10 sergibondarenko

I'm experiencing something similar for CSS, getting the following error in browser console:

Uncaught DOMException: Failed to execute 'importScripts' on 'WorkerGlobalScope': The script at 'http://localhost:9000/settings/landing-page/worker-css.js' failed to load.

When attempting to import worker directly

import 'ace-builds/src-noconflict/worker-css';

My build failed with:

ERROR in ../node_modules/ace-builds/src-noconflict/worker-css.js
Module not found: Error: Can't resolve 'ace/lib/es5-shim' in 'path/to/node_modules/ace-builds/src-noconflict'

ZeD3v avatar Oct 17 '19 10:10 ZeD3v

You need to either include the webpack-resolver

import "ace-builds/webpack-resolver";

or configure the url for each mode separately

import jsonWorkerUrl from "file-loader!ace-builds/src-noconflict/worker-json";
ace.config.setModuleUrl("ace/mode/json_worker", jsonWorkerUrl)
import cssWorkerUrl from "file-loader!ace-builds/src-noconflict/worker-css";
ace.config.setModuleUrl("ace/mode/css_worker", cssWorkerUrl)

both methods require "file-loader"

also react-ace tries to load brace if ace is not already imported so ace-builds needs to be imported before react-ace.

import "ace-builds";
import AceEditor from "react-ace";

nightwing avatar Oct 17 '19 10:10 nightwing

@nightwing that works but importing ace-builds before react-ace fails in Firefox for me. I got it to work with:

import AceEditor from 'react-ace';
import 'ace-builds/webpack-resolver';
// then the mode, theme & extension
import 'ace-builds/src-noconflict/mode-json';
import 'ace-builds/src-noconflict/theme-tomorrow_night';
import 'ace-builds/src-noconflict/ext-searchbox';

But I couldn't get it to work with my tests. The webpack-resolver import line fails in tests with

TypeError: Cannot read property 'setModuleUrl' of undefined

I'm guessing I need mock ace with something like

global.ace = require('ace-builds/src-min-noconflict/ace');

arjunu avatar Oct 18 '19 10:10 arjunu

Did anyone get this working with create-react-app? Mine gets stuck compiling forever if I add:

import 'ace-builds/webpack-resolver';

mattjstar avatar Oct 22 '19 16:10 mattjstar

I fixed by adding useWorker: false to setOptions if importing modules directly. If this is a good solution, README.md basic usage should be updated unless I'm missing something.

ghost avatar Oct 24 '19 20:10 ghost

@khoomeister that got rid of all the warnings, but did your performance get noticeably worse (that could just be my implementation)?

(thanks for the tip btw!)

mattjstar avatar Oct 25 '19 14:10 mattjstar

setOptions={{ useWorker: false }}

works for me. Thanks @khoomeister

sourovroy avatar Oct 27 '19 16:10 sourovroy

also still having this issue. does using "useWorker has any downsides? what does those workers do exactly?

doneumark avatar Nov 14 '19 22:11 doneumark

I'm using a create-react-app project.

The only thing I needed to do was to add this in my App.tsx:

import 'ace-builds/webpack-resolver'

Setting useWorker to false disables syntax checking at least, maybe other things, so I didn't want to use that.

I don't know yet if this is good enough to make it work with tests as per arjunu's comment above.

caprica avatar Nov 28 '19 19:11 caprica

Adding webpack-resolver to my create-react-app project leads to a huge increase in compile time, and adds hundreds of files to the build directory - I assume one for each module in ace-builds that it configures. Configuring the url for just the modules that I need works fine, though.

This seems like it's an issue with either react-scripts or ace-builds, not react-ace.

bespokebob avatar Dec 05 '19 18:12 bespokebob

So far I am happy with react-ace, thanks for all the hard work guys!

I was attempting to upgrade to version 8 but I failed due to issues with worker, so for now I am staying at 7.

I am using "react-scripts": "3.2.0" (Create React App)

I could not get worker to load, and the following errors were displayed in the console:

03226918-0f44-4ac8-b073-1abc2ed64713:1 Refused to execute script from 'http://localhost:8000/worker-javascript.js' because its MIME type ('text/html') is not executable.
(anonymous) @ 03226918-0f44-4ac8-b073-1abc2ed64713:1
9297f3cf-c75b-4245-8c37-3ac2a7fed94d:1 Refused to execute script from 'http://localhost:8000/worker-javascript.js' because its MIME type ('text/html') is not executable.
(anonymous) @ 9297f3cf-c75b-4245-8c37-3ac2a7fed94d:1
03226918-0f44-4ac8-b073-1abc2ed64713:1 Uncaught DOMException: Failed to execute 'importScripts' on 'WorkerGlobalScope': The script at 'http://localhost:8000/worker-javascript.js' failed to load.
    at blob:http://localhost:8000/03226918-0f44-4ac8-b073-1abc2ed64713:1:1
(anonymous) @ 03226918-0f44-4ac8-b073-1abc2ed64713:1
9297f3cf-c75b-4245-8c37-3ac2a7fed94d:1 Uncaught DOMException: Failed to execute 'importScripts' on 'WorkerGlobalScope': The script at 'http://localhost:8000/worker-javascript.js' failed to load.
    at blob:http://localhost:8000/9297f3cf-c75b-4245-8c37-3ac2a7fed94d:1:1
(anonymous) @ 9297f3cf-c75b-4245-8c37-3ac2a7fed94d:1

Disabling the worker is not an option for me. I tried adding the webpack-resolver using import 'ace-builds/webpack-resolver'; but my app would not compile - the compilation was hanging indefinitely.

I also attempted to add it manually using the file-loader and setModuleUrl but then I got the error with missing ace/lib/es5-shim.

It seems that this issue is related to #733 #755 and ajaxorg/ace#4770

jan-osch avatar Dec 27 '19 11:12 jan-osch

@mattjstar I got it working with:

import 'ace-builds'
import 'ace-builds/webpack-resolver'

So import ace-builds before the resolver (any anything else relater to the AceEditor)

See @arjunu answer above.

bitconym avatar Dec 30 '19 10:12 bitconym

I added the last 3 lines to add javascript-worker :

import AceEditor from "react-ace";
import "ace-builds/src-min-noconflict/mode-javascript";
import "ace-builds/src-min-noconflict/theme-tomorrow_night_eighties";
import "ace-builds/src-min-noconflict/ext-language_tools";
import "ace-builds/src-min-noconflict/ext-spellcheck";
import "ace-builds/src-min-noconflict/snippets/javascript";
import 'ace-builds/src-min-noconflict/ext-searchbox';
const ace = require('ace-builds/src-noconflict/ace');
ace.config.set("basePath", "https://cdn.jsdelivr.net/npm/[email protected]/src-noconflict/");
ace.config.setModuleUrl('ace/mode/javascript_worker', "https://cdn.jsdelivr.net/npm/[email protected]/src-noconflict/worker-javascript.js");

You can copy/paste the file worker-javascript.js in your local environment if you don't want to be dependant of cdn.jsdelivr.net.

Holgrabus avatar Jan 08 '20 13:01 Holgrabus

You need to either include the webpack-resolver

import "ace-builds/webpack-resolver";

or configure the url for each mode separately

import jsonWorkerUrl from "file-loader!ace-builds/src-noconflict/worker-json";
ace.config.setModuleUrl("ace/mode/json_worker", jsonWorkerUrl)
import cssWorkerUrl from "file-loader!ace-builds/src-noconflict/worker-css";
ace.config.setModuleUrl("ace/mode/css_worker", cssWorkerUrl)

both methods require "file-loader"

also react-ace tries to load brace if ace is not already imported so ace-builds needs to be imported before react-ace.

import "ace-builds";
import AceEditor from "react-ace";

This works perfectly. Define worker URL before using any mode or theme

import "ace-builds"
import ACE from "react-ace/dist/react-ace.min";

import jsonWorkerUrl from "file-loader!ace-builds/src-noconflict/worker-json";
ace.config.setModuleUrl("ace/mode/json_worker", jsonWorkerUrl);
import xmlWorkerUrl from "file-loader!ace-builds/src-noconflict/worker-xml";
ace.config.setModuleUrl("ace/mode/xml_worker", xmlWorkerUrl);
import jsWorkerUrl from "file-loader!ace-builds/src-noconflict/worker-javascript";
ace.config.setModuleUrl("ace/mode/javascript_worker", jsWorkerUrl);

import "ace-builds/src-min-noconflict/mode-typescript";
import "ace-builds/src-min-noconflict/mode-javascript";
import "ace-builds/src-min-noconflict/mode-graphqlschema";
import "ace-builds/src-min-noconflict/mode-json";
import "ace-builds/src-min-noconflict/mode-xml";
import "ace-builds/src-min-noconflict/mode-markdown";
import "ace-builds/src-min-noconflict/mode-html";
import "ace-builds/src-min-noconflict/theme-github";
import "ace-builds/src-min-noconflict/theme-tomorrow";
import "ace-builds/src-min-noconflict/theme-kuroir";
import "ace-builds/src-min-noconflict/ext-searchbox";

also no need to set: setOptions={{ useWorker: false }} https://github.com/securingsincity/react-ace/issues/725#issuecomment-546711308

pranavwani avatar Mar 22 '20 07:03 pranavwani

What if i want to have a custom worker that is not in the ace-builds/src-.../ folder? I need to use it with an ANTLR parser done by me.

MattNot avatar Mar 26 '20 18:03 MattNot

I leave the full [email protected] integration here.

import dynamic from "next/dynamic";

const AceEditor = dynamic(
  async () => {
    const reactAce = await import("react-ace");

    // prevent warning in console about misspelled props name.
    await import("ace-builds/src-min-noconflict/ext-language_tools");

    // import your theme/mode here. <AceEditor mode="javascript" theme="solarized_dark" />
    await import("ace-builds/src-min-noconflict/mode-javascript");
    await import("ace-builds/src-min-noconflict/theme-solarized_dark");

    // as @Holgrabus commented you can paste these file into your /public folder.
    // You will have to set basePath and setModuleUrl accordingly.
    let ace = require("ace-builds/src-min-noconflict/ace");
    ace.config.set(
      "basePath",
      "https://cdn.jsdelivr.net/npm/[email protected]/src-noconflict/"
    );
    ace.config.setModuleUrl(
      "ace/mode/javascript_worker",
      "https://cdn.jsdelivr.net/npm/[email protected]/src-noconflict/worker-javascript.js"
    );

    return reactAce;
  },
  {
    ssr: false // react-ace doesn't support server side rendering as it uses the window object.
  }
);

export default () =>  <AceEditor mode="javascript" theme="solarized_dark" />

jchonde avatar Mar 27 '20 13:03 jchonde

@jan-osch so if I want to use my "customWorker.js" for example, i've to set ace.config.setModuleUrl("ace/mode/myWorker", "/customWorker.js") ? (putting customWorker.js in the /public folder)

MattNot avatar Mar 27 '20 13:03 MattNot

If you want to use the workarounds in Typescript you'll need to do this to set ace config:

import { config } from 'ace-builds';

config.set(
  "basePath",
  "https://cdn.jsdelivr.net/npm/[email protected]/src-noconflict/"
);
config.setModuleUrl(
   "ace/mode/javascript_worker",
   "https://cdn.jsdelivr.net/npm/[email protected]/src-noconflict/worker-javascript.js"
);

jamesej avatar May 15 '20 07:05 jamesej

I added the following test to Webpack

  module: {
    rules: [
      {
        test: /ace-builds.*\/worker-.*$/,
        loader: 'file-loader',
        options: {
          esModule: false,
          name: '[name].[hash:8].[ext]',
        },
      },
    ],
  },

then I was able to import as following

import ace from 'ace-builds/src-noconflict/ace';
import cssWorkerUrl from 'ace-builds/src-noconflict/worker-css';

ace.config.setModuleUrl('ace/mode/css_worker', cssWorkerUrl);

aboganas avatar Sep 15 '20 07:09 aboganas

I'm importing as suggested by @pranavwani but now am running into the error Cannot read property 'Range' of undefined. "Error loading module." when ace.tsx is attempting to import ace/range.

I believe that the issue is that since window.ace is defined, even though I want to be using ace-builds, ace keeps falling back on the ace.acequire syntax in editorOptions. Has anyone come across a workaround for this issue?

johnjackweir avatar Oct 12 '20 14:10 johnjackweir

I added the following test to Webpack

  module: {
    rules: [
      {
        test: /ace-builds.*\/worker-.*$/,
        loader: 'file-loader',
        options: {
          esModule: false,
          name: '[name].[hash:8].[ext]',
        },
      },
    ],
  },

then I was able to import as following

import ace from 'ace-builds/src-noconflict/ace';
import cssWorkerUrl from 'ace-builds/src-noconflict/worker-css';

ace.config.setModuleUrl('ace/mode/css_worker', cssWorkerUrl);

you can also do that without modify webpack config

import ace from 'ace-builds/src-noconflict/ace';
/* eslint import/no-webpack-loader-syntax: off */
import cssWorkerUrl from 'ace-builds/src-noconflict/worker-css';

ace.config.setModuleUrl('ace/mode/css_worker', cssWorkerUrl);

legolasNg avatar Dec 10 '20 16:12 legolasNg

do you guys how to solve this as file-loader is deprecated, how can we configrue ace now without file-loader?

p3x-robot avatar Jul 16 '21 04:07 p3x-robot

What is the status of this issue? Although importing webpack-resolver works, it makes compilation super-slow, so cannot be considered a permanent solution.

mgoldenbe avatar Jul 19 '21 14:07 mgoldenbe

The following seems to have worked for me. The key is the order of imports and the last three lines (including the comment!) I got it from this reply.

import 'ace-builds'
import AceEditor from 'react-ace';
import ace from 'ace-builds/src-noconflict/ace'
// import mode-<language> , this imports the style and colors for the selected language.
import 'ace-builds/src-noconflict/mode-xml';
// there are many themes to import, I liked monokai.
import 'ace-builds/src-noconflict/theme-github';
// this is an optional import just improved the interaction.
import 'ace-builds/src-noconflict/ext-language_tools';
import 'ace-builds/src-noconflict/ext-beautify';
// eslint-disable-next-line import/no-webpack-loader-syntax
import xmlWorkerUrl from "!!file-loader!ace-builds/src-noconflict/worker-xml";
ace.config.setModuleUrl("ace/mode/xml_worker", xmlWorkerUrl);

mgoldenbe avatar Jul 19 '21 14:07 mgoldenbe

None of these suggestions are working for me. I am getting the same Cannot read property 'window' of undefined as the OP.

When I use:

import AceEditor from 'react-ace'
import 'ace-builds/webpack-resolver'
import 'ace-builds/src-noconflict/mode-javascript'

I get the following error: 61b85f295f78e37ba4d607ea64fab1e8.js:1 Uncaught TypeError: Cannot read property 'window' of undefined

After comparing ace-builds/src-noconflict/worker-javascript.js to my generated version, there are some changes:

  1. use strict' is added to the file at the top, right above 'no use strict'`
  2. The self-executing function at the start:
!(function (window) {
  if (typeof window.window != 'undefined' && window.document) return
})(this)

Turns into:

!(function (window) {
  if (typeof window.window != "undefined" && window.document) return;
})(void 0);

I believe this is causing me and the OPs issue. Any idea why these files would be transformed like this?

er-dev avatar Sep 08 '21 23:09 er-dev

Adding webpack-resolver creating 100+ js files when building the project https://github.com/securingsincity/react-ace/issues/1168

AlmogBaku avatar Nov 03 '21 14:11 AlmogBaku

I had trouble getting webpack-resolver to play nicely with Jest and couldn't figure out the magic moduleNameMapper pattern.

I was able to work around this in Webpack v5 by using an Asset Module targeting the worker* files in ace-build:

// webpack.config.js
module: {
  rules: [
    {
      test: /worker-.*\.js/,
      include: [/node_modules\/ace-build/],
      type: 'asset/resource',
    }
  ]
}
// editor.js
import ace from 'ace-builds/src-noconflict/ace';
import 'ace-builds/src-noconflict/mode-json';
import jsonWorker from 'ace-builds/src-noconflict/worker-json';

ace.config.setModuleUrl('ace/mode/json_worker', jsonWorker);

mattduggan avatar Dec 20 '21 19:12 mattduggan

For those of you using Vite, I was able to get it working using Explicit URL Imports (appending ?url to the end of the worker import):

import ace from 'ace-builds/src-noconflict/ace';
import jsonWorkerUrl from 'ace-builds/src-noconflict/worker-json?url';

ace.config.setModuleUrl('ace/mode/json_worker', jsonWorkerUrl);

// ... mode and theme imports here

haftav avatar Apr 01 '22 18:04 haftav

import ace from 'ace-builds/src-min-noconflict/ace';
import 'ace-builds/webpack-resolver'; 

This solution works for me, it solves all my import problems, include worker execute problem.

AmazingYuan avatar May 19 '22 14:05 AmazingYuan

For those searching how to implement workers now, when file-upload is deprecated with Webpack 5 asset/resource.

webpack config:

rules: [
  {
      test: /ace-builds.*\/worker-.*$/,
      type: "asset/resource"
  },
],

component:

import AceEditor from "react-ace";
import { config } from "ace-builds";
import "ace-builds/src-noconflict/mode-javascript";
import "ace-builds/src-noconflict/theme-github";
import "ace-builds/src-noconflict/ext-language_tools";

import jsWorkerUrl from "ace-builds/src-noconflict/worker-javascript";
config.setModuleUrl("ace/mode/javascript_worker", jsWorkerUrl);

To fix the typescript "no module declaration" error, just add the global.d.ts file to your src folder:

declare module "ace-builds/src-noconflict/worker-javascript";

Cactusx09 avatar Oct 24 '22 11:10 Cactusx09