react-ace
react-ace copied to clipboard
Could not load worker
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
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'
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 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');
Did anyone get this working with create-react-app? Mine gets stuck compiling forever if I add:
import 'ace-builds/webpack-resolver';
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.
@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!)
setOptions={{ useWorker: false }}
works for me. Thanks @khoomeister
also still having this issue. does using "useWorker has any downsides? what does those workers do exactly?
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.
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.
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
@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.
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.
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
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.
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" />
@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)
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"
);
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);
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?
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);
do you guys how to solve this as file-loader
is deprecated, how can we configrue ace
now without file-loader
?
What is the status of this issue? Although importing webpack-resolver
works, it makes compilation super-slow, so cannot be considered a permanent solution.
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);
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:
-
use strict' is added to the file at the top, right above
'no use strict'` - 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?
Adding webpack-resolver
creating 100+ js files when building the project
https://github.com/securingsincity/react-ace/issues/1168
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);
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
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.
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";