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

Not generating a web worker script #36

Closed
vitolpoc opened this issue Jan 29, 2021 · 2 comments
Closed

Not generating a web worker script #36

vitolpoc opened this issue Jan 29, 2021 · 2 comments

Comments

@vitolpoc
Copy link

vitolpoc commented Jan 29, 2021

I have a setup with cra 3.4.3 with webpack 4.42.0 and storybook. I need the cra build to use comlink-loader and the storybook static build to ignore it (because when i run storyshots, the web worker loading fails with the following
Failed to construct Worker. Cannot be accessed from Origin null , logical since the page gets loaded using file:///

I changed my setup as follows to use singleton mode since i figured it would be easier to use different webpack configs for cra and storybook

the module that will become a worker

/* /src/workers/fuseSearch.worker.ts */

import Fuse from "fuse.js";
import { TRow } from "../types/Objects";

export async function fuseSearch(data: TRow[], options: any): Promise<TRow[]> {
    // eslint-disable-next-line @typescript-eslint/ban-ts-ignore
    //@ts-ignore
    // eslint-disable-next-line
    if (typeof self === "object" && self.document !== undefined && self.document === document) {
        console.log("running on main thread");
    } else {
        //were this a web worker, self would be instanceof DedicatedWorkerGlobalScope and self.document undefined
        console.log("running in web worker");
    }
    const { field, term } = options;
    const fuse = new Fuse(data, {
        keys: ["data", field],
        useExtendedSearch: true,
    });
    const searchTerm = term
        .trim()
        .split(" ")
        .join(" '");
    return fuse.search(`'${searchTerm}`).map(({ item }) => item);
}

I then call my worker as outlined in the documentation, with await

import { fuseSearch } from "../workers/fuseSearch.worker";
...
useEffect(() => {
    async function runSearch() {
        const result = await fuseSearch(available, { field, term });
        setFilterResult(result);
    }
    runSearch();
}, [...]);

my cra webpack config (using react-app-rewired)

//config-overrides.js
module.exports = function override(config) {
    // fails when i append to the rules array, prepending seems to go through
    config.module.rules.shift({
        test: /\.worker\.(js|ts)$/i,
        use: [
            {
                loader: "comlink-loader",
                options: {
                    singleton: true,
                },
            },
        ],
    });
    return config;
};

and my storybook webpack config simply doesn't declare a comlink-loader therefore skipping the web worker wrapping altogether.

problem 1

I see no webworker in my sources tab, and fuseSearch runs on the main thread! comlink-loader does not generate a script for the worker.
Is the config i outlined above valid? why is not generating a web worker script?

problem 2

When i changed the config override to have cofing.modules.rules.push instead of cofing.modules.rules.shift I got the following error message

Uncaught Error: Module parse failed: Unexpected token (5:36)
File was processed with these loaders:
* ./node_modules/comlink-loader/dist/comlink-worker-loader.js
* ./node_modules/eslint-loader/dist/cjs.js
* ./node_modules/eslint-loader/dist/cjs.js
You may need an additional loader to handle the result of these loaders.
| import { TRow } from "../types/Objects";
|
> export async function runWorker(data: TRow[], options: any): Promise<TRow[]> {
| const { field, term } = options;
| const fuse = new Fuse(data, {
at Object../node_modules/comlink-loader/dist/comlink-worker-loader.js!./node_modules/eslint->
loader/dist/cjs.js?!./node_modules/eslint-loader/dist/cjs.js?!./src/workers/fuseWorkerImpl.worker.ts (bootstrap:83)

which i assume is logical? because the comlink-loader needs to run first?

Edit: specified webpack and react-scripts versions

@vitolpoc
Copy link
Author

solved it. it was more of a webpack config problem, once i added a babel-loader entry it worked

config.module.rules.push({
		test: /\.worker\.(js|ts)$/i,
		use: [
			{
				loader: "comlink-loader",
				options: {
					singleton: true,
				},
			},
			/* below loader options section copied from node_modules/react-scripts@3.4.3/config/webpack.config.js#382 */
			{
				loader: require.resolve("babel-loader"),
				options: {
					customize: require.resolve("babel-preset-react-app/webpack-overrides"),
					babelrc: false,
					configFile: false,
					presets: [require.resolve("babel-preset-react-app")],
					cacheIdentifier: getCacheIdentifier(isEnvProduction ? "production" : isEnvDevelopment && "development", [
						"babel-plugin-named-asset-import",
						"babel-preset-react-app",
						"react-dev-utils",
						"react-scripts",
					]),
					cacheDirectory: true,
					cacheCompression: false,
					compact: isEnvProduction,
				},
			},
		],
	});
	```

@jobh
Copy link

jobh commented Sep 23, 2021

Just a comment, the original problem might have been that shift was used instead of unshift,

config.module.rules.shift({...})

shift removes the first element (pop-beginning), unshift adds a first element (push-beginning).

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

2 participants