mirror of
https://github.com/angular/angular-cli.git
synced 2025-05-20 13:32:43 +08:00
refactor(@ngtools/webpack): adjust virtual file watching for Webpack 5
The Webpack 5 filesystem watch function has a different return object type than Webpack 4. This change adjusts the behavior based on the used Webpack version.
This commit is contained in:
parent
e5266fdd44
commit
3740d80976
@ -10,6 +10,7 @@ import { Stats } from 'fs';
|
||||
import { InputFileSystem } from 'webpack';
|
||||
import { WebpackCompilerHost } from './compiler_host';
|
||||
import { NodeWatchFileSystemInterface } from './webpack';
|
||||
import { isWebpackFiveOrHigher } from './webpack-version';
|
||||
|
||||
export const NodeWatchFileSystem: NodeWatchFileSystemInterface = require(
|
||||
'webpack/lib/node/NodeWatchFileSystem');
|
||||
@ -112,106 +113,187 @@ export class VirtualWatchFileSystemDecorator extends NodeWatchFileSystem {
|
||||
super(_virtualInputFileSystem);
|
||||
}
|
||||
|
||||
watch = (
|
||||
files: Iterable<string>,
|
||||
dirs: Iterable<string>,
|
||||
missing: Iterable<string>,
|
||||
startTime: number,
|
||||
options: {},
|
||||
callback: Parameters<NodeWatchFileSystemInterface['watch']>[5],
|
||||
callbackUndelayed: (filename: string, timestamp: number) => void,
|
||||
): ReturnType<NodeWatchFileSystemInterface['watch']> => {
|
||||
const reverseReplacements = new Map<string, string>();
|
||||
const reverseTimestamps = <T>(map: Map<string, T>) => {
|
||||
for (const entry of Array.from(map.entries())) {
|
||||
const original = reverseReplacements.get(entry[0]);
|
||||
if (original) {
|
||||
map.set(original, entry[1]);
|
||||
map.delete(entry[0]);
|
||||
mapReplacements(
|
||||
original: Iterable<string>,
|
||||
reverseReplacements: Map<string, string>,
|
||||
): Iterable<string> {
|
||||
if (!this._replacements) {
|
||||
return original;
|
||||
}
|
||||
const replacements = this._replacements;
|
||||
|
||||
return [...original].map(file => {
|
||||
if (typeof replacements === 'function') {
|
||||
const replacement = getSystemPath(replacements(normalize(file)));
|
||||
if (replacement !== file) {
|
||||
reverseReplacements.set(replacement, file);
|
||||
}
|
||||
}
|
||||
|
||||
return map;
|
||||
};
|
||||
|
||||
const newCallbackUndelayed = (filename: string, timestamp: number) => {
|
||||
const original = reverseReplacements.get(filename);
|
||||
if (original) {
|
||||
this._virtualInputFileSystem.purge(original);
|
||||
callbackUndelayed(original, timestamp);
|
||||
return replacement;
|
||||
} else {
|
||||
callbackUndelayed(filename, timestamp);
|
||||
}
|
||||
};
|
||||
const replacement = replacements.get(normalize(file));
|
||||
if (replacement) {
|
||||
const fullReplacement = getSystemPath(replacement);
|
||||
reverseReplacements.set(fullReplacement, file);
|
||||
|
||||
const newCallback: Parameters<NodeWatchFileSystemInterface['watch']>[5] = (
|
||||
err: Error | null,
|
||||
filesModified: string[],
|
||||
contextModified: string[],
|
||||
missingModified: string[],
|
||||
fileTimestamps: Map<string, number>,
|
||||
contextTimestamps: Map<string, number>,
|
||||
) => {
|
||||
// Update fileTimestamps with timestamps from virtual files.
|
||||
const virtualFilesStats = this._virtualInputFileSystem.getVirtualFilesPaths()
|
||||
.map((fileName) => ({
|
||||
path: fileName,
|
||||
mtime: +this._virtualInputFileSystem.statSync(fileName).mtime,
|
||||
}));
|
||||
virtualFilesStats.forEach(stats => fileTimestamps.set(stats.path, +stats.mtime));
|
||||
callback(
|
||||
err,
|
||||
filesModified.map(value => reverseReplacements.get(value) || value),
|
||||
contextModified.map(value => reverseReplacements.get(value) || value),
|
||||
missingModified.map(value => reverseReplacements.get(value) || value),
|
||||
reverseTimestamps(fileTimestamps),
|
||||
reverseTimestamps(contextTimestamps),
|
||||
);
|
||||
};
|
||||
|
||||
const mapReplacements = (original: Iterable<string>): Iterable<string> => {
|
||||
if (!this._replacements) {
|
||||
return original;
|
||||
}
|
||||
const replacements = this._replacements;
|
||||
|
||||
return [...original].map(file => {
|
||||
if (typeof replacements === 'function') {
|
||||
const replacement = getSystemPath(replacements(normalize(file)));
|
||||
if (replacement !== file) {
|
||||
reverseReplacements.set(replacement, file);
|
||||
}
|
||||
|
||||
return replacement;
|
||||
return fullReplacement;
|
||||
} else {
|
||||
const replacement = replacements.get(normalize(file));
|
||||
if (replacement) {
|
||||
const fullReplacement = getSystemPath(replacement);
|
||||
reverseReplacements.set(fullReplacement, file);
|
||||
|
||||
return fullReplacement;
|
||||
} else {
|
||||
return file;
|
||||
}
|
||||
return file;
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const watcher = super.watch(
|
||||
mapReplacements(files),
|
||||
mapReplacements(dirs),
|
||||
mapReplacements(missing),
|
||||
startTime,
|
||||
options,
|
||||
newCallback,
|
||||
newCallbackUndelayed,
|
||||
);
|
||||
reverseTimestamps<T>(
|
||||
map: Map<string, T>,
|
||||
reverseReplacements: Map<string, string>,
|
||||
): Map<string, T> {
|
||||
for (const entry of Array.from(map.entries())) {
|
||||
const original = reverseReplacements.get(entry[0]);
|
||||
if (original) {
|
||||
map.set(original, entry[1]);
|
||||
map.delete(entry[0]);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
close: () => watcher.close(),
|
||||
pause: () => watcher.pause(),
|
||||
getFileTimestamps: () => reverseTimestamps(watcher.getFileTimestamps()),
|
||||
getContextTimestamps: () => reverseTimestamps(watcher.getContextTimestamps()),
|
||||
return map;
|
||||
}
|
||||
|
||||
createWebpack4Watch() {
|
||||
return (
|
||||
files: Iterable<string>,
|
||||
dirs: Iterable<string>,
|
||||
missing: Iterable<string>,
|
||||
startTime: number,
|
||||
options: {},
|
||||
callback: Parameters<NodeWatchFileSystemInterface['watch']>[5],
|
||||
callbackUndelayed: (filename: string, timestamp: number) => void,
|
||||
): ReturnType<NodeWatchFileSystemInterface['watch']> => {
|
||||
const reverseReplacements = new Map<string, string>();
|
||||
|
||||
const newCallbackUndelayed = (filename: string, timestamp: number) => {
|
||||
const original = reverseReplacements.get(filename);
|
||||
if (original) {
|
||||
this._virtualInputFileSystem.purge(original);
|
||||
callbackUndelayed(original, timestamp);
|
||||
} else {
|
||||
callbackUndelayed(filename, timestamp);
|
||||
}
|
||||
};
|
||||
|
||||
const newCallback: Parameters<NodeWatchFileSystemInterface['watch']>[5] = (
|
||||
err: Error | null,
|
||||
filesModified: string[],
|
||||
contextModified: string[],
|
||||
missingModified: string[],
|
||||
fileTimestamps: Map<string, number>,
|
||||
contextTimestamps: Map<string, number>,
|
||||
) => {
|
||||
// Update fileTimestamps with timestamps from virtual files.
|
||||
const virtualFilesStats = this._virtualInputFileSystem.getVirtualFilesPaths()
|
||||
.map((fileName) => ({
|
||||
path: fileName,
|
||||
mtime: +this._virtualInputFileSystem.statSync(fileName).mtime,
|
||||
}));
|
||||
virtualFilesStats.forEach(stats => fileTimestamps.set(stats.path, +stats.mtime));
|
||||
callback(
|
||||
err,
|
||||
filesModified.map(value => reverseReplacements.get(value) || value),
|
||||
contextModified.map(value => reverseReplacements.get(value) || value),
|
||||
missingModified.map(value => reverseReplacements.get(value) || value),
|
||||
this.reverseTimestamps(fileTimestamps, reverseReplacements),
|
||||
this.reverseTimestamps(contextTimestamps, reverseReplacements),
|
||||
);
|
||||
};
|
||||
|
||||
const watcher = super.watch(
|
||||
this.mapReplacements(files, reverseReplacements),
|
||||
this.mapReplacements(dirs, reverseReplacements),
|
||||
this.mapReplacements(missing, reverseReplacements),
|
||||
startTime,
|
||||
options,
|
||||
newCallback,
|
||||
newCallbackUndelayed,
|
||||
);
|
||||
|
||||
return {
|
||||
close: () => watcher.close(),
|
||||
pause: () => watcher.pause(),
|
||||
getFileTimestamps: () =>
|
||||
this.reverseTimestamps(watcher.getFileTimestamps(), reverseReplacements),
|
||||
getContextTimestamps: () =>
|
||||
this.reverseTimestamps(watcher.getContextTimestamps(), reverseReplacements),
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
createWebpack5Watch() {
|
||||
return (
|
||||
files: Iterable<string>,
|
||||
dirs: Iterable<string>,
|
||||
missing: Iterable<string>,
|
||||
startTime: number,
|
||||
options: {},
|
||||
callback: Parameters<NodeWatchFileSystemInterface['watch']>[5],
|
||||
callbackUndelayed: (filename: string, timestamp: number) => void,
|
||||
): ReturnType<NodeWatchFileSystemInterface['watch']> => {
|
||||
const reverseReplacements = new Map<string, string>();
|
||||
|
||||
const newCallbackUndelayed = (filename: string, timestamp: number) => {
|
||||
const original = reverseReplacements.get(filename);
|
||||
if (original) {
|
||||
this._virtualInputFileSystem.purge(original);
|
||||
callbackUndelayed(original, timestamp);
|
||||
} else {
|
||||
callbackUndelayed(filename, timestamp);
|
||||
}
|
||||
};
|
||||
|
||||
const newCallback = (
|
||||
err: Error,
|
||||
// tslint:disable-next-line: no-any
|
||||
fileTimeInfoEntries: Map<string, any>,
|
||||
// tslint:disable-next-line: no-any
|
||||
contextTimeInfoEntries: Map<string, any>,
|
||||
missing: Set<string>,
|
||||
removals: Set<string>,
|
||||
) => {
|
||||
// Update fileTimestamps with timestamps from virtual files.
|
||||
const virtualFilesStats = this._virtualInputFileSystem.getVirtualFilesPaths()
|
||||
.map((fileName) => ({
|
||||
path: fileName,
|
||||
mtime: +this._virtualInputFileSystem.statSync(fileName).mtime,
|
||||
}));
|
||||
virtualFilesStats.forEach(stats => fileTimeInfoEntries.set(stats.path, +stats.mtime));
|
||||
callback(
|
||||
err,
|
||||
this.reverseTimestamps(fileTimeInfoEntries, reverseReplacements),
|
||||
this.reverseTimestamps(contextTimeInfoEntries, reverseReplacements),
|
||||
new Set([...missing].map(value => reverseReplacements.get(value) || value)),
|
||||
new Set([...removals].map(value => reverseReplacements.get(value) || value)),
|
||||
);
|
||||
};
|
||||
|
||||
const watcher = super.watch(
|
||||
this.mapReplacements(files, reverseReplacements),
|
||||
this.mapReplacements(dirs, reverseReplacements),
|
||||
this.mapReplacements(missing, reverseReplacements),
|
||||
startTime,
|
||||
options,
|
||||
newCallback,
|
||||
newCallbackUndelayed,
|
||||
);
|
||||
|
||||
return {
|
||||
close: () => watcher.close(),
|
||||
pause: () => watcher.pause(),
|
||||
getFileTimeInfoEntries: () =>
|
||||
this.reverseTimestamps(watcher.getFileTimeInfoEntries(), reverseReplacements),
|
||||
getContextTimeInfoEntries: () =>
|
||||
this.reverseTimestamps(watcher.getContextTimeInfoEntries(), reverseReplacements),
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
watch = isWebpackFiveOrHigher() ? this.createWebpack5Watch : this.createWebpack4Watch();
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user