reactjstypescriptwebpackwebpack-dev-serverhot-module-replacement

The following modules couldn't be hot updated: (Full reload needed)


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?


Solution

  • The problem, as mentioned by commenters, was missing in my loader - I'm not sure if this had anything to do with it, but I also switched to using babel after typescript - and having typescript compile to ES6. New config below:

    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.ts'), 
        ],
        output: {
            path: path.join(__dirname, 'dist'),
            filename: 'bundle.js'
        },
        plugins: [
            new webpack.optimize.OccurrenceOrderPlugin(),
            new webpack.HotModuleReplacementPlugin(),
            new HtmlWebpackPlugin({ template: path.resolve('./src/index.html') })
        ],
        module: {
            loaders: [
                {   test: /\.tsx?$/, 
                    loaders: [
                        'react-hot',
                        'babel?presets[]=es2015',                  
                        'ts-loader'
                    ] 
                },
                {   test: /\.json$/, 
                    loader: 'json'
                }
            ]
        },
        resolve: {
            extensions: ['', '.ts', '.tsx', '.js', '.json']
        },
    }