-
Notifications
You must be signed in to change notification settings - Fork 86
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
Integration with Create React App #5
Comments
Hmm - you shouldn't need any resolution config at all to use this. npm i -D workerize-loader import worker from 'workerize-loader!./foo'; |
I did try that, but CRA has rules setup:
|
Eek! That's a surprisingly draconian lint rule.. maybe try with require? const worker = require('workerize-loader!Workers/Worker') |
CRA uses eslint so just suppress that rule for the import line. import worker from 'workerize-loader!./foo'; // eslint-disable-line import/no-webpack-loader-syntax |
Perfect! Thanks for the tip, closing this issue then. |
Related: facebook/create-react-app#7741 |
Has anyone gotten workerize-loader to work with create-react-app and typescript? I'm using react-scripts version 3.2, so should have the PR related to facebook/create-react-app#7741 included in my build. However, I keep running into a typescript error: I'm importing like so: // in ./Component.tsx
import ExampleWorker from 'workerize-loader!./example.worker'; // eslint-disable-line import/no-webpack-loader-syntax
// ./example.worker.ts
interface IWorkerMessage {
message: string;
time: number;
}
export const sayHi = async ({ message, time }: IWorkerMessage) => {
console.log('in worker function!, got message, ', message);
const start = Date.now();
let count: number = 0;
while (Date.now() - start < time) {
count++;
}
return count;
}; Anyone else seen this error / overcome it? |
@wilcoxmd // in ./ComponentWorkerShim.js
import ExampleWorker from 'workerize-loader!./example.worker'; // eslint-disable-line import/no-webpack-loader-syntax
export default ExampleWorker // in ./Component.tsx
import ExampleWorker from './ComponentWorkerShim';
// ... Then you have type issues to deal with when calling the worker, but at least it works. |
The above comment works great but I'm running into issues with jest when I use the shim. Without the shim jest works fine but typescript doesn't 😢 Edit Component.tsx
src/workers/workerFileName.js
package.json
src/workers/workerFileName.mock.js
Now I have the following:
|
I think I found another solution here as well, by using a hook for each worker I create. Using some of your tips above about the jest config, and some tips from here, I have the following that works for me and allows typed usage: src/workers/sampleWorker.worker.ts export function foo(a: number, b: number) {
return `Worker result: ${a + b}`;
} src/workers/workerDeclarations.d.ts declare module 'workerize-loader!*' {
type AnyFunction = (...args: any[]) => any;
type Async<F extends AnyFunction> = (
...args: Parameters<F>
) => Promise<ReturnType<F>>;
type Workerized<T> = Worker &
{ [K in keyof T]: T[K] extends AnyFunction ? Async<T[K]> : never };
function createInstance<T>(): Workerized<T>;
export = createInstance;
} src/hooks/useSampleWorker.ts // eslint-disable-next-line import/no-webpack-loader-syntax
import createWorker from 'workerize-loader!../workers/sampleWorker.worker';
import * as SampleWorker from '../workers/sampleWorker.worker';
const sampleWorker = createWorker<typeof SampleWorker>();
export const useSampleWorker = () => sampleWorker; Component.tsx import {useSampleWorker} from '../hooks/useSampleWorker';
function Component(props) {
const sampleWorker = useSampleWorker();
// ...
sampleWorker.foo(1000, 1000).then(result => console.log(result)) // result is of type 'string'
} then to make tests work.... import { foo } from '../sampleWorker.worker';
export default () => ({
foo,
}); package.json "jest": {
"moduleNameMapper": {
"workerize-loader!../workers/sampleWorker.worker": "<rootDir>/src/workers/mocks/sampleWorker.mock.ts"
}
} |
Awesome. Instead of |
@kentcdodds No problem! This one has bugged me for a bit because I've really wanted to use this package :) I had a little trouble getting An alternative, more flexible option I did think of though is to better use the regex in the "jest": {
"moduleNameMapper": {
"^workerize-loader!(.*)/workers(.*)": "<rootDir>/src/workers/__mocks__$2"
}
} and to make the actual mock file more easy to work with... import * as SampleWorker from '../sampleWorker.worker';
export default () => SampleWorker That way any worker you add into the |
Cannot find module 'workerize-loader!./workerize'.ts(2307) TypeScript also doesn't like it. |
When I do, it works in development. |
Using a flattened promise so async methods aren't double nested as declare module "workerize-loader!*" {
type FlattenedPromise<T> = unknown extends T
? Promise<T>
: T extends Promise<infer U>
? T
: Promise<T>;
type AnyFunction = (...args: any[]) => any;
type Async<F extends AnyFunction> = (
...args: Parameters<F>
) => FlattenedPromise<ReturnType<F>>;
type Workerized<T> = Worker &
{ [K in keyof T]: T[K] extends AnyFunction ? Async<T[K]> : never };
function createInstance<T>(): Workerized<T>;
export = createInstance;
} |
Fixed it following @wilcoxmd's solution described above and also applied the alternative option but with a slightly tweak in the "jest": {
"moduleNameMapper": {
"^workerize-loader(\\?.*)?!(.*)/([^/]*)$": "$2/__mocks__/$3"
}
} with the purpose of loading mocks from a file with the same name that the worker but located in the
|
I need to setup a worker in CRA. I have ejected CRA, so I can add the loader via Webpack configs.
However, I am not sure I am doing this correctly. I have been using the test/webpack.config.js as a helper. The only thing I noticed that was different, was the resolveLoader section in the webpack config. Have I missed something else?
Current config:
The text was updated successfully, but these errors were encountered: