I'm not sure if this is the right venue for this, but I figured it was worth a shot.
I'm trying to setup hot module reloading in a react/typescript (with TSX) environment. I have used the react/redux real-world example as a model in getting things going, and this is what I have so far:
server.js
var webpack = require('webpack')
var webpackDevMiddleware = require('webpack-dev-middleware')
var webpackHotMiddleware = require('webpack-hot-middleware')
var config = require('./webpack.config')
var app = new (require('express'))()
var port = 3000
var compiler = webpack(config)
app.use(webpackDevMiddleware(compiler, { noInfo: true, publicPath: config.output.publicPath }))
app.use(webpackHotMiddleware(compiler))
app.use(function(req, res) {
res.sendFile(__dirname + '/index.html')
})
app.listen(port, function(error) {
if (error) {
console.error(error)
} else {
console.info("==> 馃寧 Listening on port %s. Open up http://localhost:%s/ in your browser.", port, port)
}
})
webpack.config.js
var path = require('path')
var webpack = require('webpack')
var HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
devtool: 'cheap-module-eval-source-map',
entry: [
'webpack-hot-middleware/client',
path.resolve('./src/index.tsx'),
],
output: {
path: path.join(__dirname, 'dist'),
filename: 'bundle.js'
},
plugins: [
new webpack.optimize.OccurrenceOrderPlugin(),
new webpack.HotModuleReplacementPlugin(),
new HtmlWebpackPlugin({ template: './index.html' })
],
module: {
loaders: [
{ test: /\.tsx?$/, loader: 'ts-loader' }
]
},
resolve: {
extensions: ['', '.ts', '.tsx', '.js', '.json']
},
}
index.tsx
import * as React from 'react';
import { render } from 'react-dom';
import Root from './containers/root';
render(
<Root />,
document.getElementById('root')
);
containers/root.tsx
import * as React from 'react';
export default class Root extends React.Component<void, void> {
render(): JSX.Element {
return (
<p>boom pow</p>
);
}
}
Changing <p>boom pow</p> to <p>boom boom pow</p> in the root element kicks off this in the javascript console in the browser:
[HMR] bundle rebuilding
client.js?3ac5:126 [HMR] bundle rebuilt in 557ms
process-update.js?e13e:27 [HMR] Checking for updates on the server...
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 http://webpack.github.io/docs/hot-module-replacement-with-webpack.html for more details.
process-update.js?e13e:89 [HMR] - ./src/containers/root.tsx
process-update.js?e13e:89 [HMR] - ./src/index.tsx
I've stepped through these steps as best I can tell, but am still having no luck.
What am I missing?
This module mainly provides a transport between the client and the server for hot updates - it doesn't provide any logic for what to actually do with a hot update.
From the readme
This module is only concerned with the mechanisms to connect a browser client to a webpack server & receive updates. It will subscribe to changes from the server and execute those changes using webpack's HMR api. Actually making your application capable of using hot reloading to make seamless changes is out of scope, and usually handled by another library.
What this means in practice, is you either need to add some code which calls module.hot.accept(), or use a plugin which can automatically add this code to your modules - otherwise webpack doesn't know how to apply the hot update.
For react, this is often done via https://github.com/gaearon/babel-plugin-react-transform or https://github.com/gaearon/react-hot-loader
Please let me know if there's something I could add to the README to make this clearer - I get these questions quite often :)
@glenjamin it would be nice to have an abstract of your answer here in the readme. For the unexperienced there is not much to connect. When you say "Actually making your application capable of using hot reloading to make seamless changes is out of scope, and usually handled by another library." you kinda leave it afloat. Maybe you could point a finger in the right direction for common needs?
That's a good suggestion, I'll aim to do something useful soon.
If anyone else fancies submitting a PR for this, please do.
Interesting point. I didn't realise that tbh. Maybe thats why mine is [HMR] connected but it forces a full reload
Same problem here. What I do wrong?

// package.json
{
"name": "yoloq",
"private": true,
"devDependencies": {
"autoprefixer": "^6.4.0",
"babel-core": "^6.14.0",
"babel-loader": "^6.2.5",
"babel-plugin-transform-flow-strip-types": "^6.14.0",
"babel-plugin-transform-runtime": "^6.12.0",
"babel-polyfill": "^6.13.0",
"babel-preset-es2015": "^6.14.0",
"babel-preset-react": "^6.11.1",
"babel-preset-stage-0": "^6.5.0",
"css-loader": "^0.24.0",
"history": "^3.0.0",
"node-sass": "^3.8.0",
"normalizr": "^2.2.1",
"postcss-loader": "^0.10.1",
"react": "^15.3.1",
"react-dom": "^15.3.1",
"react-hot-loader": "^1.3.0",
"react-redux": "^4.4.5",
"react-router": "^2.7.0",
"react-router-redux": "^4.0.5",
"redux": "^3.5.2",
"redux-logger": "^2.6.1",
"redux-thunk": "^2.1.0",
"reselect": "^2.5.3",
"sass-loader": "^4.0.0",
"style-loader": "^0.13.1"
},
"dependencies": {
"body-parser": "^1.15.2",
"express": "^4.14.0",
"webpack": "^1.13.2",
"webpack-dev-middleware": "^1.6.1",
"webpack-hot-middleware": "^2.12.2"
}
}
// webpack.config.js
const path = require('path');
const fs = require('fs');
const webpack = require('webpack');
const autoprefixer = require('autoprefixer');
const ASSETS_PATH = path.resolve('./assets');
const SRC_PATH = path.resolve('./src');
const RESOLVE_EXTS = ['', '.js', '.jsx', '.scss'];
module.exports = {
context: SRC_PATH,
entry: entries(),
output: {
path: ASSETS_PATH,
filename: '[name].js',
publicPath: '/assets/',
},
resolve: {
extensions: RESOLVE_EXTS,
},
module: {
loaders: [
{
test: /\.jsx?$/,
include: SRC_PATH,
loaders: [
'react-hot',
'babel',
],
},
{
test: /\.scss$/,
include: SRC_PATH,
loaders: [
'style',
'css?sourceMap!postcss!sass?sourceMap',
],
},
],
},
postcss: [autoprefixer],
plugins: [
new webpack.optimize.OccurenceOrderPlugin(),
new webpack.HotModuleReplacementPlugin(),
new webpack.NoErrorsPlugin(),
],
devtool: 'eval',
};
function entries() {
const POLY = 'babel-polyfill';
const HOT_MW = 'webpack-hot-middleware/client';
return fs.readdirSync(SRC_PATH)
.reduce((memo, module) => {
memo[module] = [
POLY,
HOT_MW,
path.resolve(SRC_PATH, module),
];
return memo;
}, {});
}
// index.js
'use strict';
const path = require('path');
const express = require('express');
const bodyParser = require('body-parser');
const hot = require('./hot');
const app = express();
app.use(bodyParser.json());
app.use(express.static(path.resolve('./assets')));
hot(app);
app.get('/ping', (req, res) => {
res.status(200).send('pong');
});
app.listen(1337, () => console.log('Server is running'));
// hot.js
'use strict';
const webpack = require('webpack');
const wdm = require('webpack-dev-middleware');
const whm = require('webpack-hot-middleware');
const config = require('./webpack.config');
const compiler = webpack(config);
function initHot(app) {
app.use(wdm(compiler, {
publicPath: config.output.publicPath,
stats: {
colors: true,
},
}));
app.use(whm(compiler));
}
module.exports = initHot;
@miraage, see glenjamin 's reply, you will need react-hot-loader or babel-plugin-react-transform in your project
Still getting this message even with react-hot-loader and babel-plugin-react-transform.
babel-plugin-react-transform IS DEPRECATED, use react-hot-loader
Most helpful comment
This module mainly provides a transport between the client and the server for hot updates - it doesn't provide any logic for what to actually do with a hot update.
From the readme
What this means in practice, is you either need to add some code which calls
module.hot.accept(), or use a plugin which can automatically add this code to your modules - otherwise webpack doesn't know how to apply the hot update.For react, this is often done via https://github.com/gaearon/babel-plugin-react-transform or https://github.com/gaearon/react-hot-loader
Please let me know if there's something I could add to the README to make this clearer - I get these questions quite often :)