Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hot update not update the view (screen) #100

Closed
rottmann opened this issue Jan 23, 2015 · 34 comments
Closed

Hot update not update the view (screen) #100

rottmann opened this issue Jan 23, 2015 · 34 comments

Comments

@rottmann
Copy link

I wrote a little react app and serve static files from a separate express server (to redirect all sub-pathes to index.html [react-router]).

static server on port 8080
webpack hot dev server on port 8081

Browser console log:

[HMR] Waiting for update signal from WDS...
client:14 [WDS] Hot Module Replacement enabled.

after modify and save a file (e.g. router.js)

client:18 [WDS] App updated. Recompiling...
client:60 [WDS] App hot update...
dev-server.js:54 [HMR] Checking for updates on the server...
dev-server.js:34 [HMR] Updated modules:
dev-server.js:36 [HMR]  - 11
dev-server.js:40 [HMR] App is up to date.

But on the screen nothing change

The cli console log show:

Hash: a00a156bb0c50980187c
Version: webpack 1.5.3
Time: 483ms
                               Asset     Size  Chunks             Chunk Names
                              app.js   130429       0  [emitted]  app
                           vendor.js  1854993       1  [emitted]  vendor
0.919fa51221ca3cdacfb2.hot-update.js     3980       0  [emitted]  app
919fa51221ca3cdacfb2.hot-update.json       36          [emitted]  
chunk    {0} app.js, 0.919fa51221ca3cdacfb2.hot-update.js (app) 117673 {1} [rendered]
    [0] multi app 52 {0}
    [1] (webpack)-dev-server/client?http://localhost:8081 1674 {0}
    [2] ./src/app.js 2597 {0} [1 error]
    [4] (webpack)/hot/dev-server.js 2916 {0}
   [11] ./src/router.js 3370 {0} [built]
   [34] (webpack)-dev-server/client/web_modules/socket.io/index.js 1149 {0}
   [89] (webpack)-dev-server/client/web_modules/socket.io/socket.io.js 105915 {0}
chunk    {1} vendor.js (vendor) 1601853 [rendered]
    [0] multi vendor 76 {1}
.
.
.
  [257] ./~/react/lib/toArray.js 3176 {1} [built]
webpack: bundle is now VALID.

Structure

|- build/
|- dev/
   |- webpack.base.js
   |- dev-server.js
|- src/
   |- app.js
   |- router.js
|- static/
   |- index.html
   |- assets/
      |- ...some files...

package.json

  "dependencies": {
    "react": "^0.12.2",
    "react-router": "^0.11.4"
  },
  "devDependencies": {
    "express": "^4.11.1",
    "jsx-loader": "^0.12.2",
    "react-hot-loader": "^1.1.1",
    "webpack": "^1.5.3",
    "webpack-dev-server": "^1.7.0"
  }

webpack.base.js

var webpack = require('webpack');
var path = require('path');

var vendorLibs = [
    'react',
    'react-router'
];

module.exports = function(options) {
    return {
        context: path.join(__dirname, '../', 'src'),
        entry: {
            app   : [
                'webpack-dev-server/client?http://localhost:8081',
                'webpack/hot/dev-server',
                './app.js'
            ],
            vendor: vendorLibs,
        },
        output: {
            path             : path.join(__dirname, '../', 'build'),
            filename         : '[name].js',
            chunkFilename    : '[id].bundle.js',
            sourceMapFilename: '[file].map',
            pathinfo         : true,
            publicPath       : 'http://localhost:8081/'
        },
        module: {
            loaders: [
                { test: /\.js$/, loaders: ['react-hot', 'jsx?harmony'] }
            ]
        },
        resolve: {
            extensions: ['', '.js']
        },
        debug: options.debug,
        devtool: options.devtool,
        plugins: [
            new webpack.optimize.CommonsChunkPlugin({ name: 'vendor', minChunks: Infinity }),
            new webpack.HotModuleReplacementPlugin()
        ]
    }
};

dev-server-js

var webpack = require('webpack');
var WebpackDevServer = require('webpack-dev-server');
var express = require('express');
var path = require('path');
var fs = require('fs');

var app = express();
var config = require('./webpack.base.js')

// Redirect all non existing files to index.html
app.get('/*', function(req, res) {
    var filename = path.join(__dirname, '../', 'static', req.url);
    if (fs.existsSync(filename)) {
        console.log('static: ' + req.url);
        res.sendFile(filename);
    } else {
        console.log('static: index.html (' + req.url + ')');
        res.sendFile(path.join(__dirname, '../', 'static') + '/index.html');
    }
});

var compiler = webpack(config({
    devServer    : true,
    devtool      : 'eval',
    debug        : true
}));

var server = new WebpackDevServer(compiler, {
    contentBase: 'http://localhost:8081',
    hot: true,
    quiet: false,
    noInfo: false,
    lazy: false,
    watchDelay: 300,
    publicPath: 'http://localhost:8081/',
    stats: { colors: true },
});

server.listen(8081, 'localhost', function() {});
app.listen(8080);

app.js

<!DOCTYPE html>
<html>
<body>
    <div id="app"></div>
    <script src="http://localhost:8081/vendor.js"></script>
    <script src="http://localhost:8081/app.js"></script>
</body>
</html>

Is it a problem when serving the index.html from an other port?
The docs say it is possible (http://webpack.github.io/docs/webpack-dev-server.html#combining-with-an-existing-server)

@sokra
Copy link
Member

sokra commented Jan 23, 2015

The react-hot-loader only works for React components. Is route.js a React component?

@rottmann
Copy link
Author

Yes it is the react-router with a sample react component.

@rottmann
Copy link
Author

I test it before on one port with a webpack dev only server, and it worked, then splitted it into 2 servers and got the problem.

Or is it possible to redirect router paths to index.html with webpack-dev-server?
e.g. for a direct call of http://localhost:8080/some/path/4711

@sokra
Copy link
Member

sokra commented Jan 24, 2015

The log looks pretty good... It does't look like a connection/configuration issue.

cc @gaearon

@gaearon
Copy link
Contributor

gaearon commented Jan 24, 2015

Can you put up a reproducible example in a repo so I could examine it?

@rottmann
Copy link
Author

Funny, i create an example with the code above, everything worked.
Then i try my project again and it worked too.

Hope it was the update of chrome that solved the problem and it is no other strange problem.

@rottmann
Copy link
Author

Reopened the problem.

I try my app at my office computer and got the problem.

At home i run Win7 Host with a VirtualBox Mint 17 and it worked without a problem in the box.
In the office i use a native Mint 17 with the same chrome (synced with the same plugins)... the browser not update the view.

Did somebody have an idea how i can determine the problem?

@rottmann rottmann reopened this Jan 28, 2015
@gaearon
Copy link
Contributor

gaearon commented Jan 28, 2015

Any change you have duplicate react in node_modules?
For example, some other library may have it in its own node_modules..

@rottmann
Copy link
Author

  "dependencies": {
    "react": "^0.12.2",
    "react-router": "^0.11.6"
  },
  "devDependencies": {
    "express": "^4.11.1",
    "jsx-loader": "^0.12.2",
    "react-hot-loader": "^1.1.3",
    "webpack": "^1.5.3",
    "webpack-dev-server": "^1.7.0"
  }

cleaned node_modules dir and install all modules new.

@gaearon
Copy link
Contributor

gaearon commented Jan 28, 2015

Does https://github.com/gaearon/react-hot-boilerplate work on that computer?

@rottmann
Copy link
Author

Thanks, found the problem: apparmor blocked something on port 8080. (previously i run a docker project and uninstalled docker)

Funny problem, script compilation run and browser message for reload appears, only the browser view not update thats why it was not obvious what was not working.

@gaearon
Copy link
Contributor

gaearon commented Jan 28, 2015

Good, thank you for sharing!

@bobzhang
Copy link

I see the same problem @rottmann , how can I fix it?
Logs below look perfectly fine, just chrome not updated ..

[WDS] App hot update...
bundle.js:8022 [WDS] App hot update...
bundle.js:7911 [HMR] Checking for updates on the server...
bundle.js:7945 [HMR] Updated modules:
bundle.js:7947 [HMR]  - 59
bundle.js:7897 [HMR] App is up to date.

@mikealexander
Copy link

@bobzhang did you find a solution? I am seeing the same problem.

@mharmuth
Copy link

mharmuth commented May 11, 2016

I ran into the same problem yesterday. Any information on how to fix that?

@mikealexander Did you find a solution for your problem?

@lxibarra
Copy link

lxibarra commented Aug 7, 2016

I have this same problem, anyone help

@YamiOdymel
Copy link

Same problem, the browser received the hot-update.js but updated nothing,

I tried to execute the code which is in the hot-update.js and still nothing happened.

@YamiOdymel
Copy link

YamiOdymel commented Aug 26, 2016

Okay, I solved this problem by STOP USING webpack-merge for my config.entry.client.

module.exports = merge(config, 
{
    entry:
    {
        cilent: 
        [
            'webpack-hot-middleware/client', 
            config.entry.client
        ]
    }
})

CHANGE TO

config.entry.client = ['webpack-hot-middleware/client', config.entry.client]

@wunderg
Copy link

wunderg commented Dec 9, 2016

Did anyone find a solution?

@Armour
Copy link

Armour commented Jan 8, 2017

I also met this problem, and I solved it by change

import { AppContainer } from 'react-hot-loader';
import App from 'js/App';

if (module.hot) {
    module.hot.accept('./App', () => {
        ReactDom.render(
          <AppContainer>
            <App />
          </AppContainer>,
          document.getElementById('root'),
        );
    });
}

to

import { AppContainer } from 'react-hot-loader';
import App from 'js/App';

if (module.hot) {
    module.hot.accept('./App', () => {
        const NextApp = require('js/App').default;
        ReactDom.render(
          <AppContainer>
            <NextApp />
          </AppContainer>,
          document.getElementById('root'),
        );
    });
}

Seems the App won't refresh it self, so we need to re-import it, also need to make sure import it after(or say inside) the module.hot.accept function call.

Hope it helps :)

@davincho
Copy link

davincho commented Mar 1, 2017

Thanks @Armour. I followed https://webpack.js.org/guides/hmr-react/ which says "Note that because webpack 2 has built-in support for ES2015 modules, you won't need to re-require your root component in module.hot.accept" but the browser did not update the view. After "re-requiring" the component within the module.hot.accept callback everything worked as expected.

@chbinghu
Copy link

Thanks @Armour, it works well!
My index.js is:

import React from 'react'
import ReactDOM from 'react-dom'
import { AppContainer } from 'react-hot-loader'

import App from './containers/App'

const render = Component => { 
    ReactDOM.render(
        <AppContainer>
            <Component/>
        </AppContainer>,
        document.getElementById('react-root')
    )
}

render(App)

/** It doesn't work
 * 
    if(module.hot) {
        module.hot.accept('./containers/App', () => {
            render(App)
        })
    }
 */

// It works well
if(module.hot) {
    module.hot.accept('./containers/App', () => {
        const NextApp = require('./containers/App').default
        render(NextApp)
    })
}

@tiodot
Copy link

tiodot commented Apr 1, 2017

I have the same problem, there is interesting solution which use "self-accepting",
the index.js is:

import React from 'react'
import ReactDOM from 'react-dom'
import { AppContainer } from 'react-hot-loader'

import App from './containers/App'

const render = Component => { 
    ReactDOM.render(
        <AppContainer>
            <Component/>
        </AppContainer>,
        document.getElementById('react-root')
    )
}

render(App)

/** It doesn't work
 * 
    if(module.hot) {
        module.hot.accept('./containers/App', () => {
            render(App)
        })
    }
 */

// It works well
if(module.hot) {
    module.hot.accept();
}

thepag referenced this issue in thepag/styleguide-playground Apr 18, 2017
@daviddelusenet
Copy link

I'm also experiencing this issue. I've asked a question on StackOverflow which can be seen here:

http://stackoverflow.com/questions/43491310/cant-get-webpack-2-hmr-react-to-work

This works for me:

if(module.hot) {
  module.hot.accept();
}

This also works for me:

if(module.hot) {
  module.hot.accept('./components/TodoApp', () => {
    const NextApp = require('./components/TodoApp').default;
    render(NextApp)
  })
}

This doesn't:

if (module.hot) {
  module.hot.accept('./components/TodoApp', () => {
    render(TodoApp)
  });
}

Why doesn't the default setup work? Really confused.

@hrasoa
Copy link

hrasoa commented May 8, 2017

Had the same issue since this morning and this fixed it !

@ssynix
Copy link

ssynix commented May 8, 2017

I had the same issue and it boils down to how module code generation works in your setup (through Babel/TypeScript). From my limited understanding, webpack 2 should be able to inject the require call using ES6 modules. I use TypeScript, and the below tsconfig values worked for me:

{
    "target": "es6",
    // "module":  Don't override this to anything
    "moduleResolution": "node",
}

I remember reading about a module: false parameter in Babel that did something similar for webpack + Babel configs.

module.hot.accept() and module.hot.accept('module') may not always be interchangeable. Make sure you understand what they each do.

@derekdon
Copy link

@ssynix I'm also using typescript (2.2.2) and I can't seem to get react-hot-loader@next it to work following the https://github.com/gaearon/react-hot-loader/tree/master/docs#webpack-2 example as @davincho did. Re-requiring the app in the hot reload handler works, as does just calling module.hot.accept(), but I'd like to get it working as documented. As I think @ssynix is right "it boils down to how module code generation works in your setup", I've been trying a number of different settings without much luck (would like to take advantage of tree shaking).

// main.tsx
import { AppContainer as HotContainer } from 'react-hot-loader';
import { default as App } from './containers/AppContainer';
...
const render = (Component: any) => {
    ReactDOM.render(
        <HotContainer>
            <Component
                store={store}
                routes={routes}
            />
        </HotContainer>,
        root
    );
};
...
if (module.hot) {
        module.hot.accept('./containers/AppContainer', () => {
            if (root) {
                ReactDOM.unmountComponentAtNode(root);
            }
            render(App);
        });
    }
//.babelrc
{
    "presets": [
        [
            "es2015",
            {
                "modules": false
            }
        ],
        "stage-0",
        "react"
    ],
    "plugins": [
        "react-hot-loader/babel",
        ...
    ]
}
// tsconfig.json
{
  "compilerOptions": {
    "isolatedModules": true,
    "moduleResolution": "node",
    "target": "es2015"
    ...
  }
}

@wufenfen
Copy link

wufenfen commented Jun 5, 2017

if(module.hot) {
  module.hot.accept();
} 

This works for me too, in the angular app. Thanks so much~~~

@jasondonnette
Copy link

jasondonnette commented Sep 10, 2017

I struggled with this for a bit with Webpack 3 and got it working with the import() syntax. Not sure if this is helpful to anyone but here's what's working for me:

import ReactDOM from 'react-dom';
import { AppContainer } from 'react-hot-loader';

const run = async () => {
  const { Root } = await import('index');
  ReactDOM.render(
    <AppContainer>
      <Root />
    </AppContainer>,
    document.getElementById('react'),
  );
};

const loadedStates = ['complete', 'loaded', 'interactive'];
if (loadedStates.includes(document.readyState) && document.body) {
  run();
} else {
  window.addEventListener('DOMContentLoaded', run, false);
}

module.hot.accept('index', run);

@gdepina
Copy link

gdepina commented Oct 3, 2017

@swxy
This works for me thanks a lot!
I am using, webpack 2.2 + RRV4 + React-hot-loader v3 and webpack-hot-middleware.

if(module.hot) {
    module.hot.accept();
}

@hedgepigdaniel
Copy link

hedgepigdaniel commented Oct 4, 2017

I had this issue and for me the underlying problem was misconfigured babel presets.
Before (leading to exactly the same HMR situation as @daviddelusenet):

presets: [
  [ 'es2015', { modules: false } ],
  'stage-0',
   'react',
]

After (The usual approach now works):

presets: [
  [ 'env', { modules: false } ],
   'react',
]

I think options to a preset can be overriden by other presets, in this case presumably stage-0 also turned the modules transform back on.

Source: https://stackoverflow.com/questions/43491310/cant-get-webpack-2-hmr-react-to-work/43500626

@jyotendra
Copy link

jyotendra commented Oct 24, 2017

Thanks @hedgepigdaniel. Its mentioned in the react-hot-loader doc here, that

"To make this work, you'll need to opt out of Babel transpiling ES2015 modules by changing the Babel ES2015 preset to be ["es2015", { "modules": false }]"

@gpnoel
Copy link

gpnoel commented Mar 14, 2018

I finally got this working after 5+ hours looking through many different github issues and tutorials.

First off, versions for what I'm using currently:

  • webpack: 4.1.1
  • webpack-dev-server: 3.1.1

Two things helped resolve this issue and have the browser reload on source code change:

  1. setting webpack's config for hot to false -- hot: false

People said that they did not include this property in their config s but I had to set the value to false for it to work for me

  1. including a bundle to the client for webpack-dev-server:
entry: {
  hmr_endpoint: 'webpack-dev-server/client?http://localhost:8008'
}

Whatever you name it doesn't matter. including it in an array works as well; just be wary of mismatching types if you are doing this all through Node's api like I am.

entry: [
  'webpack-dev-server/client?http://localhost:8008'
]

Obviously change the port to whichever one you are working with in your project.
Hope this helps someone and resources I looked at that helped me come to this:
1 2 3

@ejoo
Copy link

ejoo commented Feb 11, 2019

@tiodot 's solution worked with Typescript + React but failed with Redux and Redux Saga Integrated.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests