pmmmwh / react-refresh-webpack-plugin Goto Github PK
View Code? Open in Web Editor NEWA Webpack plugin to enable "Fast Refresh" (also previously known as Hot Reloading) for React components.
License: MIT License
A Webpack plugin to enable "Fast Refresh" (also previously known as Hot Reloading) for React components.
License: MIT License
Uncaught TypeError: connection.onClose is not a function
at createSocket (webpack-internal:///../../node_modules/@pmmmwh/react-refresh-webpack-plugin/src/runtime/createSocket.js:32)
at eval (webpack-internal:///../../node_modules/@pmmmwh/react-refresh-webpack-plugin/src/runtime/ErrorOverlayEntry.js:80)
at Object.../../node_modules/@pmmmwh/react-refresh-webpack-plugin/src/runtime/ErrorOverlayEntry.js (bundle.js:4276)
at __webpack_require__ (bundle.js:736)
this is the problem
let SocketClient;
if (typeof __webpack_dev_server_client__ !== 'undefined') {
SocketClient = __webpack_dev_server_client__;
} else {
SocketClient = __webpack_require__("../../node_modules/sockjs-client/lib/entry.js");
}
we are using https://github.com/shellscape/webpack-plugin-serve instead of https://github.com/webpack/webpack-dev-server
maybe @shellscape or @playma256 can help us with this one
First, thank you so much for your work on this project. I'm so excited to use it! π
While setting it up, I noticed what I think is an issue with the current logic around BabelDetectComponent
.
The detection works by checking whether a "component" in BabelDetectComponent.js
(part of the react-refresh-webpack-plugin aka RRWP runtime) was transformed by react-refresh/babel
. Note that, when RRWP is installed by a consumer, BabelDetectComponent.js
will end up in node_modules/@pmmmwh/react-refresh-webpack-plugin/src/runtime/
.
The issue is that, in general, the react-refresh/babel
transform shouldn't be applied to node_modules/
. (For example, the example in the readme applies the transform to a webpack rule that excludes /node_modules/
.) Unless a RRWP consumer has their build configured incorrectly, BabelDetectComponent.js
will never get transformed, and the "refresh check" check will always fail.
The example in this repo happens to work because it uses a local version of the runtime so the runtime modules don't match the loader exclusion rule.
For now, I can work around this by setting disableRefreshCheck: true
.
Having the option overlay set to false creates a fatal error in the runtime. This is due to the usage of WebpackProvidePlugin for the overlay.
react-refresh-webpack-plugin/src/index.js
Line 39 in c42efed
Webpack will try to load a module called false
creating a fatal error on the import.
In order to resolve it might be easiest to create a stub implementation like the on I have over here https://github.com/facebook/create-react-app/pull/8582/files#diff-b32bd53ea5f21f7fa8711bb475a72d78
It seems if you want to use the provide plugin you have to have an actual module there.
I attempted conditionally including/adding the module to provide plugin at all, and that creates errors where it attempts to be used, so I guess the usage sites could be updated instead.
Sometimes, the Promise reject data which is expected, but this plugin report error message by create an iframe#react-refresh-overlay element to html.body. That's boring, because I can see error message in Console.
This behavior will interrupted my mind and I have to close iframe by hand.
Does this plugin force me to use babel ? I'm developing react project while using only typescript loader in webpack. Can i use your awesome tool for my project or maybe you have plans to support other loaders ?
In createSocket
, I'm seeing a connection.onClose
is not a function error. In the SocketClient
conditional, it is not using webpack_dev_server_client. It is use SockJS.
Sorry I'm not sure where to turn to for help on this one. I'm pretty sure I've got the plugin registered properly, but fast refresh isn't working for most files. Also not sure what info you need and I can't give you access to the whole project.
Here is an example error:
[HMR] Cannot apply update. Need to do a full reload!
[HMR] Aborted because ./a.js is not accepted
Update propagation: ./a.js -> ./b.js -> ./c.js -> 37
hotApply@http://localhost:8000/d.js:476:30
hotUpdateDownloaded/<@http://localhost:8000/d.js:314:22
I added some debugging to src/runtime/RefreshModuleRuntime.js
and I can see that isReactRefreshBoundary
is false
for a.js
, b.js
, and c.js
. Not sure what 37
is but it's not triggering RefreshModuleRuntime
.
d
is an entry point in webpack: d: './c.js'
Hope you can help, thanks.
Sorry if this is a duplicate. I saw there was #10 but I think this is a little different. With webpack-dev-server
we're running it off another port locally. I looked at how wds
tries to establish the socket and noticed __resourceQuery
, but also that it falls back to trying to use document.currentScript
. For the time being would it be ok to add in trying to parse document.currentScript
and fall back to the current behavior? Happy to PR this, just wanted to check if it was something you'd want π
Using 0.3.0-beta.1
Module not found: Error: Can't resolve 'webpack-hot-middleware/client'
https://github.com/pmmmwh/react-refresh-webpack-plugin/blob/master/package.json#L62-L64
Hey there! Super excited about the work happening here.
One thing I noticed is that if I clone this repo, and run yarn build
in the example app, the bundled main.js contains references to
If this is unhelpful because it's still so early in the development of this plugin, feel free to close this. I'm happy to try to help if possible, but I'm not very familiar with webpack plugins or babel plugins, and wouldn't want to slow you down π
With HTML template like:
<script src="https://cdn.jsdelivr.net/npm/[email protected]/umd/react.production.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/umd/react-dom.production.min.js"></script>
And a webpack config including:
{
externals: {
react: 'React',
'react-dom': 'ReactDOM',
}
}
This plugin fails to work.
I'd like to dive into it a little, but with little knowledge about webpack I'm not sure I can find any valuable ideas.
When I compile the app and open the localhost webpage I am welcomed by this error:
There's no error in the console or in the terminal, and when I close this I can work on the app and reload works fine. This is just happening on page load looks like.
I'm using the plugin new ReactRefreshWebpackPlugin(), and adding this before HtmlWebpackPlugin
First of Thanks for this great plugin!
But i'm still struggeling getting it to work - i was experimenting with Webpack 5 and stumbled over this issue:
Error: NormalModuleFactory.afterResolve is no longer a waterfall hook, but a bailing hook instead. Do not return the passed object, but modify it instead. Returning false will ignore the request and results in no module created.
If you drop the return statement in the mentioned hook it will continue to compile, but there seems to be issues with detecting the react refresh plugin.
WARNING in React Refresh Plugin: The plugin is unable to detect transformed code from react-refresh. Did you forget to include "react-refresh/babel" in your list of Babel plugins? Note: you can disable this check by setting "disableRefreshCheck: true".
ERROR in [entry] [initial]
Cannot read property 'trimRight' of undefined
ERROR in [entry] [initial]
Cannot read property 'trimRight' of undefined
ERROR in [entry] [initial] polyfill.js
Cannot read property 'trimRight' of undefined
ERROR in [entry] [initial] app.js
Cannot read property 'trimRight' of undefined
Been looking at the source and this does not look like it was a trivial effort. I want to send you much love and thanks for donating so much of your time in order to improve the developer experience for many. β€οΈ
This can be treated as a non-bug, but it might make sense to mention it somewhere in the documentation.
Fast refresh or reload does not work if a component is written without naming it (as in the example below).
export default function() {
return <h1>Default Export Function</h1>;
}
But giving the component a name fixes the problem.
export default function MyFunc() {
return <h1>Default Export Function</h1>;
}
With the former, the entire page reloads saying Error: Aborted because filename.js is not accepted.
Uncaught ReferenceError: getModuleExports is not defined utils.js:169
Uncaught ReferenceError: handleCompileSuccess is not defined ErrorOverlayEntry.js:67
Work fine at latest chrome version
The 0.3.0-beta.2
docs say that options.overlay.sockIntegration
defaults to 'wds'
, but I don't see any part of the codebase responsible for providing that default.
As a result, running the webpack-dev-server example in the repo throws the following error:
TypeError [ERR_INVALID_ARG_TYPE]: The "request" argument must be of type string. Received undefined
at validateString (internal/validators.js:120:11)
at Function.resolve (internal/modules/cjs/helpers.js:77:5)
at getSocketIntegration (/[...]/react-refresh-webpack-plugin/examples/webpack-dev-server/node_modules/@pmmmwh/react-refresh-webpack-plugin/src/helpers/getSocketIntegration.js:11:43)
at ReactRefreshPlugin.apply (/[...]/react-refresh-webpack-plugin/examples/webpack-dev-server/node_modules/@pmmmwh/react-refresh-webpack-plugin/src/index.js:47:23)
This is because options.overlay.sockIntegration
is undefined
and eventually gets passed as an argument to require.resolve
.
Hello and thanks for an awesome plugin. it would be really useful for @openshift/console because of our massive websockets use (with this plugin there are no full page reloads so the websockets remain intact!)
webpack.config.ts
ForkTsCheckerWebpackPlugin
for type checking.I followed all suggested actions:
type-fest
It seems to work wonderfully! But the first recompilation after a code change triggers a full page reload, do we happen to know why it happens?
After some troubleshooting, I managed to finish with the following config -
// DEV SERVER config
devServer: {
writeToDisk: true,
progress: true,
hot: true,
inline: true,
},
Pastebin of the full webpack file
{
test: /(\.jsx?)|(\.tsx?)$/,
exclude: /node_modules\/(?!(bitbucket|ky)\/)/,
use: [
{ loader: 'cache-loader' },
{
loader: 'thread-loader',
options: {
// Leave one core spare for fork-ts-checker-webpack-plugin
workers: require('os').cpus().length - 1,
},
},
// THIS IS NEW, ALL THE REST WERE PRESENT
{
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env'],
plugins: [
'@babel/plugin-syntax-dynamic-import',
[
'@babel/plugin-transform-runtime',
{
regenerator: true,
},
],
isDevelopment && 'react-refresh/babel',
],
ignore: ['node_modules/bitbucket'],
},
},
//
{
loader: 'ts-loader',
options: {
// Always use the root tsconfig.json. Packages might have a separate tsconfig.json for storybook.
configFile: path.resolve(__dirname, 'tsconfig.json'),
happyPackMode: true, // This implicitly enables transpileOnly! No type checking!
transpileOnly: true, // fork-ts-checker-webpack-plugin takes care of type checking
},
},
],
},
Hey,
I'm not sure if this has to do with this Webpack plugin or with Webpack itself, with Webpack Dev Middleware and in general, I'm not even sure if this makes sense at all.
I've just spent two hours to get this really great plugin working in a custom Server Side Rendering environment that's currently using Webpack Dev Middleware (WDM) as Webpack's dev server and Webpack Hot Middleware (WHM) for HMR.
The issues I encountered:
localhost:8500
, my WDM is running on port 8501, but the socket connection is always created for window.location.port
and is not configurable (yet)runtime/createSocket.js
, it's still not working. There's an outgoing request to http://localhost:8501/sockjs-node/info?t=1579726105901
but it looks like WDM isn't listening to a /socksjs-node/info
route: Cannot GET /sockjs-node/info
POST /sockjs-node/213/kxx15upe/xhr_streaming
also gives me a 404$RefreshSig$ is not defined
, which seems obvious because they are only defined when we're in a browser environment.:ReferenceError: $RefreshSig$ is not defined
at eval (webpack:///./src/shared/i18n/IntlProvider.tsx?:17:10)
at Module../src/shared/i18n/IntlProvider.tsx (build/server/server.js:5202:1)
The last one makes sense but maybe we could just assign () => {}
noops to global.$RefreshSig$
and global.$RefreshReg$
?!
After all, I'm not really sure if this plugin does even make sense in universal rendering scenarios. If it does, I'd be happy to get some helpful hints how this could be integrated into my certainly little bit unusual but probably not that exotic setup.
// edit:
current state of my implementation attempt can be found here:
https://github.com/manuelbieh/react-ssr-setup/compare/feature/react-refresh
I tried integrating this for my custom React renderer which uses a JS environment more similar to Node (e.g. uses global
rather than window
). After I aliased global
as window
, it got stumped by the lack of an addEventListener
API:
file: node_modules/@pmmmwh/react-refresh-webpack-plugin/src/runtime/errorEventHandlers.js:85:10: JS ERROR TypeError: global.addEventListener is not a function. (In 'global.addEventListener(eventType, eventHandler)', 'global.addEventListener' is undefined)
What are the browser dependencies, and can anything be done to decouple it from the browser?
Error: [BABEL] /Users/taraslukavyi/Projects/traverz/traverz-admin/node_modules/@pmmmwh/react-refresh-webpack-plugin/src/runtime/BabelDetectComponent.js: Could not find plugin "proposal-numeric-separator". Ensure there is an entry in ./available-plugins.js for it. (While processing: "/Users/taraslukavyi/Projects/traverz/traverz-admin/node_modules/babel-preset-react-app/dependencies.js$0")
Can be reproduced if completely removed node_modules and package-lock and npm i
I'm experiencing a bug where upon changing a file, one of my modules becomes undefined
(causing part of the page to disappear).
I've mostly reduced my repro case. It seems related to cyclic dependencies. Repro steps:
Run yarn
and yarn start
, then visit http://localhost:7002/. You'll see the text "Hello: 100".
If you edit the "Hello" (in App.js), it updates properly.
If you edit the "100" (in SurveyOverview.js), the 100 disappears until next page reload.
This is because the DashboardPage import in routes.js becomes undefined (as you can see from the console logs). If you check the same import a tick later, it is correctly populated.
Not sure whether the bug is in react-refresh-webpack-plugin, react-refresh, or webpack.
I think if you do webpack-dev-server --inline it breaks this plugin. Took me a long time to figure out, I think it should be mentioned in the README.
Currently the runtime is not pre-processed, and this causes a lot of troubles when trying to use it with electron in a sandboxed environment.
I've been trying this plugin out on a few CRA-based projects (based on steps mentioned here). So far, things work well in terms of preserving state during development as I edit my components and hooks.
Question: Anytime I add or remove hooks, I get the an error stating that the number of hooks has changed between renders. The component is not re-mounted. I have to force a subsequent reload to recover. Is this the expected behavior at the moment?
Expectation: Similar to the behavior when using Dan's old wonky-scripts
experiment, adding/removing hooks should gracefully force a remount of the component if necessary rather than just bubbling the error all the way up.
I see the same behavior if I eject the CRA app and manually edit the webpack config per the README as well as if I use the feature branch version that hasn't yet been merged back to master.
Thanks for the work being put into bringing such a great React feature to web setups!
Error occurs on this line:
Plugin is called this way:
new ReactRefreshWebpackPlugin({
overlay: false,
}),
Steps to reproduce:
Hello, and thank you so much for working on this. π
I think Iβve noticed a small issue with the Sock options validation:
react-refresh-webpack-plugin/src/options.json
Lines 22 to 24 in 64a60d0
Searching for these options in the codebase do not yield any result (except for the aforementioned snippet):
I believe they are still used without the wds
prefix in the codebase. Would it be possible to either remove that validation, or update the names? :)
Has anybody tried this plugin with loadable-components?
I'm guessing that there will be a similar issue:
React version: 16.13.1
react-refresh version: 0.8.1
react-refresh-webpack-plugin version: 0.3.0-beta.6
Link to code example:
import * as React from 'react';
class ClassDefault extends React.Component {
constructor(props) {
super(props);
console.log('init class');
this.state = { state: 1 };
}
componentDidMount() {
console.log('class mount');
}
componentWillUnmount() {
console.log('class unmount');
}
render() {
const { state } = this.state;
return (
<div>
{state}
<h1>Default Export Class1</h1>
<div onClick={() => this.setState({ state: state + 1 })}>add</div>
</div>
);
}
}
export default ClassDefault;
import * as React from 'react';
function FunctionDefault() {
const [count, setCount] = React.useState(() =>Β {
console.log('init function');
return 1;
});
React.useEffect(() => {
console.log('function mount')
return function cleanup() {
console.log('function unmount');
};
}, []);
return <div>
<h1>Default Export Function {count}</h1>
<div onClick={() => setCount(count + 1)}>add</div>
</div>;
}
export default FunctionDefault;
class component will be unmount and mount with a brand new state when hmr.
function component will be unmount and mount with old state when hmr.
console shown as below
[HMR] Updated modules:
main.js:56904 [HMR] - ./src/ClassDefault.jsx
main.js:56904 [HMR] App is up to date.
main.0184bba375bf67f96cbd.hot-update.js:49 init class
main.js:57776 class unmount
main.0184bba375bf67f96cbd.hot-update.js:59 class mount
2main.js:56103 [WDS] App updated. Recompiling...
main.js:56642 [WDS] App hot update...
main.js:56904 [HMR] Checking for updates on the server...
main.js:62 XHR finished loading: GET "http://localhost:8080/ae89c6a9d927efd1cde1.hot-update.json".
(anonymous) @ main.js:62
hotDownloadManifest @ main.js:53
hotCheck @ main.js:296
check @ main.js:56964
(anonymous) @ main.js:57038
emit @ main.js:10952
reloadApp @ main.js:56646
ok @ main.js:56167
(anonymous) @ main.js:56414
sock.onmessage @ main.js:56026
EventTarget.dispatchEvent @ main.js:47130
(anonymous) @ main.js:47848
SockJS._transportMessage @ main.js:47846
EventEmitter.emit @ main.js:47046
WebSocketTransport.ws.onmessage @ main.js:49922
main.js:56904 [HMR] Updated modules:
main.js:56904 [HMR] - ./src/FunctionDefault.jsx
main.js:56904 [HMR] App is up to date.
main.js:57936 function unmount
main.ae89c6a9d927efd1cde1.hot-update.js:42 function mount
function component should be unmount and mount with a brand new state when hmr.
Thanks for your help.
And not 'react/index.js' or whatever. That's fine, but what I'm doing within our codebase is:
__react_createElement__
as its JSX pragma and these get injected during babel-loader
.ProvidePlugin
sees an unbound __react_createElement__
and imports node_modules/react/index.js
. (I don't know when this happens; maybe during the module templating? It's after the loaders in any case.)But the loader in this plugin is looking for 'react'
or "react"
in my source code. It looks in between step 1 and 2, so it sees __react_createElement__
but not the import of React from ProvidePlugin
.
The reason I do this is to avoid the import react from 'react';
that we don't explicitly use in our source code, and it lets me switch between React and Preact pretty easily. You could justifiably say "don't do that" and just call it an unsupported use case, and I acknowledge that I'm going off the beaten path a bit, so I wouldn't expect something like this to be supported out of the box. However, how would you feel about giving a little bit of control over how modules are detected? The current regex of /['"]react['"]/
could be the default, but for more bespoke situations I could pass /\b__react_createElement__\b/
or similar into the plugin options. What do you think? I'm willing to submit a pull request if you're okay with this.
(My other option is to create a loader that looks for my JSX pragma and injects 'react';
as a directive or /*'react'*/
as a comment. I'll do that just so I can proceed, but it feels a little weird.)
Hi, author. Could you please provide type definition file index.d.ts
for people who are writing configuration with typescript
Using 0.2.0
:
ERROR in ./node_modules/@pmmmwh/react-refresh-webpack-plugin/src/runtime/WHMEventSource.js
Module not found: Error: Can't resolve 'webpack-hot-middleware/client' in '/home/user/code/playground/node_modules/@pmmmwh/react-refresh-webpack-plugin/src/runtime'
@ ./node_modules/@pmmmwh/react-refresh-webpack-plugin/src/runtime/WHMEventSource.js 7:17-57
@ ./node_modules/@pmmmwh/react-refresh-webpack-plugin/src/runtime/createSocket.js
@ ./node_modules/@pmmmwh/react-refresh-webpack-plugin/src/runtime/ErrorOverlayEntry.js
@ multi ./node_modules/@pmmmwh/react-refresh-webpack-plugin/src/runtime/ReactRefreshEntry.js ./node_modules/@pmmmwh/react-refresh-webpack-plugin/src/runtime/ErrorOverlayEntry.js ./node_modules/@pmmmwh/react-refresh-webpack-plugin/src/runtime/BabelDetectComponent.js ./src
After adding this plugin to an ejected CRA project I get:
Cannot read property 'mode' of undefined
Are we assuming some particular webpack version?
I'm experiencing some incremental build performance issues. These are taken by sampling the Time output from webpack incremental builds.
RRWP+babel+ts-loader+ForkTsCheckerWebpackPlugins: 11-17 s
RRWP+babel+ts: 9-16 s
babel+ts-loader+ForkTsCheckerWebpackPlugin: 1.8-2.0s
babel+ts-loader: 1.5s-1.7s
babel: 1.4-2.1 s
ts-loader+ForkTsCheckerWebpackPlugin: 1.1-1.9 s
It looks like RRWP is adding 8-15 seconds build time to my typescript react project.
The config is as follows:
webpack.common.js
const path = require('path');
const webpack = require('webpack');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
module.exports = {
target: 'web',
entry: {
core: [
path.resolve(__dirname, 'ts/core/polyfill.ts'),
path.resolve(__dirname, 'ts/core/core.ts'),
],
reports: [
path.resolve(__dirname, 'ts/core/polyfill.ts'),
path.resolve(__dirname, 'ts/core/reports.ts'),
],
app: [path.resolve(__dirname, 'ts/apps/index.tsx')],
},
resolve: {
extensions: ['.ts', '.tsx', '.js', '.json', '.html'],
alias: {
Shared: path.resolve(__dirname, 'ts/shared'),
appA: path.resolve(__dirname, 'ts/apps/appA'),
appB: path.resolve(__dirname, 'ts/apps/appB'),
},
},
module: {
rules: [
// All image files will be handled here
{
test: /\.(png|svg|jpg|gif)$/,
loader: 'file-loader',
},
// All font files will be handled here
{
test: /\.(woff|woff2|eot|ttf|otf)$/,
loader: 'file-loader',
},
// All files with ".html" will be handled
{ test: /\.html$/, loader: 'html-loader' },
// All output ".js" files will have any sourcemaps re-processed by "source-map-loader".
{ enforce: 'pre', test: /\.js$/, exclude: [/node_modules/], loader: 'source-map-loader' },
],
},
plugins: [
// Clean dist folder.
new CleanWebpackPlugin({ verbose: true }),
// Split out library into seperate bundle and remove from app bundle.
new webpack.HashedModuleIdsPlugin(),
// avoid publishing when compilation failed.
new webpack.NoEmitOnErrorsPlugin(),
new HtmlWebpackPlugin({
inject: false,
title: null,
chunks: ['common', 'app', 'core'],
heads: ['common', 'core'],
bodys: ['app'],
filename: '../Views/Shared/_Layout.cshtml',
template: './Views/Shared/_Layout_Template.cshtml',
appMountId: 'react-app',
}),
new HtmlWebpackPlugin({
inject: false,
title: null,
chunks: ['common', 'core'],
heads: ['common', 'core'],
bodys: [],
filename: '../Views/Shared/_ExternalLayout.cshtml',
template: './Views/Shared/_ExternalLayout_Template.cshtml',
}),
new HtmlWebpackPlugin({
inject: false,
title: null,
chunks: ['common', 'reports'],
heads: ['common', 'reports'],
bodys: [],
filename: '../Views/Shared/_ReportLayout.cshtml',
template: './Views/Shared/_reportLayout_Template.cshtml',
}),
new CopyWebpackPlugin([
'ts/core/dependencies/telerik-report-viewer/telerikReportViewerTemplate-sass.html',
]),
// Moment.js is an extremely popular library that bundles large locale files
// by default due to how Webpack interprets its code. This is a practical
// solution that requires the user to opt into importing specific locales.
// https://github.com/jmblog/how-to-optimize-momentjs-with-webpack
// You can remove this if you don't use Moment.js:
new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
new ForkTsCheckerWebpackPlugin(),
],
// Some libraries import Node modules but don't use them in the browser.
// Tell Webpack to provide empty mocks for them so importing them works.
node: {
dgram: 'empty',
fs: 'empty',
net: 'empty',
tls: 'empty',
child_process: 'empty',
},
// Turn off performance hints during development because we don't do any
// splitting or minification in interest of speed. These warnings become
// cumbersome.
performance: {
hints: false,
},
// pretty terminal output
stats: { colors: true },
// Set up chunks
optimization: {
splitChunks: {
chunks: 'all',
cacheGroups: {
default: false,
vendors: false,
commons: {
name: 'common',
chunks: 'initial',
minChunks: 2,
},
},
},
},
};
and webpack.dev.js
const webpack = require('webpack');
const Merge = require('webpack-merge');
const CommonConfig = require('./webpack.common.js');
const postcssConfig = require('./postcss-config');
const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin');
const babelLoader = {
loader: 'babel-loader?cacheDirectory', //require.resolve('babel-loader'),
options: {
presets: ['@babel/react', '@babel/typescript', ['@babel/env', { modules: false }]],
plugins: [
'@babel/plugin-proposal-class-properties',
'@babel/plugin-proposal-optional-chaining',
'@babel/plugin-proposal-nullish-coalescing-operator',
'react-refresh/babel',
],
},
};
module.exports = Merge(CommonConfig, {
mode: 'development',
devtool: 'cheap-module-eval-source-map',
devServer: {
headers: {
'Access-Control-Allow-Origin': 'http://localhost:2354',
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, PATCH, OPTIONS',
'Access-Control-Allow-Headers': 'X-Requested-With, content-type, Authorization',
},
writeToDisk: true,
hot: true,
},
output: {
filename: '[name].js',
path: __dirname + '/dist',
publicPath: 'http://localhost:8080/dist/',
pathinfo: false,
},
module: {
rules: [
{
test: /\.(ts|tsx)$/,
exclude: /node_modules/,
use: [
babelLoader,
{
loader: 'ts-loader',
options: {
transpileOnly: true,
experimentalWatchApi: true,
},
},
],
},
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: [babelLoader],
},
{
// All css files will be handled here
oneOf: [
{
test: /^((?!\.module).)*scss$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
importLoaders: 2,
sourceMap: true,
},
},
postcssConfig,
{
loader: 'sass-loader',
options: {
implementation: require('node-sass'),
sourceMap: true,
},
},
],
},
{
test: /\.module.scss$/,
use: [
'style-loader',
{
loader: 'typings-for-css-modules-loader',
options: {
namedExport: true,
camelCase: true,
importLoaders: 2,
localIdentName: '[path][name]__[local]--[hash:base64:5]',
modules: true,
sourceMap: true,
},
},
postcssConfig,
{
loader: 'sass-loader',
options: {
implementation: require('node-sass'),
sourceMap: true,
},
},
],
},
// All files with ".less" will be handled and transpiled to css
{
test: /^((?!\.module).)*less$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
importLoaders: 2,
sourceMap: true,
},
},
postcssConfig,
{
loader: 'less-loader',
options: {
sourceMap: true,
},
},
],
},
{
test: /\.module.less$/,
use: [
'style-loader',
{
loader: 'typings-for-css-modules-loader',
options: {
namedExport: true,
camelCase: true,
importLoaders: 2,
localIdentName: '[path][name]__[local]--[hash:base64:5]',
modules: true,
sourceMap: true,
},
},
postcssConfig,
{
loader: 'less-loader',
options: {
sourceMap: true,
},
},
],
},
{
test: /^((?!\.module).)*css$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
importLoaders: 1,
sourceMap: true,
},
},
postcssConfig,
],
},
{
test: /module.css$/,
use: [
'style-loader',
{
loader: 'typings-for-css-modules-loader',
options: {
namedExport: true,
camelCase: true,
importLoaders: 2,
localIdentName: '[path][name]__[local]--[hash:base64:5]',
modules: true,
sourceMap: true,
},
},
postcssConfig,
],
},
],
},
],
},
plugins: [
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: JSON.stringify('development'),
},
PRODUCTION: false,
}),
new ReactRefreshWebpackPlugin({ disableRefreshCheck: true }),
],
});
After upgrading to 0.2.0, I noticed the following error:
ERROR in ./node_modules/@pmmmwh/react-refresh-webpack-plugin/src/runtime/WHMEventSource.js
Module not found: Error: Can't resolve 'webpack-hot-middleware/client' in '[...]/node_modules/@pmmmwh/react-refresh-webpack-plugin/src/runtime'
I believe this is because webpack sees this require
when bundling the injected runtime code:
And therefore tries to resolve and bundle that module. This code path isn't taken when a WDS client has been injected, but webpack doesn't know this at bundle time. My project doesn't use WHM so that module doesn't exist on my machine.
As a temporary workaround, installing WHM (npm i -D webpack-hot-middleware
) fixes the issue.
/cc @blainekasten
The plugin supports TypeScript (.tsx files)?
I'm getting the following error:
β ο½’wdmο½£: Error: The plugin is unable to detect transformed code from react-refresh. Did you forget to include "react-refresh/babel" in your list of Babel plugins? Note: you can disable this check by setting "disableRefreshCheck: true".
My babel.config.js:
module.exports = api => {
// This caches the Babel config
api.cache.using(() => process.env.NODE_ENV);
return {
presets: [
"@babel/preset-env",
"@babel/preset-react",
"@babel/preset-typescript"
],
// Applies the react-refresh Babel plugin on non-production modes only
...(!api.env("production") && { plugins: ["react-refresh/babel"] })
};
};
My webpack.config.js:
const webpack = require("webpack");
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const ReactRefreshWebpackPlugin = require("@pmmmwh/react-refresh-webpack-plugin");
module.exports = {
entry: "./src/index.tsx",
output: {
path: path.join(__dirname, "/dist"),
filename: "main.min.js"
},
devServer: {
hot: true
},
resolve: {
extensions: [".ts", ".tsx", ".js"]
},
module: {
rules: [
{
test: /\.(ts|tsx)$/,
exclude: /node_modules/,
use: [
{
loader: "babel-loader"
}
]
}
]
},
plugins: [
new ReactRefreshWebpackPlugin(),
new HtmlWebpackPlugin({
template: "./src/index.html"
})
]
};
I'm currently one of the maintainers on webpack-plugin-serve
and we also want to support it (specially for one my use cases).
But due to how tangled to wds and wdm this plugin is, we would need support for custom message handlers (similar to https://github.com/pmmmwh/react-refresh-webpack-plugin/blob/master/src/runtime/WHMEventSource.js) and a custom websocket properties!
Would these things be supported? Technically i don't want to embbed a custom message handler to this as well, i would like to leave it as generic as it would be so we can add more extensiability!
something like:
new ReactRefreshWebpackPlugin({
ws: {
url: localhost,
port: 12345
},
messageHandler: () => {
....
}
})
what do you guys think?
Edit: so we already have one PR on going, which would help 1/2 of this issue: #44
building error only result in console warning but no error overlayer
I notice in #1 (comment)
I think it works with multiple entry points. The main assumptions to me that would fail in any projects not from CRA would be the custom dev server middlewares and
cheap-module-source-map
(devtool). It also won't work with resource queries, custom socket implementations nor webpack under proxy servers, but I would consider them as advanced use cases anyhow, and thus will definitely need custom work.
then I'm now using offical webpack-dev-server, with no custom socket implementations, no proxy and using cheap-module-source-map
but overlayer still not work
what need to support overlayer? or It only work in CRA project?
Update:
I found that it's because I shoud not expect warning to cause error overlayer after debugγ but there is still a problem
I wonder if the overlay of this plugin is just a replacement of webpack-dev-server, and can we have a options to turn it off and only use webpack-dev-server's built-in overlayer?
Ref: facebook/react#16604
This issues tracks what is missing before this plugin attains "feature-parity" with the RN implementation and is representative of the "fast-refresh" branding.
iframe
) #3
console
injection)
window
)__resourceQuery
(wait for WDS v4) #52transportMode
or a plugin option with a similar footprint) #64context.hot
beta
stage (0.4.0-beta.6+
)We run webpack through a rails application and a gem called webpacker
We there for run our webserver at one port, but our dev server on another port.
Because the websocket just uses window.localtion.port
(https://github.com/pmmmwh/react-refresh-webpack-plugin/blob/master/src/runtime/createSocket.js#L26) it tries to connect to our web server port, not our web socket port.
This could be fixed a few ways.
sockPort
(https://webpack.js.org/configuration/dev-server/#devserversockport), with a fall back webpack-dev-servers port
and finally a fall back to window.localtion.port
This may also solve #36
Webpack is the foundation of several projects representing significant chunks the React ecosystem. Today, these are CRA, Next, and Gatsby. Although there are likely more.
Lately, we've been working on React features that work in integration with the compilation toolchain. Such as some of the data fetching / code splitting experiments that are in a very early stage. For those, we'll need to provide webpack plugins. Fast Refresh seems similar. There is a core experience we want to guarantee that in a way can be considered a part of the React brand.
We propose that this plugin be moved into the React monorepo as the canonical source. We've briefly discussed this with @pmmmwh and he doesn't have objections, so I'd like to raise this as a broader discussion. I think there's a few things that ideally need to happen before we do this:
module.hot.invalidate
API (webpack/webpack#10714). This should let us remove some hacks.What do you think?
Related to facebook/create-react-app#8091 in the latest CRA.
The same idle timeout seems to affect the websocket used in this plugin, as well (makes sense since it's constructing the same kind of connection).
Updating webpack from 4.42.1 to 4.43.0 seems to break the plugin. Downgrading back to 4.42.1 resolves the issue. I can't really understand why it fails the import.
My react-refresh-webpack-plugin version is 0.2.0
yarn run v1.22.4
$ NODE_ENV=development webpack-dev-server --env.development
internal/modules/cjs/loader.js:797
throw err;
^
Error: Cannot find module 'webpack'
Require stack:
- /my-project/node_modules/@pmmmwh/react-refresh-webpack-plugin/src/index.js
- /my-project/packages/client/webpack.config.js
- /my-project/packages/client/node_modules/webpack-cli/bin/utils/convert-argv.js
- /my-project/packages/client/node_modules/webpack-dev-server/bin/webpack-dev-server.js
at Function.Module._resolveFilename (internal/modules/cjs/loader.js:794:15)
at Function.Module._load (internal/modules/cjs/loader.js:687:27)
at Module.require (internal/modules/cjs/loader.js:849:19)
at require (internal/modules/cjs/helpers.js:74:18)
at Object.<anonymous> (/my-project/node_modules/@pmmmwh/react-refresh-webpack-plugin/src/index.js:2:17)
at Module._compile (internal/modules/cjs/loader.js:956:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:973:10)
at Module.load (internal/modules/cjs/loader.js:812:32)
at Function.Module._load (internal/modules/cjs/loader.js:724:14)
at Module.require (internal/modules/cjs/loader.js:849:19) {
code: 'MODULE_NOT_FOUND',
requireStack: [
'/my-project/node_modules/@pmmmwh/react-refresh-webpack-plugin/src/index.js',
'/my-project/packages/client/webpack.config.js',
'/my-project/packages/client/node_modules/webpack-cli/bin/utils/convert-argv.js',
'/my-project/packages/client/node_modules/webpack-dev-server/bin/webpack-dev-server.js'
]
}
error Command failed with exit code 1.
I have to set disableRefreshCheck: true
in order to successfully start up the webpack-dev-server, otherwise the startup seems to hang (I waited minutes, but not hours).
This is observable both on an ejected CRA app patched using instructions from the README as well as an existing CRA app that uses react-app-rewired/customize-cra.
When runtimeChunks: true
is enabled in the webpack config, I'm running into an issue with getting Rendered more hooks than during the previous render.
(or less, depending on what hooks get added/removed). To reproduce, add optimization: { runtimeChunks: true }
to the webpack config of wds-kitchen-sink
, and then add a hook to a functional component, save, and add another, The error should appear.
Edit - what I originally thought was incorrect π¦
Hi there,
Note:
I've created this issue in the customize-cra-react-refresh repo first and got referenced here.
There's a problem with fast-refresh and styled-components. It's making a full page reload. It works, however, when I make changes in a plain React component.
Reference issue:
esetnik/customize-cra-react-refresh#7 (comment)
The error I am seeing is. Please let me know if there's anything else you need.
createSocket.js:30 Uncaught TypeError: connection.onClose is not a function
at createSocket (createSocket.js:30)
at Object../node_modules/react-refresh-webpack-plugin/src/runtime/ErrorOverlayEntry.js (ErrorOverlayEntry.js:85)
at __webpack_require__ (bootstrap:785)
at fn (bootstrap:150)
at Object.0 (theme.ts:23)
at __webpack_require__ (bootstrap:785)
at checkDeferredModules (bootstrap:45)
at Array.webpackJsonpCallback [as push] (bootstrap:32)
at main.chunk.js:1
β― npm ls react-refresh react-refresh-webpack-plugin webpack-dev-server webpack
[email protected] /Users/xxx/frontend
βββ [email protected]
βββ [email protected]
βββ¬ [email protected]
βββ [email protected]
βββ [email protected]
Taken from facebook/react#16604 (comment)
const { addBabelPlugin, addWebpackPlugin, override } = require('customize-cra');
const ReactRefreshPlugin = require('react-refresh-webpack-plugin');
/**
* @param {ReactRefreshPluginOptions} [options] Options for react-refresh-plugin.
*/
const addReactRefresh = options =>
override(
process.env.NODE_ENV === 'development'
? addBabelPlugin('react-refresh/babel')
: undefined,
process.env.NODE_ENV === 'development'
? addWebpackPlugin(new ReactRefreshPlugin(options))
: undefined
);
/* config-overrides.js */
module.exports = override(addReactRefresh({ disableRefreshCheck: true }));
This plugin produces requests to http://localhost:3000/sockjs-node/info?t=...
for me (valid host/port!) that end up with 404.
It doesn't seem like my server serves this endpoint. I'm using electron-forge
.
The actual reloading works.
Is there a way to stop those info requests for running, so they don't show up as errors? It seems like there should be a noInfo
option for the socket...
I'm getting error when using with web workers:
Uncaught ReferenceError: $RefreshReg$ is not defined
A declarative, efficient, and flexible JavaScript library for building user interfaces.
π Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. πππ
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google β€οΈ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.