0

I'm trying to set up an environment for my React application using Webpack and Babel. I use JSX to implement components and I would like to leverage live reload.

Here is my package.json file:

{
  (...)
  "scripts": {
    "start": "webpack-dev-server --hot --inline"
  },
  "dependencies": {
    "babel-loader": "^6.2.4",
    "babel-preset-es2015": "^6.9.0",
    "babel-preset-react": "^6.11.1",
    "jsx-loader": "^0.13.2",
    "react": "^15.1.0",
    "react-dom": "^15.1.0",
    "react-hot-loader": "^1.3.0",
    "webpack": "^1.13.1",
    "webpack-dev-server": "^1.14.1"
  }
}

Here is my Webpack configuration:

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

var BUILD_DIR = path.resolve(__dirname, 'src/client/public');
var APP_DIR = path.resolve(__dirname, 'src/client/app');

var config = {
  entry: [
    'webpack-dev-server/client?http://0.0.0.0:8080',
    'webpack/hot/only-dev-server',
    APP_DIR + '/index.jsx'
  ],
  output: {
    path: BUILD_DIR,
    filename: 'bundle.js'
  },
  module : {
    loaders : [
      {
        test : /\.jsx?/,
        include : APP_DIR,
        loaders: ['react-hot', 'babel']
      }
    ]
  },
  plugins: [
    new webpack.HotModuleReplacementPlugin()
  ]
};

module.exports = config;

After having executed npm run start and with this configuration, I see in my console that updates in a JSX file are detected but the browser isn't updated. Moreover, if I have a look at the module.js file, my updates aren't taken into account.

Running the command webpack -d, they are...

See this repo: https://github.com/templth/react-webpack-hot-reload.

Additional hints. I see the following traces in the JavaScript console of the browser:

[HMR] Waiting for update signal from WDS...
Download the React DevTools for a better development experience: https://(...)/react-devtools
XHR finished loading: GET "http://localhost:8080/sockjs-node/info?t=1467375470671".AbstractXHRObject._start @ abstract-xhr.js:132(anonymous function) (...)
[WDS] Hot Module Replacement enabled.
[WDS] App updated. Recompiling...
[WDS] App hot update...
[HMR] Checking for updates on the server...
GET http://localhost:8080/src/client/0cf06dae430007853b6f.hot-update.json 404 (Not Found)hotDownloadManifest @ bootstrap (...)
[HMR] Cannot find update. Need to do a full reload!

only-dev-server.js:28 [HMR] (Probably because of restarting the webpack-dev-server)

and in the console that started the webpack dev server

Hash: 85771179bfa8706bc10f
Version: webpack 1.13.1
Time: 275ms
                           Asset      Size  Chunks             Chunk Names
                       bundle.js    991 kB       0  [emitted]  main
0.8073da5d40a8dd413f96.hot-update.js    3.6 kB    0, 0  [emitted] main, main
8073da5d40a8dd413f96.hot-update.json  36 bytes          [emitted]  
chunk    {0} bundle.js, 0.8073da5d40a8dd413f96.hot-update.js, 0.8073da5d40a8dd413f96.hot-update.js (main) 897 kB [rendered]
   [76] ./src/client/app/index.jsx 3.58 kB {0} [built]
     + 255 hidden modules
webpack: bundle is now VALID.

Thanks very much for your help!

Thierry Templier
  • 198,364
  • 44
  • 396
  • 360

2 Answers2

2

Your entry point should be just webpack/hot/dev-server

(webpack/hot/only-dev-server is for when you want/need to do manual reloads, see https://github.com/webpack/webpack/issues/418)

Also, you need to specify a publicPath (eg output.publicPath) in your dev config. For example:

publicPath: 'http://localhost:8080/'

(An absolute path is needed here for images in css to work with sourcemaps on)

In your prod config, you still need something here, eg

publicPath: '/',

You will also need this in the entrypoint for HMR to work. (It will be removed by minification in prod as its 'unreachable' code)

if (module.hot) {
     module.hot.accept();
}
Dan Brown
  • 136
  • 7
  • Thanks very much for your answer! But I still have the same behavior. I added some traces in my question... – Thierry Templier Jul 01 '16 at 12:28
  • I have 404 errors in the browser on requests like this: `bootstrap 0cf06da…:25 GET http://localhost:8080/src/client/0cf06dae430007853b6f.hot-update.json ` – Thierry Templier Jul 01 '16 at 12:29
  • I think you will have to set publicPath to http://localhost:8080/src/client/ (same as your dev server) [link]https://github.com/gaearon/react-hot-loader/blob/master/docs/Troubleshooting.md – Dan Brown Jul 01 '16 at 14:38
  • ... or try localhost:8080/src/client/ – Dan Brown Jul 01 '16 at 14:45
  • couple of other pointers of things I had to do: Antivirus may break hot reload (exclude your working dir from your AV) Webstorm 2016 needs the option unchecked "use safe write" for hot reload to work. This could apply to other editors. (Safe write: tries to write to a temp file first) – Dan Brown Jul 01 '16 at 14:48
  • I added the `publicPath` property but the problem remains :-( I pushed my code in this repo on Github: https://github.com/templth/react-webpack-hot-reload. Feel free to have a look. Thanks very much for your help! – Thierry Templier Jul 01 '16 at 19:20
  • For anyone else lazy as me .. this helped me a lot. After 3 days of banging my head to the wall I realized that my publicPath was relative filesystem related instead of public Url as its name says. (Not all problems were related to this as I did a egzotic combination -> koa2 + wp2 + react hl.3) – Goran.it Mar 16 '17 at 03:02
0

UPDATE: Using your github repo.

A possible solution is to use the html-webpack-plugin to serve your bundles. All you have to do is npm install it and add it to your plugins configs:

npm i html-webpack-plugin --save-dev

Usage:

var HtmlWebpackPlugin = require('html-webpack-plugin');

plugins: [
    new webpack.HotModuleReplacementPlugin(),
    new HtmlWebpackPlugin({
        template: './src/client/index.html'
    }),
  ]

Remove the <script src="public/bundle.js" type="text/javascript"></script> from your index.html, now it will be automatically added for you.

Then access http://localhost:8080/ and everything should work fine.

Bonus: you can use html-loader and the --inline config to use hot reload on html too.

npm i html-loader --save-dev

Usage:

{
  test: /\.html$/,
  loader: 'html-loader'        
} 

Then add it to your package.json:

"start": "webpack-dev-server --inline --hot"

Explanation in https://webpack.github.io/docs/webpack-dev-server.html, "Inline mode" section.


Another solution you can test is using the devServer config in your webpack.config.js:

module.exports = {
    devServer: {
        inline: true,
        port: 3333
    },
    ...

Then i use the publicPath:

publicPath: 'http://localhost:3333/'

And in my package.json:

"start": "webpack-dev-server --content-base app",

Remove those lines from webpack.config.js:

'webpack-dev-server/client?http://0.0.0.0:8080',
'webpack/hot/only-dev-server',

Also you can use just "npm start", "run" is not need in this case.

Hope it helps.

Kadoo
  • 90
  • 5
  • Thanks very much for your answer! Do you mean that live reload is provided with this approach? – Thierry Templier Jul 01 '16 at 19:14
  • Yes. I'm pretty sure this approach uses hot reload by default, but you can egt more info here https://webpack.github.io/docs/webpack-dev-server.html on the "Additional configuration options" section. I just think it's easier to understand an use it this way. – Kadoo Jul 01 '16 at 22:43