facebook / create-react-app

Set up a modern web app by running one command.
https://create-react-app.dev
MIT License
102.55k stars 26.8k forks source link

Add WebWorker Support #3660

Open dansiviter opened 6 years ago

dansiviter commented 6 years ago

Add ability to load WebWorkers (and SharedWorkers?) via the react-scripts. My use-case is for using latency (and debug) sensitive protocols over WebSocket which may get dumped by the server if no activity occurs.

There has been a lot of discussion regarding this on #1277 but no definitive answer and now closed. Also, I'm a server-side dev so JavaScript PR is not my forte, and neither is ejecting the scripts as that looks scary.

bates64 commented 4 years ago

For anyone using react-app-rewired who wants to have both React Refresh and Web Workers:

$ yarn add --dev customize-cra @pmmmwh/react-refresh-webpack-plugin react-refresh
// config-overrides.js

const {
    override,
    addBabelPlugin, getBabelLoader,
    addWebpackPlugin, addWebpackModuleRule,
} = require('customize-cra')
const ReactRefreshPlugin = require('@pmmmwh/react-refresh-webpack-plugin')

module.exports = (config, env) => {
    const prod = config.mode === 'production'
    const babelLoader = getBabelLoader(config)

    return override(
        // You can choose to just use worker-loader! instead if you want
        addWebpackModuleRule({
            test: /\.worker\.[jt]sx?$/,
            use: [
                { loader: 'worker-loader' },
                { loader: babelLoader.loader, options: babelLoader.options },
            ],
        }),

        !prod && addBabelPlugin('react-refresh/babel'),
        !prod && addWebpackPlugin(new ReactRefreshPlugin()),
    )(config, env)
}

Then in your app:

import MyWorker from './test.worker.js'

const worker = new MyWorker()
worker.onmessage = evt => console.log(evt.data)

This method allows you to use imports etc. within your worker, and it will be hot-reloaded. Note that the worker will be placed in its own chunk and fetched asynchronously - no need to use dynamic import.

For TypeScript:

// Add to react-app-env.d.ts

declare module '*.worker.ts' {
    class WebpackWorker extends Worker {
        constructor()
    }

    export default WebpackWorker
}
import MyWorker from './test.worker.ts' // .ts extension is required!
VicenteVicente commented 4 years ago

This works fine!

small clarification

// public/worker.js

// some worker
// src/index.js
const getPathFromPublic = path => `${process.env.PUBLIC_URL}/${path}`;

const workerPath = getPathFromPublic('worker.js');
const worker = new Worker(workerPath);

However, can you put the worker.js file in /src and prevent its minification/transpilation by another way?

educartoons commented 4 years ago

If anyone is looking for a solution with Typescript, you could try with react-app-rewired. Here you are the code working:

https://github.com/educartoons/creact-react-app-typescript-web-workers

It generates the build folder properly.

🍎

GarrisonD commented 4 years ago

@NicolasRannou thanks for sharing your experience!

works fine for me as well and I am super happy that don't need to eject or use react-app-rewired hacks.

grinsteindavid commented 3 years ago

up!

FezVrasta commented 3 years ago

+1 for Audio worklets, createScriptProcessor is deprecated so at some point we'll be unable to record audio without support for them.

FLGMwt commented 3 years ago

Thanks for the tip @NicolasRannou! (https://github.com/facebook/create-react-app/issues/3660#issuecomment-603922095)

In case it helps anyone, I've used this tip to set up a create-react-app typescript demonstration application with the minimum configuration necessary to consume Web Workers using Comlink: https://github.com/FLGMwt/comlink-web-worker-in-create-react-app. I couldn't get it to work importing the project through CodeSandbox, but you can try it out here: https://comlink-web-worker-in-create-react-app.netlify.app/

ryanaklein commented 2 years ago

Version 5 of create-react-app added support for webpack 5. webpack 5 added support for webworkers. This works for my use case and hopefully for the others! Now to figure out how to mock/inject into jest tests...

flyskywhy commented 2 years ago

ref to APP PixelShapeRN commit react -> react-native: let Web Worker with Support for CRA v5 (and Webpack 5) and doc Upgrade to react-scripts@5 and Add Web Workers support