webpack-contrib/webpack-hot-middleware

hot reloading not working unless I have ?reload=true

orpheus opened this issue ยท 9 comments

App won't hot reload unless I add '?reload=true' to my webpack-hot-middleware entry point in the webpack config.

The rest of my config is set up exactly according to docs. I'm using it along with react-hot-loader which is also set up according to docs.

//webpack.config.js
module.exports = {
  entry: [
    'react-hot-loader/patch', // RHL patch
    'webpack-hot-middleware/client?reload=true', //note that it reloads the page if hot module reloading fails; without this query, hmr fails
    './client/src/index.js'
  ],
  plugins: [
    new webpack.HotModuleReplacementPlugin(),
...
//server.js
server.use(webpackDevMiddleware(compiler, {
  noInfo: true, publicPath: webpackConfig.output.publicPath,
}));
server.use(webpackHotMiddleware(compiler));
//package.json
"babel": {
    "plugins": [
      "react-hot-loader/babel"
    ],
    "presets": [
      "env",
      "react",
      "stage-2"
    ]

Is there something I'm missing? I have the react-hot-loader component wrapping my root component in my index.js; so I don't know why it won't work without the reload query.

What info do you get in the browser console when reloading fails?

process-update.js?e13e:81 [HMR] The following modules couldn't be hot updated: (Full reload needed)
This is usually because the modules which have changed (and their parents) do not know how to hot reload themselves. See https://webpack.js.org/concepts/hot-module-replacement/ for more details.

I got the same error as @Always-sunny:

college_verify.js:58428 Ignored an update to unaccepted module 701 -> 602 -> 406

college_verify.js:58501 [HMR] The following modules couldn't be hot updated: (Full reload needed)
This is usually because the modules which have changed (and their parents) do not know how to hot reload themselves. See https://webpack.js.org/concepts/hot-module-replacement/ for more details.
college_verify.js:58509 [HMR]  - ./app/components/college_verify/CollegeVerify.jsx

However if I add the reload=true to the params:
webpack-hot-middleware/client?path=http://www.website.com:8080/__webpack_hmr

It allows the browser to refresh the entire page on HMR update.

I'd love to get this to work without having to do a full browser refresh. Any suggestions?

You should tell your application how to deal with the changes.
Try to use the module.hot.accept() function provided by webpack hmr.

Here is an example:

//imports
...

const renderApp = () => {
  ReactDOM.hydrate((
        <App />
  ), document.getElementById('root'));
};

// This is needed for Hot Module Replacement
if (module.hot) {
  module.hot.accept('./App', () => renderApp());
}

@ungerpeter Already implemented.

Ditto

The same situation with
react-hot-loader v.4.0.0,
webpack v.4.2.0,
webpack-dev-middleware v.3.0.1,
webpack-hot-middleware v.2.21.2.

I use new approach:

// client/index.js

import React from 'react';
import { render } from 'react-dom';
import App from './components/App';

render(
    <App/>,
    document.getElementById('root')
);
// components/App.js

import React, { Component } from 'react';
import { hot } from 'react-hot-loader'

class App extends Component {
    render() {
        return <h1>Hello world from react!</h1>
    }
}

export default hot(module)(App);
// server/index.js

import webpackDevMiddleware from 'webpack-dev-middleware';
import webpackHotMiddleWare from 'webpack-hot-middleware';
import webpackConfig from '../webpack.config';

const app = express();
const compiler = webpack(webpackConfig);

app.use(webpackDevMiddleware(compiler, {
    hot: true,
    publicPath: webpackConfig.output.publicPath
}));
app.use(webpackHotMiddleWare(compiler));
// .babelrc

{
  "presets": ["es2015", "react"],
  "plugins": ["react-hot-loader/babel"]
}
// webpack.config.js

export default {
    entry: [
        'webpack-hot-middleware/client',
        path.join(__dirname, 'client/index.js')
    ],
    output: {
        path: '/',
        publicPath: '/',
        filename: 'bundle.js'
    },
    module: {
        rules: [{
            test: /\.js$/,
            include: [path.join(__dirname, 'client')],
            loader: 'babel-loader'
        }]
    },
    plugins: [
        new webpack.NamedModulesPlugin(),
        new webpack.HotModuleReplacementPlugin(),
        new webpack.NoEmitOnErrorsPlugin()
    ]
}

Only adding 'webpack-hot-middleware/client?reload=true', helps and do reload all pages.

Error messages in console:

Ignored an update to unaccepted module ./client/components/App.js -> ./client/index.js -> 0
[HMR] The following modules couldn't be hot updated: (Full reload needed)
This is usually because the modules which have changed (and their parents) do not know how to hot reload themselves. 
See https://webpack.js.org/concepts/hot-module-replacement/ for more details.
[HMR]  - ./client/components/App.js

I spent yesterday all day. But now suddenly I've found the reason. It needs to add mode: development in webpack.config. If mode is undefined or production the issue is reproduced.

Same here works only with reload=true....

here is my webpack setup:
webpack.config.js:

const path = require('path')
const fs = require('fs')
const webpack = require('webpack')
const CopyPlugin = require('copy-webpack-plugin')
process.env['NODE_CONFIG_DIR'] = path.join(__dirname, '../config')
process.env['BABEL_ENV'] = path.join(__dirname, 'babel.config.json')
const config = require('config')

const clientDir = path.join(__dirname, '../build')

if (!fs.existsSync(clientDir)) {
  fs.mkdirSync(clientDir)
}

module.exports = {
  mode: config.get('env'),
  stats: 'errors-warnings',
  infrastructureLogging: {
    level: 'warn'
  },
  plugins: [
    new webpack.HotModuleReplacementPlugin(),
    new CopyPlugin([
      {
        from: path.join(__dirname, 'public'),
        to: clientDir
      }
    ])
  ],
  module: {
    rules: [
      {
        test: /\.(js|jsx)$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
          options: {
            cwd: './client'
          }
        }
      }
    ]
  },
  entry: [
    'webpack-hot-middleware/client?path=/__webpack_hmr&timeout=20000&reload=true',
    path.join(__dirname, 'src/index.js')
  ],
  output: {
    path: clientDir,
    filename: 'js/bundle.js',
    publicPath: '/'
  }
}

express.js:

  const webpackDevMiddleware = require('webpack-dev-middleware')
  const webpackHotMiddleware = require('webpack-hot-middleware')
  const webpackConfig = require('../../client/webpack.config.js')
  const compiler = webpack(webpackConfig)
  app.use(
    webpackDevMiddleware(compiler, {
      stats: webpackConfig.stats,
      publicPath: webpackConfig.output.publicPath
    })
  )
  app.use(webpackHotMiddleware(compiler))

Note, my app is a react app. Maybe it doesn't work because I don't use react-hot-loader module