Comments (16)
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
from workerize-loader.
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....
src/workers/mocks/sampleWorker.mock.ts
import { foo } from '../sampleWorker.worker';
export default () => ({
foo,
});
package.json
"jest": {
"moduleNameMapper": {
"workerize-loader!../workers/sampleWorker.worker": "<rootDir>/src/workers/mocks/sampleWorker.mock.ts"
}
}
from workerize-loader.
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: Cannot find module 'workerize-loader!./example.worker'.
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?
from workerize-loader.
Cannot find module 'workerize-loader!./workerize'.ts(2307)
TypeScript also doesn't like it.
from workerize-loader.
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
I was able to get this running without the shim by using require:
Component.tsx
const Worker = require( "workerize-loader!../../workers/workerFileName"); // eslint-disable-line import/no-webpack-loader-syntax
src/workers/workerFileName.js
export async function doStuff(data) {
// Worker code here
}
package.json
jest {
"moduleNameMapper": {
"workerize-loader!../../workers/workerFileName":"<rootDir>/src/workers/workerFileName.mock.js"
},
}
src/workers/workerFileName.mock.js
class WorkerFileName {
}
module.exports = WorkerFileName;
Now I have the following:
- Workers work in create-react-app with typescript
- Components that include the workerize-loader file no longer fail in jest
from workerize-loader.
src/workers/workerDeclarations.d.ts
declare module 'workerize-loader!*' {
type AnyFunction = (...args: any[]) => any;
type Async = (
...args: Parameters
) => Promise<ReturnType>;type Workerized = Worker &
{ [K in keyof T]: T[K] extends AnyFunction ? Async<T[K]> : never };function createInstance(): Workerized;
export = createInstance;
}
Using a flattened promise so async methods aren't double nested as Promise<Promise<return value>>
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;
}
from workerize-loader.
Eek! That's a surprisingly draconian lint rule.. maybe try with require?
const worker = require('workerize-loader!Workers/Worker')
from workerize-loader.
@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 jest.mock
to work for me. What were you picturing? If I try to use jest.mock
in my tests I was getting more 'unresolved' module errors.
An alternative, more flexible option I did think of though is to better use the regex in the moduleNameMapper
....
"jest": {
"moduleNameMapper": {
"^workerize-loader!(.*)/workers(.*)": "<rootDir>/src/workers/__mocks__$2"
}
}
and to make the actual mock file more easy to work with...
in src/workers/__mocks__/sampleWorker.worker.ts
import * as SampleWorker from '../sampleWorker.worker';
export default () => SampleWorker
That way any worker you add into the /workers
directory just needs a corresponding mock like the one above and you shouldn't really have to touch it again?
from workerize-loader.
Fixed it following @wilcoxmd's solution described above and also applied the alternative option but with a slightly tweak in the moduleNameMapper
regexp :
"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 ./__mocks__
folder where the worker file is (Eg: <workerFolder>/__mocks__/<workerFilename>
) since we want to have the workers and its mocks next to the other files organized by features. Our files structure looks like this:
├── src/
│ └── features/
│ └── foo/
│ ├── FooBar.worker.ts
│ └── __mocks__
│ └── FooBar.worker.ts
├── App.tsx
└── App.test.tsx
from workerize-loader.
Hmm - you shouldn't need any resolution config at all to use this.
npm i -D workerize-loader
import worker from 'workerize-loader!./foo';
from workerize-loader.
I did try that, but CRA has rules setup:
Unexpected '!' in 'workerize-loader!Workers/Worker'. Do not use import syntax to configure webpack loaders
from workerize-loader.
Perfect! Thanks for the tip, closing this issue then.
from workerize-loader.
Related: facebook/create-react-app#7741
from workerize-loader.
@wilcoxmd
It's not pretty, but I was able to get it to work using a shim js file to load the worker and export it to the TS file:
// 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.
from workerize-loader.
Awesome. Instead of moduleNameMapper
I'd probably just do jest.mock
. Glad you got that working and thanks for coming back here to show us how you did it.
from workerize-loader.
CRA uses eslint so just suppress that rule for the import line.
When I do, it works in development.
However when I then build the project, it fails without errors. It just doesn't generate anything.
Took me a few hours to figure out why.
Uncommenting the workerize loader import fixed the build right away.
So think twice before using this.
from workerize-loader.
Related Issues (20)
- Load worker scripts from other domain (CORS) HOT 3
- Jest HOT 3
- importScripts HOT 3
- Works in development but 'npm run build' silently fails to add index.html and JS bundles to build folder HOT 2
- Workerize loader runs out of memory HOT 5
- workerize-loader with Parcel bundler HOT 1
- npm install -D workerize-loader HOT 1
- How to make the output worker js file under /static rather than root directory in Create React App? HOT 1
- Feature request: rollup usage HOT 1
- Memory leak / lack of GC on Android Chrome when using workerize-loader
- worker.terminate() does not terminate worker thread
- Customizing worker bundles name results in "worker" word in file twice.
- Failed to execute 'postMessage' on 'DedicatedWorkerGlobalScope': function transformRequest(data, headers) { normalizeHeaderName(headers, 'Accept'); normalizeHeaderName(...<omitted>... } could not be cloned. HOT 1
- Uncaught TypeError: d is undefined
- FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory HOT 2
- FetchCompileWasmTemplatePlugin is not a constructor HOT 4
- Duplicate workers with inline and Webpack 5
- Duplicate worker code inside bundle file with inline option
- [path] replacer token passed to workerize-loader has stopped working in Webpack 5
- Breaks on latest gatsby, only when there is a webpack cache HOT 5
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from workerize-loader.