Webpack HotModuleReplacement css

I am trying to use webpack as a replacement for gulp and workspace workflow. I have installed the HotModuleReplacement plugin and it works correctly for JS files, but I cannot get it to work with SCSS files. It compiles SCSS to CSS correctly, but I have to manually refresh the browser each time to reflect the style changes. I think it might be a bug in the way I set up the config or something.

I have this server.js file that works:

var webpack = require('webpack');
var WebpackDevServer = require('webpack-dev-server');
var config = require('./webpack.config');

new WebpackDevServer(webpack(config), {
    publicPath: config.output.publicPath,
    hot: true,
    historyApiFallback: true,
    noInfo: true,   
    stats: { colors: true }
}).listen(3000, 'localhost', function (err, result) {
    if (err) {
    console.log(err);
    }

    console.log('Listening at localhost:3000');
});

      

and this webpack.config.js

var path = require('path');
var webpack = require('webpack');
var ExtractTextPlugin = require('extract-text-webpack-plugin');

var cssLoaders = ['css-loader'];
var jsLoaders = ['react-hot', 'babel'];
var scssLoaders = cssLoaders.slice(0);
scssLoaders.push('sass-loader?includePaths[]=' + path.resolve(__dirname, './styles'));

module.exports = {

  devtool: 'sourcemap',
  entry: [
    'webpack-dev-server/client?http://localhost:3000',
    'webpack/hot/only-dev-server',
    './scripts/index'
  ],
  output: {
    path: path.join(__dirname, './build'),
    filename: 'bundle.js',
    publicPath: '/build/'
  },
  plugins: [
    new webpack.HotModuleReplacementPlugin(),
    new webpack.NoErrorsPlugin(),
    new ExtractTextPlugin('styles.css')
  ],
  resolve: {
    extensions: ['', '.js', '.jsx', '.scss']
  },
  module: {
    loaders: [
      { test: /\.js?$/, loaders: jsLoaders, include: path.join(__dirname, 'scripts'), exclude: /node_modules/},
      { test: /\.css$/ ,loader: ExtractTextPlugin.extract('style-loader', cssLoaders.join('!')) },
      { test: /\.js$/, loader: "eslint-loader", exclude: /node_modules/ },
      { test: /\.scss$/, loader: ExtractTextPlugin.extract('style-loader', scssLoaders.join('!')) }
    ]
  }
};

      

In one of my js files, I just call the SCSS file like this:

require('../styles/app');

      

I have looked through the docs for this and there are some instructions that suggest you have to manually select for each module, but I'm not sure why that is, where to add this code, etc. What I'm trying to do seems like a pretty simple use case, so is this supported or do I still have to use gulp and live reloads for styles only?

+3


source to share


2 answers


Unfortunately, extract-text-webpack-plugin

which pulls all your styles into a CSS file does not work with hot reload (see https://github.com/webpack/extract-text-webpack-plugin/issues/30 ).

This hacked bit of JavaScript will reload all stylesheets every time it detects any hot reload event. However, it can be annoying and work better in Firefox than Chrome. Chrome delays the application of the new stylesheet until you hide the browser tab.



if (module.hot) {
    $(window).on("message onmessage", function(event) {
        if (typeof event.originalEvent.data === "string" && event.originalEvent.data.indexOf("webpackHotUpdate") === 0) {
            console.log("Reloading style sheets...");
            document.styleSheets.forEach(function (sheet) {
                if ((sheet.href || "").indexOf('localhost') !== -1) {
                    sheet.ownerNode.href = sheet.href;
                }
            });
        }
    });
}

      

There might be some way to get caught in the guts of the hot reload code, but I haven't looked at it.

+4


source


As mentioned above, extract-text-webpack-plugin

does not work properly with hot swap, unfortunately :( But there is another option to solve this problem during development. Disable this property in the extract plugin settings.

Change the configuration as described below:

plugins: [
    new ExtractTextPlugin('styles.css', {disable: process.env.NODE_ENV !== 'production'})
]

      

This will disable usage ExtractTextPlugin

during development (I mean if you run it anyway, but NODE_ENV=production webpack

or whatever rule you prefer) and bundle your styles into js.

You also need to import the style file to the entry point. Hope it works. Greetings;)




PS. Also, you can not combine the entry point with and add to plugins manually, simply by running the webpack dev server with additional parameters'webpack-dev-server/client?http://localhost:3000', 'webpack/hot/only-dev-server'

new webpack.HotModuleReplacementPlugin()

webpack-dev-server --inline --hot

      

inline

means webpack-dev-server/client

also --hot

forwebpack-dev-server/client

0


source







All Articles