Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Runtime warning about "Could not create web worker(s)..." #853

Closed
jhk-mjolner opened this issue Feb 12, 2025 · 27 comments
Closed

Runtime warning about "Could not create web worker(s)..." #853

jhk-mjolner opened this issue Feb 12, 2025 · 27 comments

Comments

@jhk-mjolner
Copy link

Full warnings I get are

Image

Could not create web worker(s). Falling back to loading web worker code in main thread, which might cause UI freezes. Please see https://github.com/microsoft/monaco-editor#faq

I don't think I'm getting the UI freezes it mentions, but the warning appeared when I changed from using the buildWorkerDefinition() method from the monaco-editor-workers package to using the new useWorkerFactory method of building/initializing workers. Or it could be from updating the monaco-languageclient packages, I'm not sure, but I don't think I can use monaco-editor-workers with the newer monaco-languageclient packages.
I'm using the monaco-editor-wrapper, but the warnings also appear in a branch I have where I'm not using the wrapper, so it doesn't appear to be related to that.

It seems to be only about the simpleWorker, and it happens even if I don't include the 'TextEditorWorker' and 'TextMateWorker' functions under workerLoaders for the useWorkerFactory() call like it is here

I'm using Angular and Webpack, and these versions of monaco packages:
monaco-editor: 0.52.2,
monaco-editor-wrapper: 6.2.5
monaco-languageclient: 9.2.5

A bit more from the console log in case it's relevant:
Image

My code where I'm using monaco editor can be seen here

I'll reiterate that I'm not seeing errors or anything breaking that I'm aware of, but I'm guessing it's not intended.

@cdietrich
Copy link
Contributor

Had this too. Once I changed the useWorkerFactory to use module paths that can be resolved, it worked for me

@jhk-mjolner
Copy link
Author

Had this too. Once I changed the useWorkerFactory to use module paths that can be resolved, it worked for me

Could you expand on that? What did you change more precisely, and was it with angular and/or webpack?

I've tried messing around with webpack config and aliases, and changing the paths in the useWorkerFactory, but didn't improve anything, only made errors about paths that didn't resolve or couldn't be found, which led me to believe the paths I have already did resolve.

@cdietrich
Copy link
Contributor

Due to the way we bundle the url that was passed / calculated was wrong. Then the worker creation failed

I debugged to to find out the url it was requesting and then figured out my app does not deliver it due to the way we bundle

@jhk-mjolner
Copy link
Author

Okay. I'll try looking further into that. Thanks.

Do you remember if there was any particular piece of documentation for webpack (or other) that helped you? Or was it just about finding what the browser requests, and where webpack (or your bundler) puts the files, and making them match?

@cdietrich
Copy link
Contributor

cdietrich commented Feb 12, 2025

yes i debugged the url, and then checked where it actually lands, and then passed the correct url
we were manually copying files around (and the paths had changed)

@jhk-mjolner
Copy link
Author

Hmm, as far as I can tell, it resolves correctly.
The 'TextEditorWorker' URL object points to an address I can open in my browser and get exactly what is in the @codingame/monaco-vscode-editor-api/esm/vs/editor/editor.worker.js file:

export * from '@codingame/monaco-vscode-api/workers/editor.worker';

And the 'TextMateWorker' function apparently isn't called.

So URLs not resolving might not be my issue...

@cdietrich
Copy link
Contributor

cdietrich commented Feb 12, 2025

hmmm and its actually downloaded as well (network tab)

i use

    TextEditorWorker: () => {
      const u = new URL("../libs/monaco-editor-workers/editorWorker-es.js", import.meta.url)
      console.log(u.toString())
      return new Worker(u, {
        type: "module",
      })
    },

and see

Image

let me check sth.

@jhk-mjolner
Copy link
Author

It's weird. It appears in the network tab, but as 'pending' and with 0 B transferred, but if I doubleclick it, I can get the content in a new tab with no problem.

Only thing I can think of now is that something in the headers, that isn't present when loading it in a new tab, is causing the server not to respond...
like the sec-fetch-dest: worker header or something.

@cdietrich
Copy link
Contributor

cdietrich commented Feb 12, 2025

the -es.js file seems self contained the other one just does
export * from '@codingame/monaco-vscode-api/workers/editor.worker'

@jhk-mjolner
Copy link
Author

jhk-mjolner commented Feb 12, 2025

Hmm, I don't have a -es.js file in @codingame/monaco-vscode-editor-api/esm/vs/editor/

Image

Now I tried using the @codingame/monaco-vscode-api/workers/editor.worker url instead, and that causes my browser to try and load the /vscode/src/vs/editor/common/services/editorWorkerBootstrap.js path it exports, but the browser can't find it, probably because its relative path is now wrong.
So it's doing something with the 0 B pending result.
I also noticed that your image says 0 B, and my pending request still has a 200 OK status, so that part might not be so wrong after all.

@kaisalmen
Copy link
Collaborator

kaisalmen commented Feb 12, 2025

Hi @jhk-mjolner I just pushed an update to our verification examples including the webpack one (after x.3.0 release). There it works. Please, take a look at the webpack config and especially the worker related things:
https://github.com/TypeFox/monaco-languageclient/blob/main/verify/webpack/webpack.config.js
If I remember correctly these where needed to make it work.

And very important: Do not install the original monaco-editor package along with @codingame/monaco-vscode-editor-api package. I just realized we have to update our README. It is hidden in the Troubleshooting section and not explicitly stated / info is outdated.

You can even remove monaco-editor completely and just use it like that:

import * as monaco from '@codingame/monaco-vscode-editor-api';

@kaisalmen
Copy link
Collaborator

kaisalmen commented Feb 12, 2025

Got to verify/webpack and run npm run verify (it performs install and brings up the dev server):
Image

@jhk-mjolner
Copy link
Author

jhk-mjolner commented Feb 13, 2025

Thanks.

I've uninstalled the monaco-editor package, and updated the others to the x.3.0 releases.
I've been messing around with the webpack config options, but nothing seems to fix the problem.

In the verify/webpack project, I noticed that the loaded worker js file is a clearly webpack bundled file called vendors-node_modules_codingame_monaco-vscode-textmate-service-override_worker_js.main.js with lots of __webpack_this__ and __webpack_that__. But the file it tries to load for me is 320d512158e71419.js, and it's just the untransformed @codingame/monaco-vscode-editor-api/esm/vs/editor/editor.worker.js file with one export line in it.
So I think the problem is that webpack isn't actually transforming and bundling the file, but just taking it as-is, like an asset.
I haven't been able to find anything about that problem, except it's apparently important not to split the url out into a variable and give it to the worker constructor. It must be given directly, or webpack can't statically analyze it. But I'm doing that already.

Except for occasionally breaking things more, the changes I tried with the webpack config didn't change that it was output and fetched as an untransformed [hash].js file.
When I look at my compiled js code without sourcemaps, I also find that it says new Worker(new URL(/* asset import */ instead of /* worker import */ that I found somewhere should be the output, and is the output in the webpack/verify example.

I don't know why webpack does that wrong, or how to change it.

@kaisalmen
Copy link
Collaborator

kaisalmen commented Feb 13, 2025

@jhk-mjolner the one thing I can add here is that I have experienced that custom webpack used by ng behaves differently then direct webpack and that may explain your observation.

@cdietrich
Copy link
Contributor

Hmm. With the latest version of the codingame packages I cannot find editorWorker-es.js
Anymore

@cdietrich
Copy link
Contributor

solved it by bundling myself

// Monaco editor workers
  await esbuild.build({
    entryPoints: ["node_modules/@codingame/monaco-vscode-editor-api/esm/vs/editor/editor.worker.js"],
    bundle: true,
    format: "esm",
    treeShaking: true,
    plugins: [

    ],
    outfile: "./static/libs/monaco-editor-workers/editorWorker-es.js",
    minify,
    sourcemap: !minify || sourcemap,
  })

@kaisalmen
Copy link
Collaborator

@cdietrich I dropped those pre-bundled versions. It was a helpful in the past, but it is better to define something on user level especially with regard to local bundling.
We do this in the examples as well now: https://github.com/TypeFox/monaco-languageclient/blob/main/packages/examples/src/common/client/utils.ts#L19-L43
monaco-languageclient supplies the worker factory (monaco-languageclient/workerFactory), so it easy to define your own.

@jhk-mjolner
Copy link
Author

I've now tried creating a new empty Angular project, installed and used monaco-editor-wrapper and monaco-languageclient.
With the default esbuild, I get the same problems about loading json as described in #841.
And changing to webpack with @angular-devkit/build-angular, I get the same warnings as described in this issue. So it isn't something funky in my project.

It seems my next option is to manually build the workers in a separate step, as @cdietrich is doing. Though I'm not sure how complicated it's going to be, seeing that I'm not fully controlling webpack, just providing extra configuration, and not using esbuild like it seems @cdietrich is doing.

@kaisalmen, would it be possible (and simple) to bring the pre-bundled versions back just to support angular with webpack? User-bundled workers can still be the suggestion and recommendation, but currently things are broken for angular both with webpack and with esbuild. Maybe pre-bundled workers could be an easy way to make it work at least for angular with webpack?

@kaisalmen
Copy link
Collaborator

@jhk-mjolner yes, I will bring back the pre-bundled workers with #863

@jhk-mjolner
Copy link
Author

I saw that #863 is merged, and a x.4.0 versions have been released.
So I updated, but I'm not seeing a change in the @codingame/monaco-vscode-editor-api/esm/vs/editor/editor.worker.js and @codingame/monaco-vscode-textmate-service-override/worker.js files. At least, they don't seem to be bundled, and still contain only a single import or export line.

Is the pre-bundling not included in x.4.0, are the pre-bundled versions available at other paths, or am I misunderstanding something?

@cdietrich
Copy link
Contributor

did you see ./node_modules/monaco-editor-wrapper/dist/workers/editorWorker-es.js

@jhk-mjolner
Copy link
Author

No, I hadn't found that. Thanks! 🙂

I'm trying to import it like new Worker(new URL('monaco-editor-wrapper/workers/module/editor', import.meta.url), {type: 'module'}) since it's exported as that path. And it does load it, but now something (I'm guessing webpack) modifies the prebundled worker file and appends two imports that reference a local file path:

import _asyncToGenerator from "C:/[path to my project]/node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js";
import _asyncIterator from "C:/[path to my project]/node_modules/@babel/runtime/helpers/esm/asyncIterator.js";

Which it obviously can't import in the browser.

I tried messing around with the worker and module related webpack configurations again, but nothing I try seem to fix it.
I'm not sure if I should try telling webpack not to modify it, or whether it needs the imports, but to understand where it can find them or what...

@cdietrich
Copy link
Contributor

cdietrich commented Feb 19, 2025

cant you simply copy over the file and then manually reference it like

TextEditorWorker: () => {
  const url = new URL("../libs/monaco-editor-workers/editorWorker-es.js", import.meta.url)
  return new Worker(url, {
    type: "module",
  })
},

Image

the js file calling it is under public/js

@jhk-mjolner
Copy link
Author

Thanks for the suggestion!
If I copy the editorWorker-es.js file to my assets/ folder and import it like new Worker('/assets/editorWorker-es.js', {type: 'module'}), it does seemingly work. If I use the new URL(..., import.meta.url) syntax, it becomes a local file://C:/... path. There's seemingly something weird about paths with webpack+angular or something, I don't understand it at least.

I'm not happy about having to do the manual step of copying it when the monaco-editor-wrapper package is updated in future, but it's better than things not working 👍

@cdietrich
Copy link
Contributor

maybe you can do something in webpack as we do in esbuild

await esbuild.build({
    ....
    plugins: [
      copy({
        resolveFrom: "cwd",
        assets: [
          ....
          // Monaco editor workers
          {
            from: ["../../node_modules/monaco-editor-wrapper/dist/workers/*"],
            to: ["./static/libs/monaco-editor-workers"],
          },
        ],
        watch: true,
      }),
    ],

@jhk-mjolner
Copy link
Author

jhk-mjolner commented Feb 19, 2025

Yeah, I was trying something like that with 'assets' in angular.json, but it wasn't happy about the node_modules/ path.
I'll look further into what I can do with my angular.json and/or extra-webpack.config.js configurations 👍

edit: for future reference, I got it working with the following glob in angular.json under architect > build > options > assets:

{
  "glob": "editorWorker-es.js",
  "input": "./node_modules/monaco-editor-wrapper/dist/workers",
  "output": "/workers/"
}

and imported as 'TextEditorWorker': () => new Worker('/workers/editorWorker-es.js', {type: 'module'})

@jhk-mjolner
Copy link
Author

Since I got it working with copying the editorWorker-es.js file, I guess we can close this issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants