Merge pull request #11252 from webpack/improve/cache-and-progress
do cache related tasks after calling handler in watching
This commit is contained in:
commit
fdfaa2efa0
|
@ -1996,15 +1996,7 @@ Or do you want to use the entrypoints '${name}' and '${runtime}' independently o
|
|||
this.unseal();
|
||||
return this.seal(callback);
|
||||
}
|
||||
this.compiler.cache.storeBuildDependencies(
|
||||
this.buildDependencies,
|
||||
err => {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
return this.hooks.afterSeal.callAsync(callback);
|
||||
}
|
||||
);
|
||||
return this.hooks.afterSeal.callAsync(callback);
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
@ -226,6 +226,9 @@ class Compiler {
|
|||
/** @type {boolean} */
|
||||
this.running = false;
|
||||
|
||||
/** @type {boolean} */
|
||||
this.idle = false;
|
||||
|
||||
/** @type {boolean} */
|
||||
this.watchMode = false;
|
||||
|
||||
|
@ -353,7 +356,9 @@ class Compiler {
|
|||
|
||||
const finalCallback = (err, stats) => {
|
||||
if (logger) logger.time("beginIdle");
|
||||
this.idle = true;
|
||||
this.cache.beginIdle();
|
||||
this.idle = true;
|
||||
if (logger) logger.timeEnd("beginIdle");
|
||||
this.running = false;
|
||||
if (err) {
|
||||
|
@ -419,16 +424,20 @@ class Compiler {
|
|||
this.hooks.done.callAsync(stats, err => {
|
||||
logger.timeEnd("done hook");
|
||||
if (err) return finalCallback(err);
|
||||
return finalCallback(null, stats);
|
||||
this.cache.storeBuildDependencies(
|
||||
compilation.buildDependencies,
|
||||
err => {
|
||||
if (err) return finalCallback(err);
|
||||
return finalCallback(null, stats);
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
this.cache.endIdle(err => {
|
||||
if (err) return finalCallback(err);
|
||||
|
||||
const run = () => {
|
||||
this.hooks.beforeRun.callAsync(this, err => {
|
||||
if (err) return finalCallback(err);
|
||||
|
||||
|
@ -442,7 +451,18 @@ class Compiler {
|
|||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
if (this.idle) {
|
||||
this.cache.endIdle(err => {
|
||||
if (err) return finalCallback(err);
|
||||
|
||||
this.idle = false;
|
||||
run();
|
||||
});
|
||||
} else {
|
||||
run();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -27,9 +27,17 @@ class MultiWatching {
|
|||
this.compiler = compiler;
|
||||
}
|
||||
|
||||
invalidate() {
|
||||
for (const watching of this.watchings) {
|
||||
watching.invalidate();
|
||||
invalidate(callback) {
|
||||
if (callback) {
|
||||
asyncLib.each(
|
||||
this.watchings,
|
||||
(watching, callback) => watching.invalidate(callback),
|
||||
callback
|
||||
);
|
||||
} else {
|
||||
for (const watching of this.watchings) {
|
||||
watching.invalidate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -61,6 +61,7 @@ const makeSerializable = require("./util/makeSerializable");
|
|||
* @property {string} loader
|
||||
* @property {any} options
|
||||
* @property {string?} ident
|
||||
* @property {string?} type
|
||||
*/
|
||||
|
||||
/**
|
||||
|
@ -148,6 +149,7 @@ makeSerializable(
|
|||
/**
|
||||
* @typedef {Object} NormalModuleCompilationHooks
|
||||
* @property {SyncHook<[object, NormalModule]>} loader
|
||||
* @property {SyncHook<[LoaderItem[], object, NormalModule]>} beforeLoaders
|
||||
* @property {HookMap<AsyncSeriesBailHook<[string, NormalModule], string | Buffer>>} readResourceForScheme
|
||||
*/
|
||||
|
||||
|
@ -169,6 +171,7 @@ class NormalModule extends Module {
|
|||
if (hooks === undefined) {
|
||||
hooks = {
|
||||
loader: new SyncHook(["loaderContext", "module"]),
|
||||
beforeLoaders: new SyncHook(["loaders", "module", "loaderContext"]),
|
||||
readResourceForScheme: new HookMap(
|
||||
() => new AsyncSeriesBailHook(["resource", "module"])
|
||||
)
|
||||
|
@ -607,6 +610,9 @@ class NormalModule extends Module {
|
|||
return callback();
|
||||
};
|
||||
|
||||
const hooks = NormalModule.getCompilationHooks(compilation);
|
||||
|
||||
hooks.beforeLoaders.call(this.loaders, this, loaderContext);
|
||||
runLoaders(
|
||||
{
|
||||
resource: this.resource,
|
||||
|
@ -615,8 +621,8 @@ class NormalModule extends Module {
|
|||
readResource: (resource, callback) => {
|
||||
const scheme = getScheme(resource);
|
||||
if (scheme) {
|
||||
NormalModule.getCompilationHooks(compilation)
|
||||
.readResourceForScheme.for(scheme)
|
||||
hooks.readResourceForScheme
|
||||
.for(scheme)
|
||||
.callAsync(resource, this, (err, result) => {
|
||||
if (err) return callback(err);
|
||||
if (typeof result !== "string" && !result) {
|
||||
|
|
|
@ -9,6 +9,8 @@ const validateOptions = require("schema-utils");
|
|||
const schema = require("../schemas/plugins/ProgressPlugin.json");
|
||||
const Compiler = require("./Compiler");
|
||||
const MultiCompiler = require("./MultiCompiler");
|
||||
const NormalModule = require("./NormalModule");
|
||||
const { contextify } = require("./util/identifier");
|
||||
|
||||
/** @typedef {import("../declarations/plugins/ProgressPlugin").HandlerFunction} HandlerFunction */
|
||||
/** @typedef {import("../declarations/plugins/ProgressPlugin").ProgressPluginArgument} ProgressPluginArgument */
|
||||
|
@ -19,7 +21,7 @@ const median3 = (a, b, c) => {
|
|||
};
|
||||
|
||||
const createDefaultHandler = (profile, logger) => {
|
||||
/** @type {{ value: string, time: number, alreadyReported: number }[]} */
|
||||
/** @type {{ value: string, time: number }[]} */
|
||||
const lastStateInfo = [];
|
||||
|
||||
const defaultHandler = (percentage, msg, ...args) => {
|
||||
|
@ -28,62 +30,57 @@ const createDefaultHandler = (profile, logger) => {
|
|||
lastStateInfo.length = 0;
|
||||
}
|
||||
const fullState = [msg, ...args];
|
||||
const state = fullState.map((_, i) =>
|
||||
fullState.slice(0, i + 1).join(" ")
|
||||
);
|
||||
const state = fullState.map(s => s.replace(/\d+\/\d+ /g, ""));
|
||||
const now = Date.now();
|
||||
const len = Math.max(state.length, lastStateInfo.length);
|
||||
for (let i = 0; i < len; i++) {
|
||||
for (let i = len; i >= 0; i--) {
|
||||
const stateItem = i < state.length ? state[i] : undefined;
|
||||
const lastStateItem =
|
||||
i < lastStateInfo.length ? lastStateInfo[i] : undefined;
|
||||
if (lastStateItem) {
|
||||
if (stateItem !== lastStateItem.value) {
|
||||
const alreadyReported = lastStateItem.alreadyReported;
|
||||
const diff = now - lastStateItem.time;
|
||||
const stateMsg = alreadyReported
|
||||
? `${diff} ms (-${alreadyReported} ms) ${lastStateItem.value}`
|
||||
: `${diff} ms ${lastStateItem.value}`;
|
||||
const d = diff - alreadyReported;
|
||||
// This depends on timing so we ignore it for coverage
|
||||
/* istanbul ignore next */
|
||||
{
|
||||
if (d > 10000) {
|
||||
logger.error(stateMsg);
|
||||
} else if (d > 1000) {
|
||||
logger.warn(stateMsg);
|
||||
} else if (d > 10) {
|
||||
logger.info(stateMsg);
|
||||
} else if (d > 5) {
|
||||
logger.log(stateMsg);
|
||||
} else {
|
||||
logger.debug(stateMsg);
|
||||
if (lastStateItem.value) {
|
||||
let reportState = lastStateItem.value;
|
||||
if (i > 0) {
|
||||
reportState = lastStateInfo[i - 1].value + " > " + reportState;
|
||||
}
|
||||
const stateMsg = `${" | ".repeat(i)}${diff} ms ${reportState}`;
|
||||
const d = diff;
|
||||
// This depends on timing so we ignore it for coverage
|
||||
/* istanbul ignore next */
|
||||
{
|
||||
if (d > 10000) {
|
||||
logger.error(stateMsg);
|
||||
} else if (d > 1000) {
|
||||
logger.warn(stateMsg);
|
||||
} else if (d > 10) {
|
||||
logger.info(stateMsg);
|
||||
} else if (d > 5) {
|
||||
logger.log(stateMsg);
|
||||
} else {
|
||||
logger.debug(stateMsg);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (stateItem === undefined) {
|
||||
lastStateInfo[i] = undefined;
|
||||
lastStateInfo.length = i;
|
||||
} else {
|
||||
lastStateItem.value = stateItem;
|
||||
lastStateItem.time = now;
|
||||
lastStateItem.alreadyReported = 0;
|
||||
lastStateInfo.length = i + 1;
|
||||
}
|
||||
lastStateInfo.length = i + 1;
|
||||
for (let j = 0; j < i; j++) {
|
||||
lastStateInfo[j].alreadyReported += diff;
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
lastStateInfo[i] = {
|
||||
value: stateItem,
|
||||
time: now,
|
||||
alreadyReported: 0
|
||||
time: now
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
logger.status(`${Math.floor(percentage * 100)}%`, msg, ...args);
|
||||
if (percentage === 1) logger.status();
|
||||
if (percentage === 1 || (!msg && args.length === 0)) logger.status();
|
||||
};
|
||||
|
||||
return defaultHandler;
|
||||
|
@ -184,6 +181,7 @@ class ProgressPlugin {
|
|||
const showDependencies = this.showDependencies;
|
||||
const showActiveModules = this.showActiveModules;
|
||||
let lastActiveModule = "";
|
||||
let currentLoader = "";
|
||||
let lastModulesCount = this.modulesCount;
|
||||
let lastDependenciesCount = this.dependenciesCount;
|
||||
let lastEntriesCount = 0;
|
||||
|
@ -231,18 +229,36 @@ class ProgressPlugin {
|
|||
|
||||
const percentage = 0.1 + percentageFactor * 0.55;
|
||||
|
||||
if (showEntries) {
|
||||
items.push(`${doneEntries}/${entriesCount} entries`);
|
||||
}
|
||||
if (showDependencies) {
|
||||
items.push(`${doneDependencies}/${dependenciesCount} dependencies`);
|
||||
}
|
||||
if (showModules) {
|
||||
items.push(`${doneModules}/${modulesCount} modules`);
|
||||
}
|
||||
if (showActiveModules) {
|
||||
items.push(`${activeModules.size} active`);
|
||||
items.push(lastActiveModule);
|
||||
if (currentLoader) {
|
||||
items.push(
|
||||
`import loader ${contextify(
|
||||
compiler.context,
|
||||
currentLoader,
|
||||
compiler.root
|
||||
)}`
|
||||
);
|
||||
} else {
|
||||
const statItems = [];
|
||||
if (showEntries) {
|
||||
statItems.push(`${doneEntries}/${entriesCount} entries`);
|
||||
}
|
||||
if (showDependencies) {
|
||||
statItems.push(
|
||||
`${doneDependencies}/${dependenciesCount} dependencies`
|
||||
);
|
||||
}
|
||||
if (showModules) {
|
||||
statItems.push(`${doneModules}/${modulesCount} modules`);
|
||||
}
|
||||
if (showActiveModules) {
|
||||
statItems.push(`${activeModules.size} active`);
|
||||
}
|
||||
if (statItems.length > 0) {
|
||||
items.push(statItems.join(" "));
|
||||
}
|
||||
if (showActiveModules) {
|
||||
items.push(lastActiveModule);
|
||||
}
|
||||
}
|
||||
handler(percentage, "building", ...items);
|
||||
lastUpdate = Date.now();
|
||||
|
@ -310,6 +326,7 @@ class ProgressPlugin {
|
|||
compiler.hooks.beforeCompile.tapAsync(
|
||||
"ProgressPlugin",
|
||||
(params, callback) => {
|
||||
handler(0.06, "setup", "waiting for cache");
|
||||
cache.get((err, data) => {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
|
@ -362,9 +379,35 @@ class ProgressPlugin {
|
|||
compilation.hooks.failedEntry.tap("ProgressPlugin", entryDone);
|
||||
compilation.hooks.succeedEntry.tap("ProgressPlugin", entryDone);
|
||||
|
||||
// avoid dynamic require if bundled with webpack
|
||||
// @ts-expect-error
|
||||
if (typeof __webpack_require__ !== "function") {
|
||||
const requiredLoaders = new Set();
|
||||
NormalModule.getCompilationHooks(compilation).beforeLoaders.tap(
|
||||
"ProgressPlugin",
|
||||
loaders => {
|
||||
for (const loader of loaders) {
|
||||
if (
|
||||
loader.type !== "module" &&
|
||||
!requiredLoaders.has(loader.loader)
|
||||
) {
|
||||
requiredLoaders.add(loader.loader);
|
||||
currentLoader = loader.loader;
|
||||
update();
|
||||
require(loader.loader);
|
||||
}
|
||||
}
|
||||
if (currentLoader) {
|
||||
currentLoader = "";
|
||||
update();
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
const hooks = {
|
||||
finishModules: "finish module graph",
|
||||
seal: "sealing",
|
||||
seal: "plugins",
|
||||
optimizeDependencies: "dependencies optimization",
|
||||
afterOptimizeDependencies: "after dependencies optimization",
|
||||
beforeChunks: "chunk graph",
|
||||
|
@ -410,24 +453,24 @@ class ProgressPlugin {
|
|||
compilation.hooks[name].intercept({
|
||||
name: "ProgressPlugin",
|
||||
call() {
|
||||
handler(percentage, title);
|
||||
handler(percentage, "sealing", title);
|
||||
},
|
||||
done() {
|
||||
handler(percentage, title);
|
||||
handler(percentage, "sealing", title);
|
||||
},
|
||||
result() {
|
||||
handler(percentage, title);
|
||||
handler(percentage, "sealing", title);
|
||||
},
|
||||
error() {
|
||||
handler(percentage, title);
|
||||
handler(percentage, "sealing", title);
|
||||
},
|
||||
tap(tap) {
|
||||
// p is percentage from 0 to 1
|
||||
// args is any number of messages in a hierarchical matter
|
||||
progressReporters.set(compilation.compiler, (p, ...args) => {
|
||||
handler(percentage, title, tap.name, ...args);
|
||||
handler(percentage, "sealing", title, tap.name, ...args);
|
||||
});
|
||||
handler(percentage, title, tap.name);
|
||||
handler(percentage, "sealing", title, tap.name);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
@ -441,53 +484,98 @@ class ProgressPlugin {
|
|||
handler(0.65, "building");
|
||||
}
|
||||
});
|
||||
const interceptHook = (hook, progress, name) => {
|
||||
const interceptHook = (hook, progress, category, name) => {
|
||||
hook.intercept({
|
||||
name: "ProgressPlugin",
|
||||
call() {
|
||||
handler(progress, name);
|
||||
handler(progress, category, name);
|
||||
},
|
||||
done() {
|
||||
handler(progress, name);
|
||||
handler(progress, category, name);
|
||||
},
|
||||
result() {
|
||||
handler(progress, name);
|
||||
handler(progress, category, name);
|
||||
},
|
||||
error() {
|
||||
handler(progress, name);
|
||||
handler(progress, category, name);
|
||||
},
|
||||
tap(tap) {
|
||||
progressReporters.set(compiler, (p, ...args) => {
|
||||
handler(progress, name, tap.name, ...args);
|
||||
handler(progress, category, name, tap.name, ...args);
|
||||
});
|
||||
handler(progress, name, tap.name);
|
||||
handler(progress, category, name, tap.name);
|
||||
}
|
||||
});
|
||||
};
|
||||
interceptHook(compiler.hooks.initialize, 0.0, "initialize");
|
||||
interceptHook(compiler.hooks.beforeRun, 0.01, "before run");
|
||||
interceptHook(compiler.hooks.run, 0.02, "run");
|
||||
interceptHook(compiler.hooks.watchRun, 0.02, "watch run");
|
||||
compiler.cache.hooks.endIdle.intercept({
|
||||
name: "ProgressPlugin",
|
||||
call() {
|
||||
handler(0, "");
|
||||
}
|
||||
});
|
||||
interceptHook(compiler.cache.hooks.endIdle, 0.01, "cache", "end idle");
|
||||
compiler.hooks.initialize.intercept({
|
||||
name: "ProgressPlugin",
|
||||
call() {
|
||||
handler(0, "");
|
||||
}
|
||||
});
|
||||
interceptHook(compiler.hooks.initialize, 0.01, "setup", "initialize");
|
||||
interceptHook(compiler.hooks.beforeRun, 0.02, "setup", "before run");
|
||||
interceptHook(compiler.hooks.run, 0.03, "setup", "run");
|
||||
interceptHook(compiler.hooks.watchRun, 0.03, "setup", "watch run");
|
||||
interceptHook(
|
||||
compiler.hooks.normalModuleFactory,
|
||||
0.03,
|
||||
0.04,
|
||||
"setup",
|
||||
"normal module factory"
|
||||
);
|
||||
interceptHook(
|
||||
compiler.hooks.contextModuleFactory,
|
||||
0.03,
|
||||
0.05,
|
||||
"setup",
|
||||
"context module factory"
|
||||
);
|
||||
interceptHook(compiler.hooks.beforeCompile, 0.035, "before compile");
|
||||
interceptHook(compiler.hooks.compile, 0.04, "compile");
|
||||
interceptHook(compiler.hooks.thisCompilation, 0.05, "setup compilation");
|
||||
interceptHook(compiler.hooks.compilation, 0.06, "setup compilation");
|
||||
interceptHook(compiler.hooks.finishMake, 0.69, "finish building");
|
||||
interceptHook(compiler.hooks.emit, 0.95, "emitting");
|
||||
interceptHook(compiler.hooks.afterEmit, 0.98, "after emitting");
|
||||
interceptHook(compiler.hooks.done, 0.99, "done");
|
||||
interceptHook(compiler.hooks.watchClose, 0.99, "closing watch compilation");
|
||||
interceptHook(
|
||||
compiler.hooks.beforeCompile,
|
||||
0.06,
|
||||
"setup",
|
||||
"before compile"
|
||||
);
|
||||
interceptHook(compiler.hooks.compile, 0.07, "setup", "compile");
|
||||
interceptHook(compiler.hooks.thisCompilation, 0.08, "setup", "compilation");
|
||||
interceptHook(compiler.hooks.compilation, 0.09, "setup", "compilation");
|
||||
interceptHook(compiler.hooks.finishMake, 0.69, "building", "finish");
|
||||
interceptHook(compiler.hooks.emit, 0.95, "emitting", "emit");
|
||||
interceptHook(compiler.hooks.afterEmit, 0.98, "emitting", "after emit");
|
||||
interceptHook(compiler.hooks.done, 0.99, "done", "plugins");
|
||||
compiler.hooks.done.intercept({
|
||||
name: "ProgressPlugin",
|
||||
done() {
|
||||
handler(0.99, "");
|
||||
}
|
||||
});
|
||||
interceptHook(
|
||||
compiler.cache.hooks.storeBuildDependencies,
|
||||
0.99,
|
||||
"cache",
|
||||
"store build dependencies"
|
||||
);
|
||||
interceptHook(compiler.cache.hooks.shutdown, 0.99, "cache", "shutdown");
|
||||
interceptHook(compiler.cache.hooks.beginIdle, 0.99, "cache", "begin idle");
|
||||
interceptHook(
|
||||
compiler.hooks.watchClose,
|
||||
0.99,
|
||||
"end",
|
||||
"closing watch compilation"
|
||||
);
|
||||
compiler.cache.hooks.beginIdle.intercept({
|
||||
name: "ProgressPlugin",
|
||||
done() {
|
||||
handler(1, "");
|
||||
}
|
||||
});
|
||||
compiler.cache.hooks.shutdown.intercept({
|
||||
name: "ProgressPlugin",
|
||||
done() {
|
||||
handler(1, "");
|
||||
|
|
129
lib/Watching.js
129
lib/Watching.js
|
@ -63,12 +63,11 @@ class Watching {
|
|||
this.startTime = Date.now();
|
||||
this.running = true;
|
||||
this.invalid = false;
|
||||
this.compiler.cache.endIdle(err => {
|
||||
if (err) return this._done(err);
|
||||
const run = () => {
|
||||
this.compiler.hooks.watchRun.callAsync(this.compiler, err => {
|
||||
if (err) return this._done(err);
|
||||
const onCompiled = (err, compilation) => {
|
||||
if (err) return this._done(err);
|
||||
if (err) return this._done(err, compilation);
|
||||
if (this.invalid) return this._done();
|
||||
|
||||
if (this.compiler.hooks.shouldEmit.call(compilation) === false) {
|
||||
|
@ -80,13 +79,13 @@ class Watching {
|
|||
logger.time("emitAssets");
|
||||
this.compiler.emitAssets(compilation, err => {
|
||||
logger.timeEnd("emitAssets");
|
||||
if (err) return this._done(err);
|
||||
if (this.invalid) return this._done();
|
||||
if (err) return this._done(err, compilation);
|
||||
if (this.invalid) return this._done(null, compilation);
|
||||
|
||||
logger.time("emitRecords");
|
||||
this.compiler.emitRecords(err => {
|
||||
logger.timeEnd("emitRecords");
|
||||
if (err) return this._done(err);
|
||||
if (err) return this._done(err, compilation);
|
||||
|
||||
if (compilation.hooks.needAdditionalPass.call()) {
|
||||
compilation.needAdditionalPass = true;
|
||||
|
@ -97,10 +96,10 @@ class Watching {
|
|||
logger.time("done hook");
|
||||
this.compiler.hooks.done.callAsync(stats, err => {
|
||||
logger.timeEnd("done hook");
|
||||
if (err) return this._done(err);
|
||||
if (err) return this._done(err, compilation);
|
||||
|
||||
this.compiler.hooks.additionalPass.callAsync(err => {
|
||||
if (err) return this._done(err);
|
||||
if (err) return this._done(err, compilation);
|
||||
this.compiler.compile(onCompiled);
|
||||
});
|
||||
});
|
||||
|
@ -113,7 +112,17 @@ class Watching {
|
|||
};
|
||||
this.compiler.compile(onCompiled);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
if (this.compiler.idle) {
|
||||
this.compiler.cache.endIdle(err => {
|
||||
if (err) return this._done(err);
|
||||
this.compiler.idle = false;
|
||||
run();
|
||||
});
|
||||
} else {
|
||||
run();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -134,36 +143,69 @@ class Watching {
|
|||
*/
|
||||
_done(err, compilation) {
|
||||
this.running = false;
|
||||
if (this.invalid) return this._go();
|
||||
|
||||
const stats = compilation ? this._getStats(compilation) : null;
|
||||
if (err) {
|
||||
const logger = compilation && compilation.getLogger("webpack.Watching");
|
||||
|
||||
let stats = null;
|
||||
|
||||
const handleError = err => {
|
||||
this.compiler.hooks.failed.call(err);
|
||||
this.compiler.cache.beginIdle();
|
||||
this.compiler.idle = true;
|
||||
this.handler(err, stats);
|
||||
for (const cb of this.callbacks) cb();
|
||||
this.callbacks.length = 0;
|
||||
};
|
||||
|
||||
if (this.invalid) {
|
||||
if (compilation) {
|
||||
logger.time("storeBuildDependencies");
|
||||
this.compiler.cache.storeBuildDependencies(
|
||||
compilation.buildDependencies,
|
||||
err => {
|
||||
logger.timeEnd("storeBuildDependencies");
|
||||
if (err) return handleError(err);
|
||||
this._go();
|
||||
}
|
||||
);
|
||||
} else {
|
||||
this._go();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const logger = compilation.getLogger("webpack.Watching");
|
||||
stats = compilation ? this._getStats(compilation) : null;
|
||||
if (err) return handleError(err);
|
||||
|
||||
logger.time("done hook");
|
||||
this.compiler.hooks.done.callAsync(stats, () => {
|
||||
this.compiler.hooks.done.callAsync(stats, err => {
|
||||
logger.timeEnd("done hook");
|
||||
logger.time("beginIdle");
|
||||
this.compiler.cache.beginIdle();
|
||||
logger.timeEnd("beginIdle");
|
||||
if (err) return handleError(err);
|
||||
this.handler(null, stats);
|
||||
process.nextTick(() => {
|
||||
if (!this.closed) {
|
||||
this.watch(
|
||||
compilation.fileDependencies,
|
||||
compilation.contextDependencies,
|
||||
compilation.missingDependencies
|
||||
);
|
||||
logger.time("storeBuildDependencies");
|
||||
this.compiler.cache.storeBuildDependencies(
|
||||
compilation.buildDependencies,
|
||||
err => {
|
||||
logger.timeEnd("storeBuildDependencies");
|
||||
if (err) return handleError(err);
|
||||
logger.time("beginIdle");
|
||||
this.compiler.cache.beginIdle();
|
||||
this.compiler.idle = true;
|
||||
logger.timeEnd("beginIdle");
|
||||
process.nextTick(() => {
|
||||
if (!this.closed) {
|
||||
this.watch(
|
||||
compilation.fileDependencies,
|
||||
compilation.contextDependencies,
|
||||
compilation.missingDependencies
|
||||
);
|
||||
}
|
||||
});
|
||||
for (const cb of this.callbacks) cb();
|
||||
this.callbacks.length = 0;
|
||||
this.compiler.hooks.afterDone.call(stats);
|
||||
}
|
||||
});
|
||||
for (const cb of this.callbacks) cb();
|
||||
this.callbacks.length = 0;
|
||||
this.compiler.hooks.afterDone.call(stats);
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -212,7 +254,7 @@ class Watching {
|
|||
}
|
||||
|
||||
/**
|
||||
* @param {Callback<void>=} callback signals when the build is invalidated
|
||||
* @param {Callback<void>=} callback signals when the build has completed again
|
||||
* @returns {void}
|
||||
*/
|
||||
invalidate(callback) {
|
||||
|
@ -266,7 +308,7 @@ class Watching {
|
|||
}
|
||||
return;
|
||||
}
|
||||
const finalCallback = () => {
|
||||
const finalCallback = (err, compilation) => {
|
||||
this.running = false;
|
||||
this.compiler.running = false;
|
||||
this.compiler.watchMode = false;
|
||||
|
@ -274,12 +316,27 @@ class Watching {
|
|||
this.compiler.removedFiles = undefined;
|
||||
this.compiler.fileTimestamps = undefined;
|
||||
this.compiler.contextTimestamps = undefined;
|
||||
this.compiler.cache.shutdown(err => {
|
||||
this.compiler.hooks.watchClose.call();
|
||||
const closeCallbacks = this._closeCallbacks;
|
||||
this._closeCallbacks = undefined;
|
||||
for (const cb of closeCallbacks) cb(err);
|
||||
});
|
||||
const shutdown = () => {
|
||||
this.compiler.cache.shutdown(err => {
|
||||
this.compiler.hooks.watchClose.call();
|
||||
const closeCallbacks = this._closeCallbacks;
|
||||
this._closeCallbacks = undefined;
|
||||
for (const cb of closeCallbacks) cb(err);
|
||||
});
|
||||
};
|
||||
if (compilation) {
|
||||
const logger = compilation.getLogger("webpack.Watching");
|
||||
logger.time("storeBuildDependencies");
|
||||
this.compiler.cache.storeBuildDependencies(
|
||||
compilation.buildDependencies,
|
||||
err => {
|
||||
logger.timeEnd("storeBuildDependencies");
|
||||
shutdown();
|
||||
}
|
||||
);
|
||||
} else {
|
||||
shutdown();
|
||||
}
|
||||
};
|
||||
|
||||
this.closed = true;
|
||||
|
|
|
@ -71,7 +71,7 @@ class IdleFileCachePlugin {
|
|||
);
|
||||
|
||||
compiler.cache.hooks.storeBuildDependencies.tap(
|
||||
{ name: "IdleFile", stage: Cache.STAGE_DISK },
|
||||
{ name: "IdleFileCachePlugin", stage: Cache.STAGE_DISK },
|
||||
dependencies => {
|
||||
pendingIdleTasks.set(BUILD_DEPENDENCIES_KEY, () =>
|
||||
strategy.storeBuildDependencies(dependencies)
|
||||
|
|
|
@ -40,14 +40,25 @@ describe("ProgressPlugin", function () {
|
|||
|
||||
expect(logs).toContainEqual(
|
||||
expect.stringMatching(
|
||||
/\[webpack\.Progress\] \d+ ms module ids DeterministicModuleIdsPlugin\n$/
|
||||
/\[webpack\.Progress\] {2}| {2}| \d+ ms module ids > DeterministicModuleIdsPlugin\n$/
|
||||
)
|
||||
);
|
||||
expect(logs).toContainEqual(
|
||||
expect.stringMatching(
|
||||
/\[webpack\.Progress\] \d+ ms(?: \(-\d+ ms\))? module ids\n$/
|
||||
/\[webpack\.Progress\] {2}| \d+ ms building > \.\.\. entries \.\.\. dependencies \.\.\. modules\n$/
|
||||
)
|
||||
);
|
||||
expect(logs).toContainEqual(
|
||||
expect.stringMatching(/\[webpack\.Progress\] \d+ ms building\n$/)
|
||||
);
|
||||
expect(logs).toContainEqual(
|
||||
expect.stringMatching(
|
||||
/\[webpack\.Progress\] {2}| \d+ ms sealing > module ids\n$/
|
||||
)
|
||||
);
|
||||
expect(logs).toContainEqual(
|
||||
expect.stringMatching(/\[webpack\.Progress\] \d+ ms sealing\n$/)
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -82,14 +93,10 @@ describe("ProgressPlugin", function () {
|
|||
expect(logs.length).toBeGreaterThan(20);
|
||||
logs.forEach(log => expect(log.length).toBeLessThanOrEqual(35));
|
||||
expect(logs).toContain(
|
||||
"75% ...optimization ...ChunksPlugin",
|
||||
"75% sealing ...mization ...nsPlugin",
|
||||
"trims each detail string equally"
|
||||
);
|
||||
expect(logs).toContain(
|
||||
"10% ...ding ...ries ...cies ...ules",
|
||||
"remove empty arguments and omit arguments when no space"
|
||||
);
|
||||
expect(logs).toContain("93% after asset optimization");
|
||||
expect(logs).toContain("92% sealing asset processing");
|
||||
expect(logs).toContain("100%");
|
||||
});
|
||||
});
|
||||
|
@ -113,8 +120,8 @@ describe("ProgressPlugin", function () {
|
|||
return RunCompilerAsync(compiler).then(() => {
|
||||
const logs = getLogs(stderr.toString());
|
||||
|
||||
expect(logs).toContain("3% normal module factory");
|
||||
expect(logs).toContain("3% context module factory");
|
||||
expect(logs).toContain("4% setup normal module factory");
|
||||
expect(logs).toContain("5% setup context module factory");
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
it("should contain the custom progress messages", function() {
|
||||
it("should contain the custom progress messages", function () {
|
||||
var data = require("data");
|
||||
expect(data).toContain("optimizing");
|
||||
expect(data).toContain("optimizing|CustomPlugin");
|
||||
expect(data).toContain("sealing|optimizing");
|
||||
expect(data).toContain("sealing|optimizing|CustomPlugin");
|
||||
expect(data).toContain(
|
||||
"optimizing|CustomPlugin|custom category|custom message"
|
||||
"sealing|optimizing|CustomPlugin|custom category|custom message"
|
||||
);
|
||||
});
|
||||
|
|
|
@ -1498,6 +1498,7 @@ declare class Compiler {
|
|||
cache: Cache;
|
||||
compilerPath: string;
|
||||
running: boolean;
|
||||
idle: boolean;
|
||||
watchMode: boolean;
|
||||
getCache(name: string): CacheFacade;
|
||||
getInfrastructureLogger(name: string | (() => string)): WebpackLogger;
|
||||
|
@ -3922,6 +3923,7 @@ declare interface LoaderItem {
|
|||
loader: string;
|
||||
options: any;
|
||||
ident: string;
|
||||
type: string;
|
||||
}
|
||||
declare class LoaderOptionsPlugin {
|
||||
constructor(options?: LoaderOptionsPluginOptions);
|
||||
|
@ -4621,7 +4623,7 @@ declare abstract class MultiStats {
|
|||
declare abstract class MultiWatching {
|
||||
watchings: Watching[];
|
||||
compiler: MultiCompiler;
|
||||
invalidate(): void;
|
||||
invalidate(callback?: any): void;
|
||||
suspend(): void;
|
||||
resume(): void;
|
||||
close(callback: CallbackFunction<void>): void;
|
||||
|
@ -4864,6 +4866,7 @@ declare class NormalModule extends Module {
|
|||
}
|
||||
declare interface NormalModuleCompilationHooks {
|
||||
loader: SyncHook<[any, NormalModule], void>;
|
||||
beforeLoaders: SyncHook<[LoaderItem[], any, NormalModule], void>;
|
||||
readResourceForScheme: HookMap<
|
||||
AsyncSeriesBailHook<[string, NormalModule], string | Buffer>
|
||||
>;
|
||||
|
|
Loading…
Reference in New Issue