web-infra-dev / rsbuild

The Rspack-based build tool. It's fast, out-of-the-box and extensible.
https://rsbuild.dev/
MIT License
1.72k stars 135 forks source link

[Bug]: Problem in launching ace-builds webworkers #3837

Open carlomorelli opened 3 days ago

carlomorelli commented 3 days ago

Version

System: OS: macOS 14.7 CPU: (12) x64 Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz Memory: 55.36 MB / 16.00 GB Shell: 5.9 - /bin/zsh Browsers: Chrome: 130.0.6723.70 Safari: 18.0.1 npmPackages: @rsbuild/core: ^1.0.1 => 1.0.2 @rsbuild/plugin-node-polyfill: ^1.0.1 => 1.0.4 @rsbuild/plugin-react: ^1.0.1 => 1.0.1 @rsbuild/plugin-sass: ^1.0.1 => 1.0.1 @rsbuild/plugin-svgr: ^1.0.1 => 1.0.1

Details

Converting a project from React-scripts 4.x (using webpack 4.x under the hood) to RsBuild 1.0.

The UI embeds library ace-builds to produce a json-editor component.

In the old build code webpack-style, this works:

import ace from 'ace-builds/src-noconflict/ace';
import 'ace-builds/css/ace.css';
import 'ace-builds/css/theme/cloud_editor.css';
import 'ace-builds/css/theme/cloud_editor_dark.css';
...

ace.config.setModuleUrl('ace/theme/cloud_editor', new URL('ace-builds/src-noconflict/theme-cloud_editor.js', import.meta.url));
ace.config.setModuleUrl('ace/theme/cloud_editor_dark', new URL('ace-builds/src-noconflict/theme-cloud_editor_dark.js', import.meta.url));
ace.config.setModuleUrl('ace/mode/json_worker', new URL('ace-builds/src-noconflict/worker-json.js', import.meta.url));
ace.config.setModuleUrl('ace/mode/json', new URL('ace-builds/src-noconflict/mode-json.js', import.meta.url));
ace.config.setModuleUrl('ace/ext/language_tools', new URL('ace-builds/src-noconflict/ext-language_tools.js', import.meta.url))

Notice that this is a personalization. The general guidelines for ace-builds is to import ace-builds/webpack-resolver that would perform all the ace.config.setModuleUrl for the whole Ace set of themes, etc, but we are doing this to optimize the build.

In the new build with RsBuild, i try to import the components ESM-style :

import ace from 'ace-builds/src-noconflict/ace';
import 'ace-builds/css/ace.css';
import 'ace-builds/css/theme/cloud_editor.css';
import 'ace-builds/css/theme/cloud_editor_dark.css';
...

ace.config.setModuleLoader('ace/theme/cloud_editor', () => import('ace-builds/src-noconflict/theme-cloud_editor'));
ace.config.setModuleLoader('ace/theme/cloud_editor_dark', () => import('ace-builds/src-noconflict/theme-cloud_editor_dark'));
ace.config.setModuleLoader('ace/mode/json_worker', () -> import('ace-builds/src-noconflict/worker-json'));
ace.config.setModuleLoader('ace/mode/json', () => import('ace-builds/src-noconflict/mode-json'));
ace.config.setModuleLoader('ace/ext/language_tools', () => import('ace-builds/src-noconflict/ext-language_tools'));

However this causes an error when we try to click on the Code editor in the deployed app:

> Refused to execute script from 'https://mywebsite.dns/static/js/worker-json.js' because its MIME type ('text/html') is not executable.
> Uncaught NetworkError: Failed to execute 'importScripts' on 'WorkerGlobalScope': The script at 'https://mywebsite.dns/static/js/worker-json.js' failed to load.
    at fa52e38c-c584-4900-99db-963c09346b9b:1:1

This also happens if I attempt to directly import the generic ESM-compatible resolver ace-builds/esm-resover.

Since the culprit seems to be the worker (which is needed to do linting in the code editor), and since by RsBuild docs it seems that RsPack has a natural way to load workers, i tried to follow https://rsbuild.dev/guide/basic/web-workers, and changed the above lines as:

const worker = new Worker(new URL('ace-builds/src-noconflict/worker-json.js', import.meta.url));
ace.config.setModuleLoader('ace/theme/cloud_editor', () => import('ace-builds/src-noconflict/theme-cloud_editor'));
ace.config.setModuleLoader('ace/theme/cloud_editor_dark', () => import('ace-builds/src-noconflict/theme-cloud_editor_dark'));
ace.config.setModuleLoader('ace/mode/json', () => import('ace-builds/src-noconflict/mode-json'));
ace.config.setModuleLoader('ace/ext/language_tools', () => import('ace-builds/src-noconflict/ext-language_tools'));

Still no success, same errors in the console, plus some complain that ace is not defined that shows up at every rerender:

Uncaught ReferenceError: ace is not defined
    at ./node_modules/ace-builds/src-noconflict/worker-json.js (worker-json.js:219:1)
    at __webpack_require__ (worker-json.js:1626:1)
    at worker-json.js:1626:1
    at worker-json.js:1626:1

Can this be looked into ? I'm not understanding if this is a Bundler problem or Ace problem.

Thank you!

Reproduce link

.

Reproduce Steps

See description.

github-actions[bot] commented 3 days ago

Hello @carlomorelli. Please provide a reproduction repository or online demo. For background, see Why reproductions are required. Thanks ❤️

carlomorelli commented 1 day ago

Unfortunately this is my company's private internal app, so I cannot share any public link.

chenjiahan commented 1 day ago

Can you create a minimal reproduction?

carlomorelli commented 1 day ago

So, I may have just found the solution, following https://github.com/ajaxorg/ace/discussions/4815#discussioncomment-9044843.

I changed the worker loading line to follow the style of ace-builds old Webpack-resolver, but without the file-loader configuration:

import ace from 'ace-builds/src-noconflict/ace';
import 'ace-builds/css/ace.css';
import 'ace-builds/css/theme/cloud_editor.css';
import 'ace-builds/css/theme/cloud_editor_dark.css';
...

ace.config.setModuleLoader('ace/theme/cloud_editor', () => import('ace-builds/src-noconflict/theme-cloud_editor'));
ace.config.setModuleLoader('ace/theme/cloud_editor_dark', () => import('ace-builds/src-noconflict/theme-cloud_editor_dark'));
ace.config.setModuleUrl('ace/mode/json_worker', new URL('ace-builds/src-noconflict/worker-json', import.meta.url)); //THIS LINE
ace.config.setModuleLoader('ace/mode/json', () => import('ace-builds/src-noconflict/mode-json'));
ace.config.setModuleLoader('ace/ext/language_tools', () => import('ace-builds/src-noconflict/ext-language_tools'));

And now the worker works! The linting is performed correctly and malformed json errors are highlighted.

I'm still a little bit confused if this is a problem of RsPack/RsBuild (bundler) or Ace-builds (code editor component)? Ace project sustains that for ESM-compatible bundlers, we should use syntax ace.config.setModuleLoader(....).

I'm happy to close this bug if you believe it's an ace-builds problem.

9aoy commented 20 hours ago

It's hard to tell whose problem it is, since we don't know what ace-builds does. It looks like ace-builds do some wrappers around webworkers.