Unable to HMR (Hot Module Replacement) css/scss with Webpack 2.2.0 and webpack-dev-server 2.2.1
J

2

11

Versions

"extract-text-webpack-plugin": "^2.0.0-rc.2",

"webpack": "^2.2.0",

"webpack-dev-server": "^2.2.1"

Issue

"extract-text-webpack-plugin": "^1.0.1",

"webpack": "^1.14.0",

"webpack-dev-server": "^1.16.2"

No longer able to HMR css/scss since upgrading to version 2, changing the styles triggers a change (see output sample below) but I have to manually refresh the page to see the changes the page does not auto refresh, also if I make a change to a js file after changing a scss file the changes are then reflected as the js change trigger a HMR which also includes the style changes, but only changing the styles with no js changes requires a manual page refresh.

Any ideas if I have configured something wrong or what I need to do for the css/scss HMR to work?

I have also posted the issue here: https://github.com/webpack-contrib/extract-text-webpack-plugin/issues/384 but not sure if it is webpack-dev-server issue or the extract-text-webpack-plugin issue or simply something I have done.

Command running:

npm run dev

"scripts": {
    "dev": "webpack-dev-server --hot --inline"
  }

Configuration before upgrade:

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

const BUILD_DIR = path.resolve(__dirname, 'public');
const APP_DIR = path.resolve(__dirname, 'app');

let generateHtml = new HtmlWebpackPlugin({ title: 'My App' });
let extractCSS = new ExtractTextPlugin('styles/[name].css', { allChunks: true });

const config = {
  entry: APP_DIR + '/index.js',
  output: {
    path: BUILD_DIR,
    filename: 'bundle.js'
  },
  externals: {
    'cheerio': 'window',
    'react/lib/ExecutionEnvironment': true,
    'react/lib/ReactContext': true,
  },
  module : {
    loaders : [
      {
        test : /\.jsx?/,
        include : APP_DIR,
        loader : 'babel'
      },
      {
        test: /\.scss$/,
        loader: extractCSS.extract('style', 'css?modules=true!sass?sourceMap=true')
      }
    ]
  },
  plugins: [
    generateHtml,
    extractCSS
  ]
};

module.exports = config;

Configuration after upgrade:

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

const BUILD_DIR = path.resolve(__dirname, 'public');
const APP_DIR = path.resolve(__dirname, 'app');

let generateHtml = new HtmlWebpackPlugin({ title: 'My App' });
let extractCSS = new ExtractTextPlugin({ filename: 'styles/[name].css', allChunks: true });

const config = {
  entry: APP_DIR + '/index.js',
  output: {
    path: BUILD_DIR,
    filename: 'bundle.js'
  },
  externals: {
    'cheerio': 'window',
    'react/lib/ExecutionEnvironment': true,
    'react/lib/ReactContext': true,
  },
  module : {
    loaders : [
      {
        test : /\.(js|jsx)?/,
        include : APP_DIR,
        loader : 'babel-loader'
      },
      {
        test: /\.scss$/,
        loader: extractCSS.extract({
          fallbackLoader: 'style-loader',
          loader: ['css-loader?modules', 'sass-loader']
        })
      }
    ]
  },
  plugins: [
    generateHtml,
    extractCSS
  ]
};

module.exports = config;

Output sample initial page load.

> webpack-dev-server --hot --inline

Project is running at http://localhost:8080/
webpack output is served from /
Hash: 0e873f689fcea2b7cee6
Version: webpack 2.2.0
Time: 3350ms
          Asset       Size  Chunks                    Chunk Names
      bundle.js     1.1 MB       0  [emitted]  [big]  main
styles/main.css  634 bytes       0  [emitted]         main
     index.html  223 bytes          [emitted]         
chunk    {0} bundle.js, styles/main.css (main) 1.03 MB [entry] [rendered]
   [19] ./~/react/react.js 56 bytes {0} [built]
   [45] ./~/redux/es/index.js 1.08 kB {0} [built]
  [106] ./~/react-redux/es/index.js 194 bytes {0} [built]
  [129] (webpack)/hot/emitter.js 77 bytes {0} [built]
  [130] ./app/index.js 938 bytes {0} [built]
  [131] (webpack)-dev-server/client?http://localhost:8080 4.66 kB {0} [built]
  [132] (webpack)/hot/dev-server.js 1.57 kB {0} [built]
  [139] ./app/containers/App.js 4.25 kB {0} [built]
  [178] ./~/react-dom/index.js 59 bytes {0} [built]
  [269] ./~/redux-thunk/lib/index.js 529 bytes {0} [built]
  [300] ./~/strip-ansi/index.js 161 bytes {0} [built]
  [305] ./~/url/url.js 23.3 kB {0} [built]
  [307] (webpack)-dev-server/client/socket.js 856 bytes {0} [built]
  [309] (webpack)/hot/log-apply-result.js 1.02 kB {0} [built]
  [310] multi (webpack)-dev-server/client?http://localhost:8080 webpack/hot/dev-server ./app/index.js 52 bytes {0} [built]
     + 296 hidden modules
Child html-webpack-plugin for "index.html":
    chunk    {0} index.html 541 kB [entry] [rendered]
        [0] ./~/lodash/lodash.js 540 kB {0} [built]
        [1] (webpack)/buildin/global.js 509 bytes {0} [built]
        [2] (webpack)/buildin/module.js 517 bytes {0} [built]
        [3] ./~/html-webpack-plugin/lib/loader.js!./~/html-webpack-plugin/default_index.ejs 540 bytes {0} [built]
Child extract-text-webpack-plugin:
    chunk    {0} extract-text-webpack-plugin-output-filename 1.77 kB [entry] [rendered]
        [0] ./~/css-loader/lib/css-base.js 1.51 kB {0} [built]
        [1] ./~/css-loader?modules!./~/sass-loader!./app/components/user/users.scss 267 bytes {0} [built]
Child extract-text-webpack-plugin:
    chunk    {0} extract-text-webpack-plugin-output-filename 1.81 kB [entry] [rendered]
        [0] ./~/css-loader/lib/css-base.js 1.51 kB {0} [built]
        [1] ./~/css-loader?modules!./~/sass-loader!./app/containers/app.scss 307 bytes {0} [built]
Child extract-text-webpack-plugin:
    chunk    {0} extract-text-webpack-plugin-output-filename 2.21 kB [entry] [rendered]
        [0] ./~/css-loader/lib/css-base.js 1.51 kB {0} [built]
        [1] ./~/css-loader?modules!./~/sass-loader!./app/components/navbar/navbar.scss 702 bytes {0} [built]
Child extract-text-webpack-plugin:
    chunk    {0} extract-text-webpack-plugin-output-filename 1.87 kB [entry] [rendered]
        [0] ./~/css-loader/lib/css-base.js 1.51 kB {0} [built]
        [1] ./~/css-loader?modules!./~/sass-loader!./app/components/common/common.scss 361 bytes {0} [built]
webpack: bundle is now VALID.

Output sample after scss change.

webpack: bundle is now INVALID.
Hash: f16b1beda9083db91735
Version: webpack 2.2.0
Time: 251ms
                               Asset       Size  Chunks                    Chunk Names
                           bundle.js     1.1 MB       0  [emitted]  [big]  main
0e873f689fcea2b7cee6.hot-update.json   35 bytes          [emitted]         
                     styles/main.css  626 bytes       0  [emitted]         main
chunk    {0} bundle.js, styles/main.css (main) 1.03 MB [entry] [rendered]
  [143] ./app/components/navbar/navbar.scss 181 bytes {0} [built]
     + 310 hidden modules
Child html-webpack-plugin for "index.html":
    chunk    {0} index.html 541 kB [entry]
         + 4 hidden modules
Child extract-text-webpack-plugin:
    chunk    {0} extract-text-webpack-plugin-output-filename 2.2 kB [entry] [rendered]
        [1] ./~/css-loader?modules!./~/sass-loader!./app/components/navbar/navbar.scss 694 bytes {0} [built]
         + 1 hidden modules
webpack: bundle is now VALID.

You can see the size of the main.css changed, but the page never refreshed until I pressed f5

Jarv answered 31/1, 2017 at 13:15 Comment(0)
R
4

for better control over CSS HMR while using extract-text-webpack-plugin use css-hot-loader

below is my usage code sample in the rules collection

{ test: /\.css$/, use: ['css-hot-loader'].concat(ExtractTextPlugin.extract({ fallback: 'style-loader', use: 'css-loader' })) }

Rupture answered 20/4, 2018 at 1:45 Comment(2)
Waoh !! Just works perfectly, thanks ;) Should be accepted answerRancher
ExtractTextPlugin is deprecated, and I wasn't able to get css-hot-loader with extract-mini-css-pluginHighfalutin
P
2

As stated in the github main page of extract-text-webpack-plugin: Caveats: "No Hot Module Replacement"

You should not use this plugin while development, it is still useful for creating build for production. You can create two webpack config files, one for dev and one for prod, that might help for both scenarios.

Prior answered 31/1, 2017 at 17:20 Comment(1)
While the documentation states Caveats: "No Hot Module Replacement", the documentation and behaviour do not match. Checkout the following repo and commit to see HMR working perfectly with version 1, recompiling the css and refreshing the browser to automatically see the styling change. Repo: github.com/Rob-Leggett/react_redux_webpack Commit: 0d976fa734e6b8d197fe1bee58cd4ed974985854 This all stop working in the next commit, when I upgraded to version 2.Jarv

© 2022 - 2024 — McMap. All rights reserved.