运行 webpack 构建后的命令

Run command after webpack build

我想在 --watch 模式下 运行 webpack,并且 运行 在每次构建后将一个文件夹同步到另一个文件夹的 shell 命令。

我发现 this plugin 在每次构建后都会触发一个事件。这行得通,但最后一个难题是从 Javascript 触发 shell 命令(用于同步)。非常感谢有关如何实现这一目标的任何指示。

您可以轻松地 运行 任何带有内置 child_process module. Also you can try some shell libraries for node.js, like Shell.js 的 shell 命令。它包装了大部分默认 shell 以便更方便地使用

我也需要这样的东西,所以我编译了一个超级简单的插件,在每次构建前后执行shell命令。

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

然后在你的 webpack 配置中:

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

这是超级基础的,不能正确支持异步脚本。但它有效。随意修改您认为合适的方式。

Consider this code under MIT licence.

Needs node 4.x and up to run, as I use some es6 features here.

如果你们想在更改特定文件时执行此操作,可以使用我构建的这个小插件:https://www.npmjs.com/package/webpack-noodle-plugin

希望能帮到你

Webpack 4

截至今天(2018 年 4 月 11 日),我尝试过的大多数插件都使用已弃用的 API 导致此警告:

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

很高兴发现您可以轻松编写 ad-hoc webpack 插件 (docs)。

在您的 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);
          });
        });
      }
    }
  ]
};

如果您更愿意使用 spawn 从脚本中获取 real-time 或 "live" 数据,这说明了基本用法:

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

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

使用webpack-shell-plugin

使用方法:

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


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

基本上,您可以在整个编译的各个阶段挂接到编译器,以发出资源阶段等,并 运行 您自己的脚本或代码。

我喜欢这样做 -

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

然后像这样使用它

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

webpack-shell-plugin-next 插件

webpack-shell-plugin-next插件:

使用插件

onAfterDone plugin API:

onAfterDone: configuration object for scripts that execute after done.

可用于实现所需的 watch-related 行为(此外,请参阅下面的 重要说明):

I'd like to run webpack in --watch mode, and run a shell command after each build that synchronizes a folder to another one.

重要说明onAfterDone 插件 API 也适用于(影响)正常构建模式(即没有 --watch 选项的 webpack 命令)。

这里是对相关 GitHub 问题的额外参考:onDoneWatch scripts executing before bundle written · Issue #16 · s00d/webpack-shell-plugin-next

例子

刚刚尝试使用该插件:它运行良好。

devDependencies(来自package.json

"devDependencies": {
  "webpack": "5.3.2",
  "webpack-cli": "4.1.0",
  "webpack-shell-plugin-next": "2.0.4"
}

watch npm 运行 脚本(来自 package.json

"scripts": {
  "watch": "webpack --config webpack.config.js --watch"
}

Webpack 配置文件(webpack.config.js)

const WebpackShellPluginNext = require('webpack-shell-plugin-next');

module.exports = {
    plugins: [
        new WebpackShellPluginNext({
            onAfterDone: {
                scripts: ['echo "It works!"'],
                blocking: true,
                parallel: false
            }
        })
    ]
};

观察模式下 运行 Webpack 的命令行

npm run watch

我在使用 webpack-shell-pluginwebpack-shell-plugin-next 时遇到了一些问题:即使我使用 onDoneWatch.

那是我发现 hook-shell-script-webpack-plugin 的时候。 就像一个魅力。