web-dev-qa-db-fra.com

Exécuter la commande après la construction du webpack

Je souhaite exécuter Webpack en mode --watch et exécuter une commande Shell après chaque génération qui synchronise un dossier sur un autre.

J'ai trouvé ce plugin qui déclenche un événement après chaque construction. Cela fonctionne, mais la dernière pièce du puzzle consiste à déclencher une commande Shell (pour la synchronisation) à partir de Javascript. Tous les conseils sur la façon d'atteindre cet objectif sont grandement appréciés.

38
Monokai

Vous pouvez facilement exécuter n'importe quelle commande Shell avec le module child_process intégré. Vous pouvez aussi essayer certaines bibliothèques Shell pour node.js, comme Shell.js . Il enveloppe la plupart des Shell par défaut pour une utilisation plus pratique

5
just-boris

J'avais aussi besoin d'une telle chose, j'ai donc compilé un plugin extrêmement simple pour exécuter des commandes Shell avant et après chaque construction.

'use strict';

var exec = require('child_process').exec;

function puts(error, stdout, stderr) {
    console.log(stdout);
}

function WebpackShellPlugin(options) {
  var defaultOptions = {
    onBuildStart: [],
    onBuildEnd: []
  };

  this.options = Object.assign(defaultOptions, options);
}

WebpackShellPlugin.prototype.apply = function(compiler) {
  const options = this.options;

  compiler.plugin("compilation", compilation => {
    if(options.onBuildStart.length){
        console.log("Executing pre-build scripts");
        options.onBuildStart.forEach(script => exec(script, puts));
    }
  });

  compiler.plugin("emit", (compilation, callback) => {
    if(options.onBuildEnd.length){
        console.log("Executing post-build scripts");
        options.onBuildEnd.forEach(script => exec(script, puts));
    }
    callback();
  });
};

module.exports = WebpackShellPlugin;

puis dans votre config de webpack:

plugins: [
    new WebpackShellPlugin({ 
         onBuildStart: ['echo "hello world"'], 
         onBuildEnd: ['echo "goodbye world"'] 
    })
]

C'est super basique et ne supporte pas les scripts async correctement. mais ça marche. n'hésitez pas à modifier comme bon vous semble.

Considérez ce code sous la licence MIT.

Nécessite le noeud 4.x et supérieur à exécuter, car j’utilise certaines fonctionnalités de es6 ici. 

62
Yair Tavor

Webpack 4

À compter d'aujourd'hui (11 avril 2018), la plupart des plugins que j'ai essayés utilisent l'API obsolète, ce qui entraîne l'avertissement suivant:

DeprecationWarning: Tapable.plugin is deprecated. Use new API on `.hooks` instead

Je suis ravi de constater qu’un plugin ad-web Webpack semble d’une simplicité satisfaisante.

Dans votre fichier webpack.config.js:

const exec = require('child_process').exec;

module.exports = {

  // ... other config here ...

  plugins: [

    // ... other plugins here ...

    {
      apply: (compiler) => {
        compiler.hooks.afterEmit.tap('AfterEmitPlugin', (compilation) => {
          exec('<path to your post-build script here>', (err, stdout, stderr) => {
            if (stdout) process.stdout.write(stdout);
            if (stderr) process.stderr.write(stderr);
          });
        });
      }
    }
  ]
};

Si vous préférez utiliser spawn pour obtenir des données "en direct" en temps réel à partir de votre script, ceci illustre l'utilisation de base:

const child = spawn('<your script here>');
child.stdout.on('data', function (data) {
    process.stdout.write(data);
});
child.stderr.on('data', function (data) {
    process.stderr.write(data);
});
46
jchook

Utilisez webpack-Shell-plugin

Comment utiliser:

const WebpackShellPlugin = require('webpack-Shell-plugin');


    module.exports = {
      ...
      ...
      plugins: [
        new WebpackShellPlugin({onBuildStart:['echo "Webpack Start"'], onBuildEnd:['echo "Webpack End"']})
      ],
      ...
    }
3
Krishna

Si vous voulez le faire quand un fichier spécifique est changé, vous pouvez utiliser ce petit plugin que j'ai construit: https://www.npmjs.com/package/webpack-noodle-plugin

J'espère que ça peut aider

1
Pistolpete .

Fondamentalement, vous pouvez vous connecter au compilateur à différentes étapes de la compilation pour émettre des ressources, etc., et exécuter votre propre script ou code à votre guise. 

J'aime le faire de cette façon - 

class CustomPlugin {
  constructor(name, command, stage = 'afterEmit') {
    this.name = name;
    this.command = command;
    this.stage = stage;
  }

  static execHandler(err, stdout, stderr) {
    if (stdout) process.stdout.write(stdout);
    if (stderr) process.stderr.write(stderr);
  }

  apply(compiler) {
    compiler.hooks[this.stage].tap(this.name, () => {
      exec(this.command, CustomPlugin.execHandler);
    });
  }
}

et ensuite l'utiliser comme si 

new CustomPlugin('RunTest', 'jest', 'beforeRun'),
0
Sohail