mirror of
https://github.com/angular/angular-cli.git
synced 2025-05-21 05:52:41 +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 { InputFileSystem } from 'webpack';
|
||||||
import { WebpackCompilerHost } from './compiler_host';
|
import { WebpackCompilerHost } from './compiler_host';
|
||||||
import { NodeWatchFileSystemInterface } from './webpack';
|
import { NodeWatchFileSystemInterface } from './webpack';
|
||||||
|
import { isWebpackFiveOrHigher } from './webpack-version';
|
||||||
|
|
||||||
export const NodeWatchFileSystem: NodeWatchFileSystemInterface = require(
|
export const NodeWatchFileSystem: NodeWatchFileSystemInterface = require(
|
||||||
'webpack/lib/node/NodeWatchFileSystem');
|
'webpack/lib/node/NodeWatchFileSystem');
|
||||||
@ -112,106 +113,187 @@ export class VirtualWatchFileSystemDecorator extends NodeWatchFileSystem {
|
|||||||
super(_virtualInputFileSystem);
|
super(_virtualInputFileSystem);
|
||||||
}
|
}
|
||||||
|
|
||||||
watch = (
|
mapReplacements(
|
||||||
files: Iterable<string>,
|
original: Iterable<string>,
|
||||||
dirs: Iterable<string>,
|
reverseReplacements: Map<string, string>,
|
||||||
missing: Iterable<string>,
|
): Iterable<string> {
|
||||||
startTime: number,
|
if (!this._replacements) {
|
||||||
options: {},
|
return original;
|
||||||
callback: Parameters<NodeWatchFileSystemInterface['watch']>[5],
|
}
|
||||||
callbackUndelayed: (filename: string, timestamp: number) => void,
|
const replacements = this._replacements;
|
||||||
): ReturnType<NodeWatchFileSystemInterface['watch']> => {
|
|
||||||
const reverseReplacements = new Map<string, string>();
|
return [...original].map(file => {
|
||||||
const reverseTimestamps = <T>(map: Map<string, T>) => {
|
if (typeof replacements === 'function') {
|
||||||
for (const entry of Array.from(map.entries())) {
|
const replacement = getSystemPath(replacements(normalize(file)));
|
||||||
const original = reverseReplacements.get(entry[0]);
|
if (replacement !== file) {
|
||||||
if (original) {
|
reverseReplacements.set(replacement, file);
|
||||||
map.set(original, entry[1]);
|
|
||||||
map.delete(entry[0]);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return map;
|
return replacement;
|
||||||
};
|
|
||||||
|
|
||||||
const newCallbackUndelayed = (filename: string, timestamp: number) => {
|
|
||||||
const original = reverseReplacements.get(filename);
|
|
||||||
if (original) {
|
|
||||||
this._virtualInputFileSystem.purge(original);
|
|
||||||
callbackUndelayed(original, timestamp);
|
|
||||||
} else {
|
} 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] = (
|
return fullReplacement;
|
||||||
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;
|
|
||||||
} else {
|
} else {
|
||||||
const replacement = replacements.get(normalize(file));
|
return file;
|
||||||
if (replacement) {
|
|
||||||
const fullReplacement = getSystemPath(replacement);
|
|
||||||
reverseReplacements.set(fullReplacement, file);
|
|
||||||
|
|
||||||
return fullReplacement;
|
|
||||||
} else {
|
|
||||||
return file;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
};
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const watcher = super.watch(
|
reverseTimestamps<T>(
|
||||||
mapReplacements(files),
|
map: Map<string, T>,
|
||||||
mapReplacements(dirs),
|
reverseReplacements: Map<string, string>,
|
||||||
mapReplacements(missing),
|
): Map<string, T> {
|
||||||
startTime,
|
for (const entry of Array.from(map.entries())) {
|
||||||
options,
|
const original = reverseReplacements.get(entry[0]);
|
||||||
newCallback,
|
if (original) {
|
||||||
newCallbackUndelayed,
|
map.set(original, entry[1]);
|
||||||
);
|
map.delete(entry[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return map;
|
||||||
close: () => watcher.close(),
|
}
|
||||||
pause: () => watcher.pause(),
|
|
||||||
getFileTimestamps: () => reverseTimestamps(watcher.getFileTimestamps()),
|
createWebpack4Watch() {
|
||||||
getContextTimestamps: () => reverseTimestamps(watcher.getContextTimestamps()),
|
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