webpackwebpack-dev-middlewarewebpack-hot-middleware

webpack-hot-middleware not working with webpack-dev-middleware


I'm trying to use webpack-hot-middleware to hot reload the modules of my application. I'm using webpack-dev-middleware as well.

Here is my setup.

package.json

{
  "name": "dev-front-end",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "build": "webpack --config webpack.config.production.js",
    "clean-dist": "rimraf dist",
    "lint": "esw buildScripts data/*.js src *.js --color",
    "lint:watch": "npm run lint -- --watch",
    "prebuild": "npm run clean-dist",
    "prestart": "babel-node buildScripts/startMessage.js",
    "security-check": "nsp check",
    "serve-dist": "babel-node buildScripts/distServer.js",
    "serve-src": "babel-node buildScripts/srcServer.js",
    "share": "ngrok http 3000",
    "start": "npm run serve-src",
    "test": "babel-node buildScripts/testSetup.js",
    "test:watch": "npm run test -- --watch"
  },
  "dependencies": {
    "angular": "1.5.11",
    "angular-animate": "<1.6.0",
    "angular-aria": "<1.6.0",
    "angular-audio": "^1.7.3",
    "angular-cookie": "^4.1.0",
    "angular-cookies": "<1.6.0",
    "angular-google-maps": "^2.4.1",
    "angular-ismobile": "^1.0.0",
    "angular-loading-bar": "^0.9.0",
    "angular-material": "^1.1.3",
    "angular-messages": "<1.6.0",
    "angular-scroll": "^1.0.0",
    "angular-socialshare": "^2.3.7",
    "angular-socket-io": "^0.7.0",
    "angular-timeago": "^0.4.4",
    "angular-ui-router": "^1.0.0-rc.1",
    "angulartics": "^1.4.0",
    "angulartics-google-analytics": "^0.4.0",
    "bootstrap": "v4.0.0-alpha.6",
    "bootstrap-social": "^5.1.1",
    "cropperjs": "^0.8.1",
    "font-awesome": "^4.7.0",
    "lodash": "^4.17.4",
    "ng-file-upload": "^12.2.13",
    "ng-infinite-scroll": "^1.3.0",
    "ng-token-auth": "^0.0.30",
    "ngSmoothScroll": "^2.0.0",
    "ngclipboard": "^1.1.1",
    "restangular": "^1.6.1",
    "socket.io-client": "^2.0.3"
  },
  "author": "Medhavin Goyal",
  "license": "ISC",
  "devDependencies": {
    "babel-cli": "^6.24.1",
    "babel-loader": "^7.0.0",
    "babel-preset-latest": "^6.24.1",
    "compression": "^1.6.2",
    "connect-history-api-fallback": "^1.3.0",
    "copy-webpack-plugin": "^4.0.1",
    "css-loader": "^0.28.4",
    "eslint": "^4.0.0",
    "eslint-config-angular": "^0.5.0",
    "eslint-loader": "^1.8.0",
    "eslint-plugin-angular": "^2.5.0",
    "eslint-watch": "^3.1.2",
    "express": "^4.15.3",
    "extract-text-webpack-plugin": "^2.1.2",
    "file-loader": "^0.11.2",
    "html-webpack-plugin": "^2.28.0",
    "jest": "^20.0.4",
    "ng-annotate-loader": "^0.6.1",
    "ngrok": "^2.2.11",
    "npm-run-all": "^4.0.2",
    "raw-loader": "^0.5.1",
    "rimraf": "^2.6.1",
    "strip-loader": "^0.1.2",
    "style-loader": "^0.18.2",
    "url-loader": "^0.5.9",
    "webpack": "^2.6.1",
    "webpack-dev-middleware": "^1.10.2",
    "webpack-hot-middleware": "^2.18.0"
  }
}

webpack.config.js

const path = require('path');
const webpack = require('webpack');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');

var VENDOR_LIBS = [
    'webpack-hot-middleware/client?timeout=20000&reload=true',
    'angular',
    'angular-animate',
    'angular-aria',
    'angular-audio',
    'angular-cookie',
    'angular-cookies',
    'angular-google-maps',
    'angular-ismobile',
    'angular-loading-bar',
    'angular-material',
    'angular-messages',
    'angular-scroll',
    'angular-socialshare',
    'angular-socket-io',
    'angular-timeago',
    'angular-ui-router',
    'angulartics',
    'angulartics-google-analytics',
    'bootstrap',
    'cropperjs',
    'lodash',
    'ng-file-upload',
    'ng-infinite-scroll',
    'ng-token-auth',
    'ngSmoothScroll',
    'ngclipboard',
    'restangular',
    'socket.io-client'
];

const config =  {
    entry: {
        bundle: ['webpack-hot-middleware/client?timeout=20000&reload=true', './src/app.module.js'],
        vendor: VENDOR_LIBS
    },
    output: {
        path: path.resolve(__dirname, 'build'),
        filename: 'js/[name].[hash].js',
        publicPath: '/'
    },
    module: {
        rules: [
            {
                use: 'babel-loader',
                test: /\.js$/,
                exclude: /node_modules/
            },
            {
                use: 'url-loader',
                test: /\.woff2?(\?v=[0-9]\.[0-9]\.[0-9])?$/
            },
            {
                use: 'file-loader?name=fonts/[name].[hash].[ext]',
                test: /\.(ttf|eot|svg)(\?[\s\S]+)?$/
            },
            {
                use: ExtractTextPlugin.extract({
                    use: 'css-loader'
                }),
                test: /\.css$/
            },
            {
                use: 'raw-loader',
                test: /\.html$/,
                exclude: /node_modules/
            }
        ]
    },
    plugins: [
        new ExtractTextPlugin('css/style.[hash].css'),
        new webpack.optimize.CommonsChunkPlugin({
            name: ['vendor','manifest']
        }),
        new HtmlWebpackPlugin({
            template: 'src/index.html'
        }),
        new webpack.ProvidePlugin({
            $: 'jquery',
            jQuery: 'jquery',
            'window.jQuery': 'jquery',
            Tether: 'tether',
            Popper: ['popper.js', 'default'],
            _: 'lodash',
            io: 'socket.io-client'
        }),
        new CopyWebpackPlugin([{
            from: 'assets',
            to: 'assets'
        }]),
        new webpack.HotModuleReplacementPlugin(),
        // new webpack.NoEmitOnErrorsPlugin()
    ],
    devtool: 'inline-source-map',
    target: 'web'
};

module.exports = config;

srcServer.js

import express from 'express';
import path from 'path';
import webpack from 'webpack';
import webpackMiddleware from 'webpack-dev-middleware';
import webpackHotMiddleware from 'webpack-hot-middleware';
import historyApiFallback from 'connect-history-api-fallback';
import config from '../webpack.config';

const port = 3000;
const app = express();

app.use(webpackMiddleware(webpack(config), {
    noInfo: false,
    publicPath: config.output.publicPath
}));
app.use(webpackHotMiddleware(webpack(config), {
   'log': console.log,
   'heartbeat': 10 * 1000
}));
app.use(historyApiFallback({
    disableDotRule: true
}));
app.use(webpackMiddleware(webpack(config), {
    noInfo: false,
    publicPath: config.output.publicPath
}));

app.listen(port, function(err) {
    if (err) {
        console.log(err);
    } else {
        console.log("App listening on port " + port);
    }
});

The setup is not working. The compilation works fine when I update my code, and when I refresh my browser, the new application code is executed. However the modules aren't replaced.

Output in browser console

Network Traffic

Please help me solve this issue. Thanks!


Solution

  • It should work if you follow the instructions in the fine manual, which in your case would translate to something like this:

    let compiler = webpack(config);
    
    app.use(webpackMiddleware(compiler, {
      noInfo     : false,
      publicPath : config.output.publicPath
    }));
    
    app.use(webpackHotMiddleware(compiler, {
      'log'       : console.log,
      'path'      : '/__webpack_hmr',
      'heartbeat' : 10 * 1000
    }));
    

    I'm not sure about the various options that you're passing to webpackHotMiddleware (log already defaults to console.log so you can leave it out, and you should probably use the default for path instead of setting it yourself).