Domanda Come ricaricare Hot Sass usando Webpack 2?


Sto lavorando alla creazione di un'applicazione React che utilizza Webpack2, webpack-dev-middleware e HMR per lo sviluppo. Ogni volta che apporto una modifica a un componente React, esso si aggiorna nel browser come previsto. Il problema che sto incontrando è che quando modifico i miei file .scss, fa il browser non aggiornare. Quello che succede invece è che nella console mi dà il seguente:

[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.

Dopodiché, quando aggiorno la pagina, vengono visualizzate le modifiche al mio stile. Non sono del tutto sicuro di cosa sta succedendo o da dove il problema deriva ma vorrei aiuto e chiarimenti.

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 che utilizza 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 sul lato client

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

11
2018-04-07 20:56


origine


risposte:


Stai usando extract-text-webpack-plugin e dopo che il webpack ricostruisce il pacchetto webpack-dev-middleware pensa che nulla sia cambiato, perché il modulo corrispondente nel tuo bundle che rappresenta il CSS è vuoto poiché il suo contenuto è stato estratto.

Devi disabilitare extract-text-webpack-plugin in fase di sviluppo per ottenere HMR. Puoi usare il disable opzione e riporterà al style-loader, che inietta il <style> tag.

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

Invece di dover definire due versioni del plugin è possibile utilizzare variabili d'ambiente come NODE_ENV=production e usarlo nel plugin:

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

21
2018-04-07 21:08