I have a basic setup with two apps each in a separate directory, I'm using a custom server to compile them using webpack-dev-middleware
/webpack-hot-middleware
. Things are working fine except that I can't get HMR to work for the second app (I'm using react-hot-loader
).
Here's a minimal repo illustrating the problem: https://github.com/AmrN/multi-react-app-hmr
My main code files:
webpack.config.js
var path = require('path');
var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = function (appName) {
return {
devtool: 'cheap-module-eval-source-map',
entry: [
'react-hot-loader/patch',
'webpack-hot-middleware/client',
path.join(__dirname, appName, 'index'),
],
output: {
path: path.join(__dirname, 'dist', appName),
filename: 'bundle.js',
publicPath: '/'+appName+'/'
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new webpack.NamedModulesPlugin(),
new webpack.NoEmitOnErrorsPlugin(),
new HtmlWebpackPlugin({
template: path.join(__dirname, appName, 'index.html'),
}),
],
module: {
loaders: [{
test: /\.jsx?$/,
loaders: ['babel-loader'],
exclude: /node_modules/,
}]
},
};
};
server.js
var path = require('path');
var webpack = require('webpack');
var express = require('express');
var config1 = require('./webpack.config')('app1');
var config2 = require('./webpack.config')('app2');
var app = express();
[config1, config2].forEach((config) => {
var compiler = webpack(config);
app.use(require('webpack-dev-middleware')(compiler, {
publicPath: config.output.publicPath
}));
app.use(require('webpack-hot-middleware')(compiler));
});
app.listen(3000, function (err) {
if (err) {
return console.error(err);
}
console.log('Listening at http://localhost:3000/');
});
(app1|app2)/index.js
import { AppContainer } from 'react-hot-loader';
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
const rootEl = document.getElementById('root');
const render = Component =>
ReactDOM.render(
<AppContainer>
<Component />
</AppContainer>,
rootEl
);
render(App);
if (module.hot) module.hot.accept('./App', () => render(App));
Now if I run the server, my files are compiled correctly, and I can visit http://localhost:3000/app1/index.html
successfully, and HMR is working properly here. However, if I visit the second app http://localhost:3000/app2/index.html
it opens but HMR is not working and looking at the console it gives me the following error:
GET http://localhost:3000/app2/640a44b6b47b67436af2.hot-update.json 404 (Not Found)
[HMR] Cannot find update (Full reload needed)
[HMR] (Probably because of restarting the server)
Another thing I've noticed is that changing the order in which I apply my apps webpack configs in server.js from:
[config1, config2].forEach((config) => {...})
to:
[config2, config1].forEach((config) => {...})
switches the problem to app1, now HMR works for app2 but not app1.
Any help is appreciated, thanks.
The problem was that both apps used the same path for hot reloading (I think it's /__webpack_hmr
by default).
So I had to use a different one for each:
in webpack.config.js I did:
entry: [
// ...
'webpack-hot-middleware/client?path=/__webpack_hmr_'+appName,
// ...
]
and in server.js:
app.use(require('webpack-hot-middleware')(compiler, {
path: '/__webpack_hmr_'+appName
}));
Now it's working properly.