From da92cd0af67ae2742c07c539f635fb2a656c07e6 Mon Sep 17 00:00:00 2001 From: cainrus Date: Fri, 9 Feb 2018 15:26:25 +0200 Subject: [PATCH 1/2] Callback for every webpack build in watch mode --- README.md | 24 ++++++++++++++++++++++++ index.js | 11 +++++++---- src/watchDoneHandler.js | 6 ++++-- src/watchModeIPC.js | 29 ++++++++++++++++++++++++++--- src/webpackWorker.js | 11 ++++++++--- 5 files changed, 69 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index c7d051e..fa141b7 100644 --- a/README.md +++ b/README.md @@ -238,6 +238,30 @@ function notify() { run(configPath, options, notify); ``` + +You can pass a notify callback for every webpack watch callback as well. +```javascript +var run = require('parallel-webpack').run, + configPath = require.resolve('./webpack.config.js'), + options = {/*...*/}; + +let qeueu = []; +run(configPath, options, () => { + console.log('[webpack-parallel] every configuration has been compiled. I will not be invoked anymore'); +}, (list, i) => { + if (qeueu.length === 0) { + qeueu = list.map(Number); + } + console.log(`[webpack-parallel] configuration #${i} is compiled in watch mode.`); + if (qeueu.includes(i)) { + qeueu.splice(qeueu.indexOf(i), 1); + if (qeueu.length === 0) { + console.log(`[webpack-parallel] all configurations(${list.join(',')}) were compiled in watch mode.`); + } + } +}); +``` + **NOTE:** In watch mode notify callback provided with Node.js API will run **only once** when all of the builds are finished. diff --git a/index.js b/index.js index c0c5ddf..a2ab713 100644 --- a/index.js +++ b/index.js @@ -20,14 +20,14 @@ function notSilent(options) { return !options.json; } -function startFarm(config, configPath, options, runWorker, callback) { +function startFarm(config, configPath, options, runWorker, doneCallback, watchCallback) { config = Array.isArray(config) ? config : [config]; options = options || {}; // When in watch mode and a callback is provided start IPC server to invoke callback // once all webpack configurations have been compiled if (options.watch) { - startWatchIPCServer(callback, Object.keys(config)); + startWatchIPCServer(doneCallback, watchCallback, Object.keys(config)); } if(notSilent(options)) { @@ -69,14 +69,16 @@ function startFarm(config, configPath, options, runWorker, callback) { * on build error * @param {Function} [callback] A callback to be invoked once the build has * been completed + * @param {Function} [watchCallback] A callback to be invoked on each configuration build complete in watch mode. * @return {Promise} A Promise that is resolved once all builds have been * created */ -function run(configPath, options, callback) { +function run(configPath, options, callback, watchCallback) { var config, argvBackup = process.argv, farmOptions = assign({}, options); options = options || {}; + if(options.colors === undefined) { options.colors = chalk.supportsColor; } @@ -122,7 +124,8 @@ function run(configPath, options, callback) { configPath, options, Promise.promisify(workers), - callback + callback, + watchCallback ).error(function(err) { if(notSilent(options)) { console.log('%s Build failed after %s seconds', chalk.red('[WEBPACK]'), chalk.blue((Date.now() - startTime) / 1000)); diff --git a/src/watchDoneHandler.js b/src/watchDoneHandler.js index c4bc43e..f79c0b8 100644 --- a/src/watchDoneHandler.js +++ b/src/watchDoneHandler.js @@ -2,11 +2,13 @@ * Handler for done event * @param data - the configuration index of the completed webpack run */ -module.exports = function watchDoneHandler(callback, ipc, configIndices, data) { +module.exports = function watchDoneHandler(callback, ipc, configIndices, dontStop, data) { // Once every configuration has completed once, stop the server and invoke the callback configIndices.splice(configIndices.indexOf(data), 1); if (!configIndices.length) { - ipc.server.stop(); + if (!dontStop) { + ipc.server.stop(); + } if (typeof callback === 'function') { callback(); diff --git a/src/watchModeIPC.js b/src/watchModeIPC.js index eb062d6..1cf80d0 100644 --- a/src/watchModeIPC.js +++ b/src/watchModeIPC.js @@ -7,21 +7,31 @@ module.exports = { /** * Start IPC server and listens for 'done' message from child processes * @param {any} callback - callback invoked once 'done' has been emitted by each confugration + * @param {Function} watchCallback - callback invoked on every webpack compile in watch mode * @param {any} configIndices - array indices of configuration */ - startWatchIPCServer: function startWatchIPCServer(callback, configIndices) { + startWatchIPCServer: function startWatchIPCServer(callback, watchCallback, configIndices) { ipc.config.id = serverName; ipc.config.retry = 3; ipc.config.silent = true; + var dontStopServer = !!watchCallback; + ipc.serve( function() { ipc.server.on( 'done', - watchDoneHandler.bind(this, callback, ipc, configIndices) + watchDoneHandler.bind(this, callback, ipc, configIndices, dontStopServer) ); + if (watchCallback) { + ipc.server.on( + 'watchCallback', + watchCallback.bind(null, [].concat(configIndices)) + ) + } } ); + ipc.server.start(); }, @@ -40,5 +50,18 @@ module.exports = { ipc.of.webpack.emit('done', index); } ); - } + }, + + notifyIPCWatchCallback: function notifyIPCWatchCallback(index) { + ipc.config.id = serverName + index; + ipc.config.stopRetrying = 3; + ipc.config.silent = true; + + ipc.connectTo( + serverName, + function() { + ipc.of.webpack.emit('watchCallback', index); + } + ); + }, } diff --git a/src/webpackWorker.js b/src/webpackWorker.js index 8aa0080..3398397 100644 --- a/src/webpackWorker.js +++ b/src/webpackWorker.js @@ -2,6 +2,7 @@ var Promise = require('bluebird'), chalk = require('chalk'), loadConfigurationFile = require('./loadConfigurationFile').default, notifyIPCWatchCompileDone = require('./watchModeIPC').notifyIPCWatchCompileDone, + notifyIPCWatchCallback = require('./watchModeIPC').notifyIPCWatchCallback, presetToOptions = require('webpack/lib/Stats').presetToOptions; /** * Choose the most correct version of webpack, prefer locally installed version, @@ -135,10 +136,14 @@ module.exports = function(configuratorFileName, options, index, expectedConfigLe if(!watch) { process.removeListener('SIGINT', shutdownCallback); done(null, options.stats ? JSON.stringify(stats.toJson(outputOptions), null, 2) : ''); - } else if (!hasCompletedOneCompile) { - notifyIPCWatchCompileDone(index); - hasCompletedOneCompile = true; + } else { + notifyIPCWatchCallback(index); + if (!hasCompletedOneCompile) { + notifyIPCWatchCompileDone(index); + hasCompletedOneCompile = true; + } } + }; if(!silent) { console.log('%s Started %s %s', chalk.blue('[WEBPACK]'), watch ? 'watching' : 'building', chalk.yellow(getAppName(webpackConfig))); From 4106ea2d1acb35730205204cd06a018977ddbe87 Mon Sep 17 00:00:00 2001 From: cainrus Date: Fri, 9 Feb 2018 16:23:31 +0200 Subject: [PATCH 2/2] Fix tests --- src/__tests__/watchDoneHandler.spec.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/__tests__/watchDoneHandler.spec.js b/src/__tests__/watchDoneHandler.spec.js index 309b438..f5fdfa4 100644 --- a/src/__tests__/watchDoneHandler.spec.js +++ b/src/__tests__/watchDoneHandler.spec.js @@ -22,8 +22,9 @@ describe('watchDoneHandler', () => { it('should stop server and invoke callback', () => { let configIndices = [0, 1]; let callback = jest.fn(); - watchDoneHandler(callback, ipc, configIndices, 0); - watchDoneHandler(callback, ipc, configIndices, 1); + let dontStop = false; + watchDoneHandler(callback, ipc, configIndices, dontStop, 0); + watchDoneHandler(callback, ipc, configIndices, dontStop, 1); expect(configIndices).toEqual([]); expect(callback).toHaveBeenCalled(); expect(ipc.server.stop).toHaveBeenCalled(); @@ -32,8 +33,9 @@ describe('watchDoneHandler', () => { it('should stop server', () => { let configIndices = [0, 1]; let callback = jest.fn(); - watchDoneHandler(null, ipc, configIndices, 0); - watchDoneHandler(null, ipc, configIndices, 1); + let dontStop = false; + watchDoneHandler(null, ipc, configIndices, dontStop, 0); + watchDoneHandler(null, ipc, configIndices, dontStop, 1); expect(configIndices).toEqual([]); expect(ipc.server.stop).toHaveBeenCalled(); });