{"id":16429705,"url":"https://github.com/dominique-mueller/create-react-app-typescript-web-worker-setup","last_synced_at":"2025-03-21T04:31:32.369Z","repository":{"id":43676213,"uuid":"253606708","full_name":"dominique-mueller/create-react-app-typescript-web-worker-setup","owner":"dominique-mueller","description":"Using Web Workers in a TypeScript React project based on create-react-app.","archived":false,"fork":false,"pushed_at":"2022-02-24T16:03:24.000Z","size":828,"stargazers_count":35,"open_issues_count":1,"forks_count":9,"subscribers_count":2,"default_branch":"main","last_synced_at":"2024-10-12T08:24:01.521Z","etag":null,"topics":["comlink","create-react-app","react","typescript","web-worker","webpack"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dominique-mueller.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-04-06T20:20:42.000Z","updated_at":"2024-05-02T05:47:41.000Z","dependencies_parsed_at":"2022-09-04T04:53:27.712Z","dependency_job_id":null,"html_url":"https://github.com/dominique-mueller/create-react-app-typescript-web-worker-setup","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dominique-mueller%2Fcreate-react-app-typescript-web-worker-setup","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dominique-mueller%2Fcreate-react-app-typescript-web-worker-setup/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dominique-mueller%2Fcreate-react-app-typescript-web-worker-setup/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dominique-mueller%2Fcreate-react-app-typescript-web-worker-setup/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dominique-mueller","download_url":"https://codeload.github.com/dominique-mueller/create-react-app-typescript-web-worker-setup/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":221811369,"owners_count":16884305,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["comlink","create-react-app","react","typescript","web-worker","webpack"],"created_at":"2024-10-11T08:24:05.799Z","updated_at":"2024-10-28T09:20:43.152Z","avatar_url":"https://github.com/dominique-mueller.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n\n# create-react-app-typescript-web-worker-setup\n\nUsing **[Web Workers](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers)** in a\n**[TypeScript](https://github.com/microsoft/TypeScript)** **[React](https://github.com/facebook/react)** project based on\n**[create-react-app](https://github.com/facebook/create-react-app)**.\n\n\u003c/div\u003e\n\n\u003cbr\u003e\u003cbr\u003e\u003cbr\u003e\n\n## How to use Web Workers in a TypeScript React app\n\nThis project is an example React application that uses Web Workers. You can clone it and play around with it (see **[Commands](#commands)**).\nThe following sub-chapters explain how to setup Web Worker support in a `create-react-app` project, and how to use Web Workers in your app -\nboth vanilla and using **[Comlink](https://github.com/GoogleChromeLabs/comlink)**.\n\n\u003cbr\u003e\n\n### 1. Install dependencies\n\nFirst of all, we need a few new dependencies. In particular:\n\n- We need **[react-app-rewired](https://github.com/timarney/react-app-rewired)** to hook into the Webpack configuration that `react-scripts`\n  uses under the hood (without having to eject the config)\n- We use the Webpack **[worker-loader](https://github.com/webpack-contrib/worker-loader)** to integrate Web Workers into our build process\n\nAdd both dependencies to your `package.json` file and install them. For example:\n\n```diff\n  {\n    \"devDependencies\": {\n+     \"react-app-rewired\": \"2.1.x\",\n+     \"worker-loader\": \"3.0.x\"\n    }\n  }\n```\n\n\u003cbr\u003e\n\n### 2. Customize the build process\n\nFirst, replace all mentions of `react-scripts` within the `scripts` area of your `package.json` file by `react-app-rewired`. This enables us\nto tap into the build process in the next step. For example:\n\n```diff\n  {\n    \"scripts\": {\n-     \"start\": \"react-scripts start\",\n+     \"start\": \"react-app-rewired start\",\n-     \"build\": \"react-scripts build\",\n+     \"build\": \"react-app-rewired build\",\n-     \"test\": \"react-scripts test\",\n+     \"test\": \"react-app-rewired test\",\n    }\n  }\n```\n\nThen, create a file named `react-app-rewired.config.js` (or whatever name you prefer) within the root folder of your project. This file will\nbe used by `react-app-rewired` when the build process runs, and allows us to customize the underlying Webpack configuration before the build\nruns. Fill it with the following content:\n\n```js\n/**\n * React App Rewired Config\n */\nmodule.exports = {\n  // Update webpack config to use custom loader for worker files\n  webpack: (config) =\u003e {\n    // Note: It's important that the \"worker-loader\" gets defined BEFORE the TypeScript loader!\n    config.module.rules.unshift({\n      test: /\\.worker\\.ts$/,\n      use: {\n        loader: 'worker-loader',\n        options: {\n          // Use directory structure \u0026 typical names of chunks produces by \"react-scripts\"\n          filename: 'static/js/[name].[contenthash:8].js',\n        },\n      },\n    });\n\n    return config;\n  },\n};\n```\n\nFinally, reference the `react-app-rewired.config.js` file in your `package.json` file by adding the following line:\n\n```diff\n  {\n+   \"config-overrides-path\": \"react-app-rewired.config.js\",\n  }\n```\n\n\u003cbr\u003e\n\n### 3. Create and use a Web Worker\n\nNow you can start using Web Workers! Two things are important here: Files that contain a Web Worker must end with `*.worker.ts`, and they\nmust start with the following two lines of code in order to work nicely together with TypeScript:\n\n```ts\ndeclare const self: DedicatedWorkerGlobalScope;\nexport default {} as typeof Worker \u0026 { new (): Worker };\n\n// Your code ...\n```\n\nIn your application, you can import your Web Workers like a normal module, and instantiate them as a class. For example:\n\n```ts\nimport MyWorker from './MyWorker.worker';\n\nconst myWorkerInstance: Worker = new MyWorker();\n```\n\n\u003e Implementation pointers:\n\u003e\n\u003e - [Web Worker implementation](https://github.com/dominique-mueller/react-web-worker-experiment/blob/master/src/MyWorker.worker.ts)\n\u003e - [Using the Web Worker](https://github.com/dominique-mueller/react-web-worker-experiment/blob/master/src/App.tsx#L9)\n\n\u003cbr\u003e\n\n### Bonus: Using [Comlink](https://github.com/GoogleChromeLabs/comlink)\n\nUsing Web Workers as is comes with the additional overhead of messaging between the main thread and the worker thread.\n**[Comlink](https://github.com/GoogleChromeLabs/comlink)** is a library by Googlers that simplifies the usage of Web Workers by turning\nthe message-based communication into a \"remote function execution\"-like system.\n\nWithin your React app, you can use Comlink just like you would expect. For example, expose your API within your worker:\n\n```ts\nimport { expose } from 'comlink';\n\nexport default {} as typeof Worker \u0026 { new (): Worker };\n\n// Define API\nexport const api = {\n  createMessage: (name: string): string =\u003e {\n    return `Hello ${name}!`;\n  },\n};\n\n// Expose API\nexpose(api);\n```\n\nThen, from within you main thread, wrap the instantiated worker and use the worker API (asynchronously):\n\n```ts\nimport { wrap } from 'comlink';\nimport MyComlinkWorker, { api } from './MyComlinkWorker.worker';\n\n// Instantiate worker\nconst myComlinkWorkerInstance: Worker = new MyComlinkWorker();\nconst myComlinkWorkerApi = wrap\u003ctypeof api\u003e(myComlinkWorkerInstance);\n\n// Call function in worker\nmyComlinkWorkerApi.createMessage('John Doe').then((message: string) =\u003e {\n  console.log(message);\n});\n```\n\n\u003e Implementation pointers:\n\u003e\n\u003e - [Web Worker implementation](https://github.com/dominique-mueller/react-web-worker-experiment/blob/master/src/MyComlinkWorker.worker.ts)\n\u003e - [Using the Web Worker](https://github.com/dominique-mueller/react-web-worker-experiment/blob/master/src/App.tsx#L14)\n\n\u003cbr\u003e\n\n### A note on testing\n\nSoooo, Jest does not support Web Workers (see **[jest/#3449](https://github.com/facebook/jest/issues/3449)**). Plus, Jest does not use our\ncustomized Webpack configuration anyways. Thus - using one of the many ways you can mock stuff in Jest - mock away Web Workers when testing\ncode that instantes them / works with them.\n\n\u003cbr\u003e\u003cbr\u003e\n\n## Commands\n\nThe following commands are available:\n\n| Command               | Description                                        | CI                 |\n| --------------------- | -------------------------------------------------- | ------------------ |\n| `npm start`           | Creates a development build, running in watch mode |                    |\n| `npm run build`       | Creates a production build                         | :heavy_check_mark: |\n| `npm run start:build` | Runs the production build                          |                    |\n| `npm run test`        | Executes all unit tests                            | :heavy_check_mark: |\n| `npm run test:watch`  | Executes all unit tests, running in watch mode     |                    |\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdominique-mueller%2Fcreate-react-app-typescript-web-worker-setup","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdominique-mueller%2Fcreate-react-app-typescript-web-worker-setup","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdominique-mueller%2Fcreate-react-app-typescript-web-worker-setup/lists"}