Prevent multi compiler from running twice at a time

This commit is contained in:
Maksim 2018-03-07 13:45:38 +03:00
parent e225d1005c
commit 9f60f50644
3 changed files with 136 additions and 5 deletions

View File

@ -53,6 +53,7 @@ module.exports = class MultiCompiler extends Tapable {
}
});
}
this.running = false;
}
get outputPath() {
@ -185,10 +186,24 @@ module.exports = class MultiCompiler extends Tapable {
}
watch(watchOptions, handler) {
if (this.running)
return handler(
new Error(
"You ran Webpack twice. Each instance only supports a single concurrent compilation at a time."
)
);
const finalHandler = (err, stats) => {
this.running = false;
if (handler !== undefined) handler(err, stats);
};
let watchings = [];
let allStats = this.compilers.map(() => null);
let compilerStatus = this.compilers.map(() => false);
if (this.validateDependencies(handler)) {
if (this.validateDependencies(finalHandler)) {
this.running = true;
this.runWithDependencies(
this.compilers,
(compiler, callback) => {
@ -199,7 +214,7 @@ module.exports = class MultiCompiler extends Tapable {
? watchOptions[compilerIdx]
: watchOptions,
(err, stats) => {
if (err) handler(err);
if (err) finalHandler(err);
if (stats) {
allStats[compilerIdx] = stats;
compilerStatus[compilerIdx] = "new";
@ -209,7 +224,7 @@ module.exports = class MultiCompiler extends Tapable {
});
compilerStatus.fill(true);
const multiStats = new MultiStats(freshStats);
handler(null, multiStats);
finalHandler(null, multiStats);
}
}
if (firstRun && !err) {
@ -230,8 +245,22 @@ module.exports = class MultiCompiler extends Tapable {
}
run(callback) {
if (this.running)
return callback(
new Error(
"You ran Webpack twice. Each instance only supports a single concurrent compilation at a time."
)
);
const finalCallback = (err, stats) => {
this.running = false;
if (callback !== undefined) return callback(err, stats);
};
const allStats = this.compilers.map(() => null);
if (this.validateDependencies(callback)) {
this.running = true;
this.runWithDependencies(
this.compilers,
(compiler, callback) => {
@ -243,8 +272,8 @@ module.exports = class MultiCompiler extends Tapable {
});
},
err => {
if (err) return callback(err);
callback(null, new MultiStats(allStats));
if (err) return finalCallback(err);
finalCallback(null, new MultiStats(allStats));
}
);
}

View File

@ -27,6 +27,7 @@ class MultiWatching {
err => {
this.compiler.hooks.watchClose.call();
if (typeof callback === "function") {
this.compiler.running = false;
callback(err);
}
}

View File

@ -52,4 +52,105 @@ describe("MultiCompiler", function() {
}
});
});
it("should not be run twice at a time (run)", function(done) {
const compiler = createMultiCompiler();
compiler.run((err, stats) => {
if (err) return done(err);
});
compiler.run((err, stats) => {
if (err) return done();
});
});
it("should not be run twice at a time (watch)", function(done) {
const compiler = createMultiCompiler();
compiler.watch({}, (err, stats) => {
if (err) return done(err);
});
compiler.watch({}, (err, stats) => {
if (err) return done();
});
});
it("should not be run twice at a time (run - watch)", function(done) {
const compiler = createMultiCompiler();
compiler.run((err, stats) => {
if (err) return done(err);
});
compiler.watch({}, (err, stats) => {
if (err) return done();
});
});
it("should not be run twice at a time (watch - run)", function(done) {
const compiler = createMultiCompiler();
compiler.watch({}, (err, stats) => {
if (err) return done(err);
});
compiler.run((err, stats) => {
if (err) return done();
});
});
it("should not be run twice at a time (instance cb)", function(done) {
const compiler = webpack(
{
context: __dirname,
mode: "production",
entry: "./c",
output: {
path: "/",
filename: "bundle.js"
}
},
() => {}
);
compiler.outputFileSystem = new MemoryFs();
compiler.run((err, stats) => {
if (err) return done();
});
});
it("should run again correctly after first compilation", function(done) {
const compiler = createMultiCompiler();
compiler.run((err, stats) => {
if (err) return done(err);
compiler.run((err, stats) => {
if (err) return done(err);
done();
});
});
});
it("should watch again correctly after first compilation", function(done) {
const compiler = createMultiCompiler();
compiler.run((err, stats) => {
if (err) return done(err);
compiler.watch({}, (err, stats) => {
if (err) return done(err);
done();
});
});
});
it("should run again correctly after first closed watch", function(done) {
const compiler = createMultiCompiler();
const watching = compiler.watch({}, (err, stats) => {
if (err) return done(err);
});
watching.close(() => {
compiler.run((err, stats) => {
if (err) return done(err);
done();
});
});
});
it("should watch again correctly after first closed watch", function(done) {
const compiler = createMultiCompiler();
const watching = compiler.watch({}, (err, stats) => {
if (err) return done(err);
});
watching.close(() => {
compiler.watch({}, (err, stats) => {
if (err) return done(err);
done();
});
});
});
});