Comments (30)
@blacksteed232 @GuskiS
I have some workarounds.
Sloppy
-
In the entry of your Worker, add the following two lines:
self.$RefreshReg$ = () => {}; self.$RefreshSig$$ = () => () => {};
-
This is basically a "polyfill" for helpers expected by
react-refresh/babel
Simple
- You don't have to mess with configurations
- Ensure all exports in the whole code path does not contain anything in
PascalCase
, which will make the Babel plugin do nothing when it hits your files - In general, the
PascalCase
naming scheme should be reserved for React components only, and I assume there wouldn't exist any React components within a Web Worker - Slight issue is when you have dependencies with that naming scheme, but most setups bypass
node_modules
from Babel anyways
Robust
-
Similar to what @blacksteed232 attempted, but with Webpack's
oneOf
rule -
Alter the Webpack module rules (the section for JS-related files) as follows:
{ rules: [ // JS-related rules only { oneOf: [ { test: /\.[jt]s$/, include: '<Your worker files here>', exclude: /node_modules/, use: { loader: 'babel-loader', options: { // Your Babel config here }, }, }, { test: /\.[jt]sx?$/, include: '<Your files here>', exclude: ['<Your worker files here>', /node_modules/], use: { loader: 'babel-loader', options: { // Your Babel config here }, }, }, ], }, // Any other rules, such as CSS { test: /\.css$/, use: ['style-loader', 'css-loader'], }, ], }
Edit:
I also would suggest to not run ReactRefreshPlugin
through WorkerPlugin
- messing with module templates in child compilers for a different realm does not end well from my testing while figuring out the two solutions above. It COULD be made to work, but I currently don't see a good path towards that goal.
I do understand that it is a bit of work to add this configuration, but I also hope that people can understand that react-refresh
and this plugin weren't designed to be used "standalone" or in non-React related code paths. For the case of Web Workers, in my honest opinion, I think they should be compiled from the start separately (in terms of TypeScript/Babel transpilation) - import/exports are not available natively, and the global object is different.
Hopefully this provided some insight and hopefully the workarounds above have solved your problems!
from react-refresh-webpack-plugin.
@pmmmwh - I haven't had much time to looking into this yet.
But I believe the issue is caused because workers don't have window. And at least with https://github.com/developit/workerize-loader and https://github.com/GoogleChromeLabs/worker-plugin it suggests changing your webpack config to use this
to allow for Hot Module Replacement
output: {
globalObject: "this"
},
When you do this Webpack is throwing on
bootstrap:22 Uncaught ReferenceError: window is not defined
at __webpack_require__ (bootstrap:22)
at bootstrap:97
at bootstrap:97
Which is lines (
react-refresh-webpack-plugin/src/helpers/createRefreshTemplate.js
Lines 13 to 15 in 615157e
It appears if you reference window
at all here webpack throws even if its to check if window
exists.
Changing these lines to use this
seems to work for me for both when I've changed the globalObject to this
and to when I have left it as window
.
from react-refresh-webpack-plugin.
This might be useful to add to documentation, maybe worker section? As it requires additional changes for workers 🤔
I'll probably add a TROUBLESHOOTING.md
soon and move all the FAQs there from the readme. I've been hoping to rewrite documentation so stuff will be clearer.
from react-refresh-webpack-plugin.
Happy that the resolutions worked for both of you!
But that got me thinking, could it be possible that I'm somehow importing that code as worker and directly?
For example, that file contains class, in my code it is only used as worker(new Worker("./myworker.worker.ts")
), but in few typing files I use it as type definition to see what methods are being exposed.Could something in bundling process mess it up?
I haven't analyzed bundle output in a while, will give it a try later.
If you are on TypeScript 3.8+, I highly suggest checking out the import type
syntax, this option for TypeScript and this option for Babel's TypeScript transpilation. Type imports ensures that no side effects will be ran from the imported module, and they will be erased completely after bundling.
from react-refresh-webpack-plugin.
Thanks, when I added:
(global as any).$RefreshReg$ = () => {};
(global as any).$RefreshSig$$ = () => () => {};
it didn't show error. (CRA eslint rule didn't allow me to use self
)
But that got me thinking, could it be possible that I'm somehow importing that code as worker and directly?
For example, that file contains class, in my code it is only used as worker(new Worker("./myworker.worker.ts")
), but in few typing files I use it as type definition to see what methods are being exposed.
Could something in bundling process mess it up?
I haven't analyzed bundle output in a while, will give it a try later.
from react-refresh-webpack-plugin.
I wanted to post this here in case someone else is encountering the same issue as I was.
We are using worker-loader
instead of worker-plugin
.
After trying the suggested Robust solution, I still kept getting the error Cannot read properties of undefined (reading 'signature')
from the worker bundle (__webpack_require__.$Refresh$
being undefined), despite verifying that worker files were excluded from babel-loader
. This could still be some misconfiguration on my part.
Fix inspired by
Usage in webpack configuration is to replace ReactRefreshWebpackPlugin
with an extended WorkerSafeReactRefreshWebpackPlugin
.
import { Template } from 'webpack';
import ReactRefreshWebpackPlugin from '@pmmmwh/react-refresh-webpack-plugin';
// This ensures we don't get runtime errors by ensuring workers have stubbed out expected functions.
export default class WorkerSafeReactRefreshWebpackPlugin extends ReactRefreshWebpackPlugin {
apply(compiler) {
super.apply(compiler);
compiler.hooks.compilation.tap('ReactRefreshWebpackPlugin', (compilation) => {
const hookVars = compilation.mainTemplate.hooks.localVars;
hookVars.tap('ReactFreshWebpackPlugin', (source) =>
Template.asString([
source,
'',
'// noop fns to prevent runtime errors during initialization',
'__webpack_require__.$Refresh$ = { register: function () {}, signature: function() { return function(type) { return type; } } };',
]),
);
});
}
}
from react-refresh-webpack-plugin.
Can you provide me some steps to reproduce? I'm not too familiar with Web Workers and don't have much context on what is broken.
from react-refresh-webpack-plugin.
I am getting same error as author with version 0.2.0
I have added component that used in worker to babel ignore
from react-refresh-webpack-plugin.
I am getting same error as author with version 0.2.0
I have added component that used in worker to babel ignore
Can you provide more info on your setup?
from react-refresh-webpack-plugin.
I am getting same error as author with version 0.2.0
I have added component that used in worker to babel ignoreCan you provide more info on your setup?
We are using worker-loader from webpack to load workers to DOM.
{
test: /\.worker\.js$/,
use: {
loader: 'worker-loader',
options: {
fallback: true,
name: 'scripts/[hash].worker.js',
publicPath: '/',
},
},
},
I don't know why, but only last of the components chain have this error.
I added this component to babel ignore.
"development": {
"ignore": [
"**/Element.js",
"^^^ This needed to avoid transform of Element.js in Web Worker with react-refresh/babel, possible in future it can be removed"
],
"plugins": [
["babel-plugin-module-resolver", { "root": ["./src/routes/builder"] }],
["@babel/plugin-transform-runtime", { "regenerator": true }],
"transform-flow-strip-types",
"@babel/plugin-syntax-export-default-from",
"@babel/plugin-syntax-dynamic-import",
"@babel/plugin-proposal-class-properties",
"react-refresh/babel"
]
},
The chain is Worker -> renderMarkup -> nodesToString -> Provider -> Node Component -> Element Component
It looks like problem caused by react-refresh/babel
from react-refresh-webpack-plugin.
It looks like problem caused by
react-refresh/babel
I cannot comment on this without having a look at a reproducible example.
I'll close this for now, since #29 addressed the original issue.
If you still face this issue, please feel free to open another issue.
from react-refresh-webpack-plugin.
Hmm, still getting some weird error:
When I click on the 220 line in devtools I see this output and there is no line 220:
module.exports = __webpack_public_path__ + "static/js/autocable.chunk.worker.js"
But the worker code is fine and it is running as expected 🤔
Using latest version.
from react-refresh-webpack-plugin.
Hmm, still getting some weird error
The plugin now rewrites all all references to $RefreshReg$
and $RefreshSig$
so this is most likely a configuration error.
Did you exclude the worker file from being processed by react-refresh/babel
or the plugin? You either have to set it up so that it passes through both of them or none of them.
from react-refresh-webpack-plugin.
I'm using this configuration: https://codesandbox.io/s/using-craco-ei2ek?file=/craco.config.js
And in code:
const worker = comlink.wrap(new Worker("lib/AutoCable/index.worker.ts", { name: "autocable", type: "module" }));
I don't have any other configuration for that worker 🤔
from react-refresh-webpack-plugin.
I don't have any other configuration for that worker 🤔
You SHOULD have. You should have added processing/chunking behaviour for that worker because CRA does not support Workers out of the box. I would assume you added something like worker-plugin
?
There are two choices.
-
use the
plugins
options from it (ref) and add this plugin to the list. -
Exclude the loader file from Babel's processing, which means you have to modify the rule to add exclusions (which I do think is a bit verbose), or just move it out of your source folder.
Here's a demonstration of approach 2 -
https://codesandbox.io/s/using-craco-workers-qip7m
from react-refresh-webpack-plugin.
My apologies, somehow tunnel-read what you meant. Yes, I'm using worker-plugin
. Will implement 1st suggested approach tomorrow, will report if there are any issues.
This might be useful to add to documentation, maybe worker section? As it requires additional changes for workers 🤔
from react-refresh-webpack-plugin.
First approach didn't work, tried both ways - with named plugin or by initializing directly. I'm getting the same error.
Second approach feels like a lot of work, cause my worker is quite complicated.
from react-refresh-webpack-plugin.
First approach didn't work, tried both ways - with named plugin or by initializing directly. I'm getting the same error.
Second approach feels like a lot of work, cause my worker is quite complicated.
Can you create a reproducible example? There's no way I can offer more help without any context.
from react-refresh-webpack-plugin.
i have same problem because of using react-refresh/babel
in production by mistake, So just using react-refresh/babel
in dev
from react-refresh-webpack-plugin.
I'm not using it in production, as I'm getting error in dev.
Also, I'm not able to recreate broken example.
from react-refresh-webpack-plugin.
I'm not using it in production, as I'm getting error in dev.
Also, I'm not able to recreate broken example.
I'm not sure how to help further.
Clearly here the problem is that there exist some files that are linked by the worker plugin that evaded processing by this plugin, but got caught processed by the Babel plugin. This is something that I cannot help with (unfortunately), and would rely on either worker plugin wiring things up correctly, or tweaking Babel manually.
I can take a look at the craco config if provided, then maybe I can see if something is wrong.
from react-refresh-webpack-plugin.
@pmmmwh I don't know much about the inner workings of this plugin, and honestly, I'm just looking everywhere to see bits of information. Looks like on next.js
side, they also faced similar issue with worker-loader
and managed to find a workaround
Personally, I don't know if I did the right thing but here's what I did. I create 2 rules for babel in webpack
config:
- With
react-refresh
plugin but exclude the worker from the scope - Without
react-refresh
plugin but include only the worker
This doesn't work as when I run my app, the error overlay shows up with the same error message$RefreshSig$ is not defined
// ...
module: {
rules: [
{
test: /\.(js|ts)x?$/,
exclude: [
/node_modules/,
'app/workers/myWorker.ts',
],
use: [
{
loader: require.resolve('babel-loader'),
options: {
cacheDirectory: true,
presets: [
'@babel/preset-env',
'@babel/preset-react',
'@babel/preset-typescript',
],
plugins: [
// ... other plugins
isEnvDevelopment && 'react-refresh/babel'
].filter(Boolean)
}
},
]
},
// repeat the block another time to make sure the Worker is transpiled (since I use TS)
{
test: /Worker\.(js|ts)x?$/,
exclude: [
/node_modules/,
],
use: [
{
loader: require.resolve('babel-loader'),
options: {
cacheDirectory: true,
presets: [
'@babel/preset-env',
'@babel/preset-react',
'@babel/preset-typescript',
],
plugins: [
// ... other plugins
// isEnvDevelopment && 'react-refresh/babel'
].filter(Boolean)
}
},
]
}
plugins: [
new WorkerPlugin(),
new ReactRefreshWebpackPlugin(),
// ...
};
from react-refresh-webpack-plugin.
@pmmmwh I don't know much about the inner workings of this plugin, and honestly, I'm just looking everywhere to see bits of information. Looks like on
next.js
side, they also faced similar issue withworker-loader
and managed to find a workaround
That workaround won't work for us as the helpers we inject are hoisted in the Webpack global, not the actual global scope (window
, global
, self
). We rewrite all helpers when we detect its usage (so if the file is not being processed by the plugin, we cannot do anything).
Personally, I don't know if I did the right thing but here's what I did. I create 2 rules for babel in
webpack
config
Try inverting the order of the two blocks - the more specific test
rule should always come first.
from react-refresh-webpack-plugin.
@pmmmwh Thanks, inverting the order doesn't help.
Regarding what you said earlier:
Clearly here the problem is that there exist some files that are linked by the worker plugin that evaded processing by this plugin, but got caught processed by the Babel plugin. This is something that I cannot help with (unfortunately), and would rely on either worker plugin wiring things up correctly, or tweaking Babel manually.
Does this mean if I could have react-refresh/babel
not looking at this worker file at all then it should be ok right?
(I really hoped my trick earlier would work but it didn't so I wonder why...)
from react-refresh-webpack-plugin.
Does this mean if I could have
react-refresh/babel
not looking at this worker file at all then it should be ok right?
(I really hoped my trick earlier would work but it didn't so I wonder why...)
Theoretically yes.
However upon looking at worker plugin issues it seems that it is slightly more complicated because some plugin hooks would bleed into child compilers (which is what worker plugin uses). I will have to take a look at the final bundle to see what is truly messed up.
(If possible I would love a repro)
from react-refresh-webpack-plugin.
@pmmmwh Thank you so much! Can't wait to be able to try this out.
I will try to create a repro for you, my codebase is internal so might take some time for me to create a minimal reproducible though
from react-refresh-webpack-plugin.
@pmmmwh Thank you so much! Can't wait to be able to try this out.
I will try to create a repro for you, my codebase is internal so might take some time for me to create a minimal reproducible though
I'll try creating my own in the mean time 🤣
Honestly though, I'm quite shocked that somehow it is more difficult to get things working with Workers than with non-browser renderers 🙈 I really want this to be as smooth as possible ...
from react-refresh-webpack-plugin.
@blacksteed232 Seems like your second config block have a typo? Your worker's name is app/workers/myWorker.ts
while you're matching Worker\.(js|ts)x?$
from react-refresh-webpack-plugin.
@pmmmwh I can confirm that the Robust
approach work, the problem for my snippet above is not about the wrong RegExp
but more that my worker imports code from other places in the project that has PascalCase
.
Due to that, Sloppy
and Simple
didn't quite work. But by doing Robust
, i.e. well-isolating jsx
and non-jsx
files, I could get my code to work. Though your Simple
explanation really shed some lights on the problem I got, I started by commenting out the imports.
So thank you so much @pmmmwh!!
I was super anxious that I can't really use this nice plugin since I have quite a complicated setup (i.e. Mobx
, Typescript
, worker-plugin
, etc.), so finger-cross.
from react-refresh-webpack-plugin.
@pmmmwh Thanks, I did not pay attention to this when the version was released. Seems like the default
should work fine for us as of now since the import statement will be purged if it's type-only.
My web-worker was actually using a function from another module, so I think babel
takes those into account as well, if I don't comment out the imports and just don't use them, everything works fine.
from react-refresh-webpack-plugin.
Related Issues (20)
- Cannot read properties of undefined (reading 'call') at at options.factory HOT 1
- Relative imports outside of src/ are not supported. HOT 6
- Can I use a custom domain and SSL cert for the cable URL? HOT 1
- Tsc error when upgraded to 0.5.X from 0.4.X HOT 1
- Is that possible to refresh when files in node_modules are changed?
- Rewrite window.fetch method It will not work!
- Using with webpack-hot-middleware, issues
- npm ERR! ERESOLVE could not resolve HOT 1
- Security vulnerability - loader-utils 2.0.4 HOT 2
- Getting lot's of *.hot-update.js files in dist folder HOT 1
- Not working with multiple entry points in webpack where one entry does not use react
- Expand webpack-dev-server dev dependency to include the newes semver 5.x HOT 1
- erroroverlay
- There are some edge cases where we have to manually refresh the page to see the change. HOT 1
- Issues when combining webpack HMR and react-refresh-webpack-plugin HOT 10
- `useEffect` inside refreshed code runs needlessly HOT 1
- Alternative for React Class Components. HOT 1
- Issues with peer dependencies found HOT 1
- Memory cleanup doesn't happen on incremental compiles HOT 3
- Using the external configuration item of webpack in the development environment can cause react refresh to fail HOT 4
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 react-refresh-webpack-plugin.