web-dev-qa-db-fra.com

remplacement de module Webpack chaud: css sans actualisation

Jusqu'ici, j'ai utilisé livereload pour que chaque fois que je change de JS ou de modèles, la page soit actualisée et lorsque je change de CSS, le nouveau CSS soit échangé sans actualisation.

J'essaie Webpack maintenant et j'ai presque le même comportement, à une exception près: lorsque le CSS change, la fenêtre entière est rafraîchie. Est-il possible de faire du hotswap en CSS sans rafraîchissement?

Config jusqu'ici:

var webpackConfig = {
    entry: ["webpack/hot/dev-server", __dirname + '/app/scripts/app.js'],
    debug: true,
    output: {
        path: __dirname + '/app',
        filename: 'scripts/build.js'
    },
    devtool: 'source-map',
    plugins: [
        new webpack.HotModuleReplacementPlugin(),
        new htmlWebpackPlugin({
            template: __dirname + '/app/index.html',
            inject: 'body',
            hash: true,
            config: config
        }),
        new webpack.ProvidePlugin({
            'angular': 'angular'
        }),
        new ExtractTextPlugin("styles.css")
    ],
    module: {
        loaders: [
            {
                test: /\.scss$/,
                loader: "style!css!sass?includePaths[]=" + __dirname + "/app/bower_components/compass-mixins/lib&includePaths[]=" + __dirname + '/instance/sth/styles&includePaths[]=' + __dirname + '/app/scripts'
            }
        ]
    }
};
17
Bart van den Burg

C’est l’un des inconvénients de l’utilisation de ExtractTextPlugin comme indiqué dans le projet README . Vous pouvez résoudre le problème en fractionnant votre configuration. C'est à dire. ont une configuration séparée pour le développement sans et une pour la production avec.

17
Juho Vepsäläinen

Il est maintenant possible d’utiliser angular2, un pack Web avec remplacement de module à chaud, des cartes source sass et des fichiers CSS chargés de manière externe. Cela m'a pris des jours de jouer avec ça, mais ça a marché!

Les dépendances sont style-loader, css-loader et sass-loader (si vous utilisez sass, sinon, le chargeur sass peut être supprimé).

J'utilise ExtractTextPlugin pour le mode de production pour émettre des fichiers .css réels.

REMARQUE: pour que cela fonctionne, je n'utilise pas la propriété stylesUrl, mais j'importe le fichier .scss en dehors du décorateur @Component afin que les styles soient chargés dans un contexte global plutôt que définis par composant.

Cette configuration permet le remplacement de Hot Module par des fichiers SCSS à l'aide du serveur Webpack dev, et une extraction de texte pour le mode de production afin d'émettre des fichiers .css réels.

Voici ma config de travail

{
        test: /\.(scss)$/,
        use:
          isDevServer ? [
              {
                loader: 'style-loader',
              },             
              {
                loader: 'css-loader',
                options: { sourceMap: true }
              },
              {
                loader: 'postcss-loader',
                options: { postcss: [AutoPrefixer(autoPrefixerOptions)], sourceMap: true }
              },
              {
                loader: 'sass-loader',
                options: { sourceMap: true }
              },
              {
                loader: 'sass-resources-loader',
                options: {
                  resources: [
                    './src/assets/styles/variables.scss',
                    './src/assets/styles/mixins.scss']
                }
              }, 
              /**
               * The sass-vars-loader will convert the 'vars' property or any module.exports of 
               * a .JS or .JSON file into valid SASS and append to the beginning of each 
               * .scss file loaded.
               *
               * See: https://github.com/epegzz/sass-vars-loader
               */
              {
                loader: '@epegzz/sass-vars-loader?',
                options: querystring.stringify({
                  vars: JSON.stringify({
                    susyIsDevServer: susyIsDevServer
                  })
                })
              }] : // dev mode
          ExtractTextPlugin.extract({
            fallback: "css-loader",
            use: [
              {
                loader: 'css-loader',
                options: { sourceMap: true }
              },
              {
                loader: 'postcss-loader',
                options: { postcss: [AutoPrefixer(autoPrefixerOptions)], sourceMap: true }
              },
              {
                loader: 'sass-loader',
                options: { sourceMap: true }
              },
              {
                loader: 'sass-resources-loader',
                options: {
                  resources: [
                    './src/assets/styles/variables.scss',
                    './src/assets/styles/mixins.scss']
                }
              }, {
                loader: '@epegzz/sass-vars-loader?',
                options: querystring.stringify({
                  vars: JSON.stringify({
                    susyIsDevServer: susyIsDevServer
                  })
                  // // Or use 'files" object to specify vars in an external .js or .json file
                  // files: [
                  //    path.resolve(helpers.paths.appRoot + '/assets/styles/sass-js-variables.js')
                  // ],
                })
              }],
            publicPath: '/' // 'string' override the publicPath setting for this loader
          })
      },

Ensuite, dans votre composant, par exemple, app.component.ts, vous auriez besoin de votre fichier app.style.scss OUTSIDE du décorateur @Component .

C'est le truc. Cela ne fonctionnera pas si vous chargez les styles de la "manière angulaire" avec stylesUrl. En procédant ainsi, vous pourrez charger paresseux les feuilles de style .css pour les composants chargés paresseux, ce qui accélérera encore le temps de chargement initial.

app.component.css

/*
 * THIS IS WHERE WE REQUIRE CSS/SCSS FILES THAT THIS COMPONENT NEEDS
 *
 * Function: To enable so-called "Lazy Loading" CSS/SCSS files "on demand" as the app views need them.
 * Do NOT add styles the "Angular2 Way" in the @Component decorator ("styles" and "styleUrls" properties)
 */
    import './app.style.scss'

/**
 * AppComponent Component
 * Top Level Component
 */
@Component({
   selector: 'body',
   encapsulation: ViewEncapsulation.None,
   Host: { '[class.authenticated]': 'appState.state.isAuthenticated' },
   templateUrl: './app.template.html'
})

Je n'ai eu aucun problème à exécuter cette configuration. Voici!

sass_sourcemaps _hmr _wds

Mise à jour 08/2017: Configuration améliorée pour les exigences du schéma webpack 3+ et pour travailler avec la compilation Angular 4 AOT.

4
TetraDev

Il existe en fait un moyen simple de le faire. J'utilise sass-loader avec extract-text-plugin qui produit des fichiers CSS.

Ce que vous devez faire, c'est ajouter un identifiant à votre css include

  <link id="js-style" type="text/css" rel="stylesheet" href="/static/main.css">

Maintenant, vous devez vous assurer que lorsque HMR se produit, vous mettez à jour l'URL avec la version/l'horodatage actuel. Vous pouvez le faire de la manière suivante:

import '../style/main.scss'
if (module.hot) {
  module.hot.accept('../style/main.scss', () => {
    const baseStyle = window.document.getElementById('js-style')
    baseStyle.setAttribute('href', '/static/main.css?v=' + new Date().valueOf)
  })
}

Donc, chaque fois que css change, nous allons corriger l’url de css include pour le recharger.

2
Hatch

Bien que ExtractTextPlugin indique "Pas de remplacement de module actif" dans sa section README , j'ai résolu ce problème en mettant à jour manuellement les fichiers CSS via l'API BrowserSync.

J'ai utilisé regard pour écouter les modifications apportées à mes fichiers CSS, puis j'ai utilisé BrowserSync pour les mettre à jour.

    npm install gaze

Vous pouvez également le faire facilement en modifiant votre script de construction avec l’une des caractéristiques suivantes:

  const { Gaze } = require('gaze');

  // Your own BrowserSync init
  browserSync.init({
    ...
  }, resolve);

  // Create a watcher:
  // You can watch/reload specific files according to your build/project structure
  const gaze = new Gaze('**/*.css');
  gaze.on('all', () => bs.reload('*.css'));

J'espère que cela pourra aider.

1
urip

Vous pouvez utiliser 'css-hot-loader' pour activer HMR pour votre css extrait . Il fonctionne parfaitement pour moi.

0
ddemakov