Giter VIP home page Giter VIP logo

react-refresh-webpack-plugin's People

Contributors

agarun avatar amwam avatar audunolsen avatar austaras avatar blainekasten avatar bmdoherty avatar bsthun avatar dependabot[bot] avatar equinox avatar frehner avatar gopeter avatar hailwood avatar keraf avatar kirkcola avatar latin-1 avatar marcello3d avatar miguel-silva avatar mmhand123 avatar naruaway avatar patrikholcak avatar pmmmwh avatar rap2hpoutre avatar ro-savage avatar shoyuf avatar soilspoon avatar test-ac avatar tinytinyeye avatar vikpe avatar wojtekmaj avatar xandris avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

react-refresh-webpack-plugin's Issues

Suggestion: Don't display error iframe

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.

BabelDetectComponent logic doesn't work for consumers

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.

Allow custom ports for websockets

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.

  1. You could allow a customer port to be passed to createSocket
  2. You could use the port that is specified in webpack-dev-server's config 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

Incremental build performance issues

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 }),
  ],
});

Plugin requires naming of the component being exported

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.

Add custom EventSource and web socket url

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

Question RE: adding/removing hooks...

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 on app start while loading the page

When I compile the app and open the localhost webpage I am welcomed by this error:
image

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

Regression: webpack-hot-middleware is not optional #66

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

Type Definition

Hi, author. Could you please provide type definition file index.d.ts for people who are writing configuration with typescript

Try integrating into Create React App

I've tried integrating this into an ejected CRA project but got stuck (#6).

This gets me thinking: perhaps, the next milestone is to get it to a point where we can create a pull request for CRA? What's missing for that to work? cc @iansu

404 with http://localhost:3000/sockjs-node/info?t=...

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...

[Meta] Releasing this Plugin as "Fast Refresh" capable

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.

Tasks

  • Error Recovery
    • Module Import Errors
      • Static Imports
      • Dynamic Imports (Lazy)
      • Add/Remove Imports
      • Concurrent Mode
    • Syntax Errors
      • File Level
      • Component Level
      • Life-cycle Method Level
      • Function Return Level
    • Runtime Errors
      • Rendering Errors
      • React-related Errors
    • Root Mounting Errors (Full Refresh)
      • Error on Initial Mount
      • Accidental Root Unmount
  • Component Auto-Registration
    • Function Components (via Babel plugin)
      • Loader would also pickup false-negatives from the plugin
    • Class Components (via packaged loader)
    • Mutating Exports (add/remove/change)
  • Error Box Integration (iframe) #3
    • Compilation Errors (via Socket)
      • Renders Error Message
      • Dismissal after Error Recovery (via tracking of Hot status)
    • Runtime Errors (via console injection)
      • Renders Error Message (optional source trace? source-map support?)
      • Dismissal after Error Recovery (via hook in window)
  • Webpack Advanced Integration
    • Supports __resourceQuery (wait for WDS v4) #52
    • Allow custom socket integrations (through transportMode or a plugin option with a similar footprint) #64
    • Express-like middleware to cater advanced WDM users
  • Webpack@5 Support #123
    • Correctly detects context.hot
    • Update hook footprints to match new object types
    • Detects and support multi-compilers and child-compilers (Obsolete for now, this plugin won't break in those scenarios)
    • Better integration with the new modular HMR system #89
    • Release after Webpack@5 hits beta stage (0.4.0-beta.6+)
  • Tests
    • Fast refresh conformance tests #93 #96
    • Fast refresh error recovery regression tests
    • Plugin unit tests #127

$RefreshReg$ appears in production bundle

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 $RefreshReg$. Opening the built app via dist/index.html crashes as a result.

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 πŸ˜…

Incompatible with webpack 4.43.0

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.

Could not find plugin "proposal-numeric-separator"

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

How to integrate this into non-browser environments?

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?

React module detection doesn't work unless explicitly importing 'react'

And not 'react/index.js' or whatever. That's fine, but what I'm doing within our codebase is:

  1. Babel uses __react_createElement__ as its JSX pragma and these get injected during babel-loader.
  2. Webpack's 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.)

First recompile triggers a full page reload

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!)

  1. we use Typescript -> webpack.config.ts
  2. we use ForkTsCheckerWebpackPlugin for type checking.

I followed all suggested actions:

  1. peer dependency type-fest
  2. tried to learn from this sample (got it from README.md)

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
            },
          },
        ],
      },

Support other means of Webpack sockets

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

Upstreaming the plugin into the React monorepo

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:

What do you think?

error overlayer not work when warning

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

  1. If I turn off webpack-dev-server's overlay, how to display overlayer for warning. because this plugin only display overlayer when error
  2. If I turn on webpack-dev-server's overlay, It will appear two overlayer for errors.

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?

Issues working with Webpack Dev Middleware in server rendering environments

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:

  • While my actual server rendered application is served on 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)
  • After I manually changed the port to 8501 in 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
  • Universal components that are also used on the server side fail because $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

Module becomes `undefined` after refresh due to cyclic dependencies

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:

  1. Clone https://github.com/sophiebits/refresh-cycle-repro

  2. Run yarn and yarn start, then visit http://localhost:7002/. You'll see the text "Hello: 100".

  3. If you edit the "Hello" (in App.js), it updates properly.

  4. 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.

Fails to work when integrated into create-react-app

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 }));

Incompatible with chrome 53

Uncaught ReferenceError: getModuleExports is not defined          utils.js:169
Uncaught ReferenceError: handleCompileSuccess is not defined      ErrorOverlayEntry.js:67

Work fine at latest chrome version

Issues with Webpack 5

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

Aborted because <file> is not accepted

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.

Bug: function component is unmount and mount with old state when hmr

React version: 16.13.1
react-refresh version: 0.8.1
react-refresh-webpack-plugin version: 0.3.0-beta.6

Steps To Reproduce

  1. run examples/webpack-dev-server
  2. change file
    examples/webpack-dev-server/src/ClassDefault.js
    examples/webpack-dev-server/src/FunctionDefault.js
  3. try hmr

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;

The current behavior

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

The expected behavior

function component should be unmount and mount with a brand new state when hmr.

Thanks for your help.

overlay.sockIntegration does not receive 'wds' default

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.

Issue with adding/removing hooks when runtimeChunk is true

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 😦

Thank you

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. ❀️

The plugin is unable to detect transformed code from react-refresh

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"
    })
  ]
};

Server startup hangs forever (or a really long time?) if disableRefreshCheck=false

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.

`connection.onClose` is not a function

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.

Incorrect β€˜wdsSock*’ options validation

Hello, and thank you so much for working on this. 🌟

I think I’ve noticed a small issue with the Sock options validation:

"wdsSockHost": { "type": "string" },
"wdsSockPath": { "type": "string" },
"wdsSockPort": { "type": "number", "minimum": 0 }

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? :)

`options.overlay` set to false creates fatal error

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.

[errorOverlay]: this.options.overlay && require.resolve(this.options.overlay.module),

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.

image

Failed to work when react is external and loaded via standalone script

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.

Support typescript loader ?

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 ?

WHM support breaks projects that do not have it installed

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:

const client = require('webpack-hot-middleware/client');

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

Get websocket port from `document.currentScript` if possible

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 😁

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.