question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Hot reloading doesn't work in 2.0

See original GitHub issue
  • Node Version: 8.9.4
  • NPM Version: 5.2.0
  • koa Version: ^2.3.0
  • koa-webpack: ^2.0.3
v2 webpack.config
// webpack.config.js
'use strict' // eslint-disable-line

const path = require('path')
const webpack = require('webpack')
const ExtractTextPlugin = require('extract-text-webpack-plugin')
const StyleLintPlugin = require('stylelint-webpack-plugin')
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer')
const { CSSModules, inlineLimit } = require('./config')

const nodeEnv = process.env.NODE_ENV || 'development'
const isDev = nodeEnv !== 'production'

const WebpackIsomorphicToolsPlugin = require('webpack-isomorphic-tools/plugin')
const webpackIsomorphicToolsPlugin = new WebpackIsomorphicToolsPlugin(require('./WIT.config')).development(isDev)

// Setting the plugins for development/production
const getPlugins = () => {
  // Common
  const plugins = [
    new ExtractTextPlugin({
      filename: '[name].[contenthash:8].css',
      allChunks: true,
      disable: isDev, // Disable css extracting on development
      ignoreOrder: CSSModules
    }),
    new webpack.LoaderOptionsPlugin({
      options: {
        // Javascript lint
        eslint: {},
        context: '/', // Required for the sourceMap of css/sass loader
        debug: isDev,
        minimize: !isDev
      }
    }),
    // Style lint
    new StyleLintPlugin({ files: ['src/**/*.css'], quiet: false }),
    // Setup environment variables for client
    new webpack.EnvironmentPlugin({ NODE_ENV: JSON.stringify(nodeEnv) }),
    // Setup global variables for client
    new webpack.DefinePlugin({
      __CLIENT__: true,
      __SERVER__: false,
      __DEV__: isDev
    }),
    new webpack.NoEmitOnErrorsPlugin(),
    webpackIsomorphicToolsPlugin,
    new webpack.optimize.CommonsChunkPlugin({ name: 'vendor', minChunks: module => /node_modules/.test(module.resource) })
  ]

  if (isDev) {
    // For development
    plugins.push(
      // Prints more readable module names in the browser console on HMR updates
      new webpack.NamedModulesPlugin(),
      new webpack.IgnorePlugin(/webpack-stats\.json$/),
      new BundleAnalyzerPlugin({
        analyzerMode: 'static',
        openAnalyzer: false
      })
    )
  } else {
    plugins.push(
      // For production
      new webpack.HashedModuleIdsPlugin(),
      new webpack.optimize.UglifyJsPlugin({
        sourceMap: true,
        beautify: false,
        mangle: { screw_ie8: true },
        compress: {
          screw_ie8: true, // React doesn't support IE8
          warnings: false,
          unused: true,
          dead_code: true
        },
        output: { screw_ie8: true, comments: false }
      })
    )
  }

  return plugins
}

// get babel plugins for dev/production
const getBabelPlugins = () => {
  const plugins = [
    'react-hot-loader/babel',
    'transform-object-rest-spread',
    'transform-class-properties',
    [
      'transform-imports',
      {
        'redux-form': {
          transform: 'redux-form/es/${member}', // eslint-disable-line no-template-curly-in-string
          preventFullImport: true
        },
        lodash: {
          transform: 'lodash/${member}', // eslint-disable-line no-template-curly-in-string
          preventFullImport: true
        }
      }
    ]
  ]

  if (isDev) {
    plugins.push('transform-react-jsx-source')
  }

  return plugins
}

// Setting the entry for development/production
const getEntry = () => {
  // For development
  let entry = [
    'babel-polyfill', // Support promise for IE browser (for dev)
    'react-hot-loader/patch',
    './src/client.js'
  ]

  // For production
  if (!isDev) {
    entry = {
      main: './src/client.js'
    }
  }

  return entry
}

// Setting webpack config
module.exports = {
  name: 'client',
  target: 'web',
  cache: isDev,
  devtool: isDev ? 'cheap-module-eval-source-map' : 'hidden-source-map',
  context: path.join(process.cwd()),
  entry: getEntry(),
  output: {
    path: path.join(process.cwd(), './build/public/assets'),
    publicPath: '/assets/',
    // Don't use chunkhash in development it will increase compilation time
    filename: isDev ? '[name].js' : '[name].[chunkhash:8].js',
    chunkFilename: isDev ? '[name].chunk.js' : '[name].[chunkhash:8].chunk.js',
    pathinfo: isDev
  },
  module: {
    noParse: [/dtrace-provider/, /safe-json-stringify/, /mv/, /source-map-support/],
    rules: [
      {
        test: /\.jsx?$/,
        enforce: 'pre',
        exclude: /node_modules/,
        loader: 'eslint',
        options: {
          fix: true
        }
      },
      {
        test: /node_modules[/\\]jsonstream/i,
        loader: 'shebang'
      },
      {
        test: /\.jsx?$/,
        loader: 'babel',
        exclude: /node_modules/,
        options: {
          cacheDirectory: isDev,
          babelrc: false,
          presets: [
            [
              'env',
              {
                targets: {
                  browsers: ['last 2 versions', 'ie >= 10']
                },
                useBuiltIns: true
              }
            ],
            'react'
          ],
          plugins: getBabelPlugins()
        }
      },
      {
        test: /\.css$/,
        exclude: /node_modules/,
        loader: ExtractTextPlugin.extract({
          fallback: 'style',
          use: [
            {
              loader: 'css',
              options: {
                importLoaders: 1,
                sourceMap: true,
                modules: CSSModules,
                // "context" and "localIdentName" need to be the same with server config,
                // or the style will flick when page first loaded
                context: path.join(process.cwd(), './src'),
                localIdentName: isDev ? '[name]__[local].[hash:base64:5]' : '[hash:base64:5]',
                minimize: !isDev
              }
            },
            {
              loader: 'postcss'
            }
          ]
        })
      },
      {
        test: /\.css$/,
        use: ExtractTextPlugin.extract({
          fallback: 'style-loader',
          use: [
            {
              loader: 'css-loader'
            }
          ]
        }),
        include: [/node_modules[/\\]animate.css/,
          /flexboxgrid/,
          /react-table/,
          /react-datepicker/,
          /react-checkbox/
        ]
      },
      {
        test: /\.(woff2?|ttf|eot|svg)$/,
        loader: 'url',
        options: { limit: inlineLimit }
      },
      {
        test: webpackIsomorphicToolsPlugin.regular_expression('images'),
        // Any image below or equal to 10K will be converted to inline base64 instead
        use: [
          {
            loader: 'url',
            options: { limit: inlineLimit }
          },
          // Using for image optimization
          {
            loader: 'image-webpack',
            options: { bypassOnDebug: true }
          }
        ]
      }
    ]
  },
  plugins: getPlugins(),
  // Where to resolve our loaders
  resolveLoader: {
    modules: ['src', 'node_modules'],
    moduleExtensions: ['-loader']
  },
  resolve: {
    modules: ['src', 'node_modules'],
    descriptionFiles: ['package.json'],
    moduleExtensions: ['-loader'],
    extensions: ['.js', '.jsx', '.json']
  },
  // Some libraries import Node modules but don't use them in the browser.
  // Tell Webpack to provide empty mocks for them so importing them works.
  // https://webpack.github.io/docs/configuration.html#node
  // https://github.com/webpack/node-libs-browser/tree/master/mock
  node: {
    fs: 'empty',
    vm: 'empty',
    net: 'empty',
    tls: 'empty'
  }
}

v2 app.js
// app.js

  const config = require('../tools/webpack/webpack.client.babel')

  app.use(require('koa-webpack')({
    config,
    dev: {
      publicPath: config.output.publicPath,
      noInfo: true,
      stats: 'minimal'
    },
    hot: { port: 3001 }  // this bit was added after 2.x migration as the default port 8081 is taken up in my PC
  }))

Expected Behavior

Hot reloading should work. Browser should show HMR connected in console.

Actual Behavior

Doesn’t work. I neither see HMR connected message nor does the browser refreshes when I change source files. Webpack builds the changes.

How can we reproduce the behavior?

The same config (minus changes required for v2.x migration) worked without any issues with v1. Here are the relevant bits:

v1 webpack config
'use strict' // eslint-disable-line

const path = require('path')
const webpack = require('webpack')
const ExtractTextPlugin = require('extract-text-webpack-plugin')
const StyleLintPlugin = require('stylelint-webpack-plugin')
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer')
const { CSSModules, inlineLimit } = require('./config')

const nodeEnv = process.env.NODE_ENV || 'development'
const isDev = nodeEnv !== 'production'

const WebpackIsomorphicToolsPlugin = require('webpack-isomorphic-tools/plugin')
const webpackIsomorphicToolsPlugin = new WebpackIsomorphicToolsPlugin(require('./WIT.config')).development(isDev)

// Setting the plugins for development/production
const getPlugins = () => {
  // Common
  const plugins = [
    new ExtractTextPlugin({
      filename: '[name].[contenthash:8].css',
      allChunks: true,
      disable: isDev, // Disable css extracting on development
      ignoreOrder: CSSModules
    }),
    new webpack.LoaderOptionsPlugin({
      options: {
        // Javascript lint
        eslint: {},
        context: '/', // Required for the sourceMap of css/sass loader
        debug: isDev,
        minimize: !isDev
      }
    }),
    // Style lint
    new StyleLintPlugin({ files: ['src/**/*.css'], quiet: false }),
    // Setup environment variables for client
    new webpack.EnvironmentPlugin({ NODE_ENV: JSON.stringify(nodeEnv) }),
    // Setup global variables for client
    new webpack.DefinePlugin({
      __CLIENT__: true,
      __SERVER__: false,
      __DEV__: isDev
    }),
    new webpack.NoEmitOnErrorsPlugin(),
    webpackIsomorphicToolsPlugin,
    new webpack.optimize.CommonsChunkPlugin({ name: 'vendor', minChunks: module => /node_modules/.test(module.resource) })
  ]

  if (isDev) {
    // For development
    plugins.push(
      new webpack.HotModuleReplacementPlugin(),
      // Prints more readable module names in the browser console on HMR updates
      new webpack.NamedModulesPlugin(),
      new webpack.IgnorePlugin(/webpack-stats\.json$/),
      new BundleAnalyzerPlugin({
        analyzerMode: 'static',
        openAnalyzer: false
      })
    )
  } else {
    plugins.push(
      // For production
      new webpack.HashedModuleIdsPlugin(),
      new webpack.optimize.UglifyJsPlugin({
        sourceMap: true,
        beautify: false,
        mangle: { screw_ie8: true },
        compress: {
          screw_ie8: true, // React doesn't support IE8
          warnings: false,
          unused: true,
          dead_code: true
        },
        output: { screw_ie8: true, comments: false }
      })
    )
  }

  return plugins
}

// get babel plugins for dev/production
const getBabelPlugins = () => {
  const plugins = [
    'react-hot-loader/babel',
    'transform-object-rest-spread',
    'transform-class-properties',
    [
      'transform-imports',
      {
        'redux-form': {
          transform: 'redux-form/es/${member}', // eslint-disable-line no-template-curly-in-string
          preventFullImport: true
        },
        lodash: {
          transform: 'lodash/${member}', // eslint-disable-line no-template-curly-in-string
          preventFullImport: true
        }
      }
    ]
  ]

  if (isDev) {
    plugins.push('transform-react-jsx-source')
  }

  return plugins
}

// Setting the entry for development/production
const getEntry = () => {
  // For development
  let entry = [
    'babel-polyfill', // Support promise for IE browser (for dev)
    'react-hot-loader/patch',
    'webpack-hot-middleware/client?reload=true',
    './src/client.js'
  ]

  // For production
  if (!isDev) {
    entry = {
      main: './src/client.js'
    }
  }

  return entry
}

// Setting webpack config
module.exports = {
  name: 'client',
  target: 'web',
  cache: isDev,
  devtool: isDev ? 'cheap-module-eval-source-map' : 'hidden-source-map',
  context: path.join(process.cwd()),
  entry: getEntry(),
  output: {
    path: path.join(process.cwd(), './build/public/assets'),
    publicPath: '/assets/',
    // Don't use chunkhash in development it will increase compilation time
    filename: isDev ? '[name].js' : '[name].[chunkhash:8].js',
    chunkFilename: isDev ? '[name].chunk.js' : '[name].[chunkhash:8].chunk.js',
    pathinfo: isDev
  },
  module: {
    noParse: [/dtrace-provider/, /safe-json-stringify/, /mv/, /source-map-support/],
    rules: [
      {
        test: /\.jsx?$/,
        enforce: 'pre',
        exclude: /node_modules/,
        loader: 'eslint',
        options: {
          fix: true
        }
      },
      {
        test: /node_modules[/\\]jsonstream/i,
        loader: 'shebang'
      },
      {
        test: /\.jsx?$/,
        loader: 'babel',
        exclude: /node_modules/,
        options: {
          cacheDirectory: isDev,
          babelrc: false,
          presets: [
            [
              'env',
              {
                targets: {
                  browsers: ['last 2 versions', 'ie >= 10']
                },
                useBuiltIns: true
              }
            ],
            'react'
          ],
          plugins: getBabelPlugins()
        }
      },
      {
        test: /\.css$/,
        exclude: /node_modules/,
        loader: ExtractTextPlugin.extract({
          fallback: 'style',
          use: [
            {
              loader: 'css',
              options: {
                importLoaders: 1,
                sourceMap: true,
                modules: CSSModules,
                // "context" and "localIdentName" need to be the same with server config,
                // or the style will flick when page first loaded
                context: path.join(process.cwd(), './src'),
                localIdentName: isDev ? '[name]__[local].[hash:base64:5]' : '[hash:base64:5]',
                minimize: !isDev
              }
            },
            {
              loader: 'postcss'
            }
          ]
        })
      },
      {
        test: /\.css$/,
        use: ExtractTextPlugin.extract({
          fallback: 'style-loader',
          use: [
            {
              loader: 'css-loader'
            }
          ]
        }),
        include: [/node_modules[/\\]animate.css/,
          /flexboxgrid/,
          /react-table/,
          /react-datepicker/,
          /react-checkbox/
        ]
      },
      {
        test: /\.(woff2?|ttf|eot|svg)$/,
        loader: 'url',
        options: { limit: inlineLimit }
      },
      {
        test: webpackIsomorphicToolsPlugin.regular_expression('images'),
        // Any image below or equal to 10K will be converted to inline base64 instead
        use: [
          {
            loader: 'url',
            options: { limit: inlineLimit }
          },
          // Using for image optimization
          {
            loader: 'image-webpack',
            options: { bypassOnDebug: true }
          }
        ]
      }
    ]
  },
  plugins: getPlugins(),
  // Where to resolve our loaders
  resolveLoader: {
    modules: ['src', 'node_modules'],
    moduleExtensions: ['-loader']
  },
  resolve: {
    modules: ['src', 'node_modules'],
    descriptionFiles: ['package.json'],
    moduleExtensions: ['-loader'],
    extensions: ['.js', '.jsx', '.json']
  },
  // Some libraries import Node modules but don't use them in the browser.
  // Tell Webpack to provide empty mocks for them so importing them works.
  // https://webpack.github.io/docs/configuration.html#node
  // https://github.com/webpack/node-libs-browser/tree/master/mock
  node: {
    fs: 'empty',
    vm: 'empty',
    net: 'empty',
    tls: 'empty'
  }
}
v1 app.js
// app.js

  const config = require('../tools/webpack/webpack.client.babel')

  app.use(require('koa-webpack')({
    config,
    dev: {
      publicPath: config.output.publicPath,
      noInfo: true,
      stats: 'minimal'
    }
  }))

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Comments:11 (4 by maintainers)

github_iconTop GitHub Comments

2reactions
mrchiefcommented, Jan 23, 2018

Works like a charm!

image

And love the new icon in the console log! 👍

2reactions
shellscapecommented, Jan 23, 2018

I just published a patch version to webpack-hot-client that might resolve one or more issues you all are facing. Please do let me know if that works. Will probably require a reinstall of koa-webpack.

Read more comments on GitHub >

github_iconTop Results From Across the Web

(S)CSS modules hot reloading doesn't work in CRA 2.0 #4690
If you edit App.module.css or App.module.scss , the whole app reloads, whereas for editing App.css the stylesheet is updated without a reload.
Read more >
Hot module reload is not working on my nextjs app
I just solve this problem just by delete folder ".next" and then close terminal and run again npm run ...
Read more >
Hot Reload doesn't work after updating to 16.9 Prev2
[severity:It's more difficult to complete my work] [regression] [worked-in:16.9 prev1] Hot reload stopped working on android emulator after updating.
Read more >
Hot Reloading in React - Medium
As long as you configure Webpack to enable HMR, the code above works fine and redraws your application when a hot reload occurs...
Read more >
XAML Hot Reload not working. - Microsoft Q&A
I uninstalled VS for Mac and installed it again, Then XHR added to VS but it does not work! I have VS 8.9...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found