Webpack 热模块替换 CSS

3

我试图使用webpack替代gulp和livereload工作流。我已经设置了HotModuleReplacement插件,对于JS文件它可以正常工作,但是我无法让它与SCSS文件一起工作。它可以正确地将SCSS编译为CSS,但每次都需要手动刷新浏览器才能显示样式更改。我认为可能是我配置设置有误或类似的问题。

我有一个server.js文件在运行:

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');
});

还有这个 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('!')) }
    ]
  }
};

在我的一个js文件中,我只是像这样调用了SCSS文件:
require('../styles/app');

我查看了相关文档,其中有些说明建议你需要手动选择每个模块,但我不确定为什么要这样做,以及在哪里添加该代码等问题。我的需求似乎是一个非常简单的用例,所以是否支持这个功能?还是说我仍然需要使用gulp和live reload来处理样式?

2个回答

4

很不幸,extract-text-webpack-plugin插件将所有样式提取到一个CSS文件中,与热重载不兼容(请参见https://github.com/webpack/extract-text-webpack-plugin/issues/30)。

这段JS代码会在检测到任何热重载事件发生时重新加载所有样式表。但是它可能会变得很烦人,并且在Firefox上效果比Chrome更好 - Chrome似乎要延迟应用新的样式表,直到你聚焦浏览器选项卡。

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;
                }
            });
        }
    });
}

可能有一些方法可以更深入地连接到热重载代码的核心,但我还没有深入研究。


0
如上所述,extract-text-webpack-plugin与热替换不兼容,很遗憾:( 但是在开发过程中有另外一种解决此问题的方法。那就是在提取插件设置中使用 disable 属性。

按照以下说明修改您的配置:

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

这将在开发过程中禁用ExtractTextPlugin的使用(我的意思是如果你以任何方式运行它,但是NODE_ENV=production webpack或者你喜欢的任何其他规则),并将你的样式捆绑在js中。

同时注意在入口点导入你的样式文件。希望这能起作用。干杯 ;)


PS. 另外,您可以避免将入口点与'webpack-dev-server/client?http://localhost:3000','webpack/hot/only-dev-server'组合,并手动添加new webpack.HotModuleReplacementPlugin()到插件中,只需使用附加参数运行webpack dev服务器即可。

webpack-dev-server --inline --hot

inline 代表 webpack-dev-server/client,而 --hot 则代表 webpack-dev-server/client


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接