【问题标题】:How to Hot Reload Sass Using Webpack 2?如何使用 Webpack 2 热重载 Sass?
【发布时间】:2017-04-07 20:56:15
【问题描述】:

我正在设置一个使用 Webpack2、webpack-dev-middleware 和 HMR 进行开发的 React 应用程序。每当我对 React 组件进行更改时,它都会按预期在浏览器中更新。我遇到的问题是,当我修改 .scss 文件时,浏览器会更新。相反,在控制台中它给了我以下信息:

[HMR] bundle rebuilding
client.js:207 [HMR] bundle rebuilt in 1567ms
process-update.js:27 [HMR] Checking for updates on the server...
process-update.js:98 [HMR] Nothing hot updated.
process-update.js:107 [HMR] App is up to date.

在此之后,当我刷新页面时,我的样式更改会出现。我不完全确定发生了什么或问题出在哪里,但希望得到一些帮助和澄清。以下是我的设置:

Webpack.config.js

var webpack = require('webpack');
var path = require('path');
var autoprefixer = require('autoprefixer');
var DashboardPlugin = require('webpack-dashboard/plugin');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var argv = require('yargs').argv;

const config = {};

// This configured production
if (argv.p) {
    config.entry = [
      './src/client/scripts/index',
      './src/client/scripts/utils/index',
      './src/client/styles/index.scss'
    ]
    config.plugins = [
      new DashboardPlugin(),
      new ExtractTextPlugin({
        filename: 'bundle.css',
        allChunks: true
      }),
    ]
}
else {
  config.entry = [
    'react-hot-loader/patch',
    'webpack-hot-middleware/client',
    './src/client/scripts/index',
    './src/client/scripts/utils/index',
    './src/client/styles/index.scss'
  ]
  config.plugins = [
    new DashboardPlugin(),
    new webpack.HotModuleReplacementPlugin(),
    new webpack.NoEmitOnErrorsPlugin(),
    new webpack.NamedModulesPlugin(),
    new ExtractTextPlugin({
      filename: 'bundle.css',
      allChunks: true
    })
  ]
}

module.exports = {
  entry: config.entry,
  output: {
    path: path.join(__dirname, 'src', 'client', 'static'),
    filename: 'bundle.js',
    publicPath: '/static/'
  },
  devtool: 'inline-source-map',
  devServer: {
    hot: true,
    contentBase: path.resolve(__dirname, 'src', 'client', 'static'),
    publicPath: (__dirname, 'src', 'client', 'static')
  },
  plugins: config.plugins,
  module: {
    rules: [
      {
        test: /\.js?$/,
        exclude: /(node_modules|bower_components)/,
        include: path.join(__dirname, 'src'),
        use: [
          {
            loader: 'babel-loader',
            query: {
              presets: ['react', ['es2015', { 'modules': false }], 'stage-0'],
              plugins: ['react-hot-loader/babel', 'react-html-attrs', 'transform-class-properties', 'transform-decorators-legacy'],
            }
          }
        ]
      },
      {
        test: /\.(png|woff|woff2|eot|ttf|svg)$/,
        use: [
          {
            loader: 'url-loader?limit=100000'
          }
        ],
      },
      {
        test: /\.scss$/,
        use: ExtractTextPlugin.extract({
          fallback: 'style-loader',
          use: ['css-loader', 'sass-loader']
        })
      }
    ]
  }
};

Server.js 使用 webpack-dev-middleware

const router = Router();
const clientDir = resolve(`${__dirname}/../../client`);

if (isDev()) {
  const webpackDevMiddleware = require('webpack-dev-middleware')
  const webpack = require('webpack')
  const webpackConfig = require('../../../webpack.config')
  const webpackHotMiddleware = require('webpack-hot-middleware')

  const compiler = webpack(webpackConfig)

  // This compiles our app using webpack
  router.use(webpackDevMiddleware(compiler, {
    publicPath: webpackConfig.output.publicPath,
    noInfo: true
  }))

  // This connects our app to HMR using the middleware
  router.use(webpackHotMiddleware(compiler))
}

router.use(express.static(clientDir));

export default router

客户端的 index.js

import React from 'react'
import ReactDOM from 'react-dom'
import { AppContainer } from 'react-hot-loader'
import App from './App'

const root = document.querySelector('.root');

// Wraps our App in AppContainer
const render = (Component) => {
  ReactDOM.render(
    <AppContainer>
      <Component/>
    </AppContainer>,
    root
  );
};

// Renders our application
render(App);

// This checks if a component has been updated
// It then accepts the changes and replaced the module.
// It's only checking if JS has been changed...
// @TODO - it only works for JS not CSS.
// I think this is an issue with webpack not
// recognizing bundle.css as a dependency?
if (module.hot) {
  module.hot.accept();
}

【问题讨论】:

    标签: javascript reactjs webpack


    【解决方案1】:

    您正在使用extract-text-webpack-plugin,并且在 webpack 重建包之后,webpack-dev-middleware 认为没有任何改变,因为您的包中代表 CSS 的相应模块是空的,因为它的内容已被提取。

    您需要在开发中禁用 extract-text-webpack-plugin 才能获得 HMR。您可以使用disable option,它将回退到注入&lt;style&gt; 标签的style-loader

    new ExtractTextPlugin({
      filename: 'bundle.css',
      allChunks: true,
      disable: true
    })
    

    您可以使用诸如NODE_ENV=production 之类的环境变量并在插件中使用它,而不必定义插件的两个版本:

    new ExtractTextPlugin({
      filename: 'bundle.css',
      allChunks: true,
      disable: process.env.NODE_ENV !== 'production'
    })
    

    【讨论】:

    • 感谢您的明确回复和上下文。刚刚添加了禁用选项,就像一个魅力。干杯!
    • @Michael Jugo 你救了我的命
    猜你喜欢
    • 2015-11-17
    • 2016-08-13
    • 2019-02-02
    • 2016-09-17
    • 2017-08-07
    • 1970-01-01
    • 2017-01-05
    • 2020-12-18
    • 2021-03-10
    相关资源
    最近更新 更多