mirror of
https://github.com/angular/angular-cli.git
synced 2025-05-16 18:43:42 +08:00
fix(@ngtools/webpack): support watching file replacements
This commit is contained in:
parent
56fb5ebce0
commit
d09d739b60
@ -5,7 +5,7 @@
|
|||||||
* Use of this source code is governed by an MIT-style license that can be
|
* Use of this source code is governed by an MIT-style license that can be
|
||||||
* found in the LICENSE file at https://angular.io/license
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
import { dirname, normalize, resolve, virtualFs } from '@angular-devkit/core';
|
import { Path, dirname, normalize, resolve, virtualFs } from '@angular-devkit/core';
|
||||||
import { NodeJsSyncHost } from '@angular-devkit/core/node';
|
import { NodeJsSyncHost } from '@angular-devkit/core/node';
|
||||||
import { ChildProcess, ForkOptions, fork } from 'child_process';
|
import { ChildProcess, ForkOptions, fork } from 'child_process';
|
||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
@ -617,8 +617,21 @@ export class AngularCompilerPlugin {
|
|||||||
this._compilerHost,
|
this._compilerHost,
|
||||||
);
|
);
|
||||||
compilerWithFileSystems.inputFileSystem = inputDecorator;
|
compilerWithFileSystems.inputFileSystem = inputDecorator;
|
||||||
|
|
||||||
|
let replacements: Map<Path, Path> | undefined;
|
||||||
|
if (this._options.hostReplacementPaths) {
|
||||||
|
replacements = new Map();
|
||||||
|
for (const replace in this._options.hostReplacementPaths) {
|
||||||
|
replacements.set(
|
||||||
|
normalize(replace),
|
||||||
|
normalize(this._options.hostReplacementPaths[replace]),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
compilerWithFileSystems.watchFileSystem = new VirtualWatchFileSystemDecorator(
|
compilerWithFileSystems.watchFileSystem = new VirtualWatchFileSystemDecorator(
|
||||||
inputDecorator,
|
inputDecorator,
|
||||||
|
replacements,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
* Use of this source code is governed by an MIT-style license that can be
|
* Use of this source code is governed by an MIT-style license that can be
|
||||||
* found in the LICENSE file at https://angular.io/license
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
|
import { Path, getSystemPath, normalize } from '@angular-devkit/core';
|
||||||
import { Stats } from 'fs';
|
import { Stats } from 'fs';
|
||||||
import { WebpackCompilerHost } from './compiler_host';
|
import { WebpackCompilerHost } from './compiler_host';
|
||||||
import { Callback, InputFileSystem, NodeWatchFileSystemInterface } from './webpack';
|
import { Callback, InputFileSystem, NodeWatchFileSystemInterface } from './webpack';
|
||||||
@ -105,26 +106,52 @@ export class VirtualFileSystemDecorator implements InputFileSystem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class VirtualWatchFileSystemDecorator extends NodeWatchFileSystem {
|
export class VirtualWatchFileSystemDecorator extends NodeWatchFileSystem {
|
||||||
constructor(private _virtualInputFileSystem: VirtualFileSystemDecorator) {
|
constructor(
|
||||||
|
private _virtualInputFileSystem: VirtualFileSystemDecorator,
|
||||||
|
private _replacements?: Map<Path, Path>,
|
||||||
|
) {
|
||||||
super(_virtualInputFileSystem);
|
super(_virtualInputFileSystem);
|
||||||
}
|
}
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
files: any, // tslint:disable-line:no-any
|
files: string[],
|
||||||
dirs: any, // tslint:disable-line:no-any
|
dirs: string[],
|
||||||
missing: any, // tslint:disable-line:no-any
|
missing: string[],
|
||||||
startTime: any, // tslint:disable-line:no-any
|
startTime: number | undefined,
|
||||||
options: any, // tslint:disable-line:no-any
|
options: {},
|
||||||
callback: any, // tslint:disable-line:no-any
|
callback: any, // tslint:disable-line:no-any
|
||||||
callbackUndelayed: any, // tslint:disable-line:no-any
|
callbackUndelayed: (filename: string, timestamp: number) => void,
|
||||||
) {
|
) {
|
||||||
|
const reverseReplacements = new Map<string, string>();
|
||||||
|
const reverseTimestamps = (map: Map<string, number>) => {
|
||||||
|
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 map;
|
||||||
|
};
|
||||||
|
|
||||||
|
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 = (
|
const newCallback = (
|
||||||
err: any, // tslint:disable-line:no-any
|
err: Error | null,
|
||||||
filesModified: any, // tslint:disable-line:no-any
|
filesModified: string[],
|
||||||
contextModified: any, // tslint:disable-line:no-any
|
contextModified: string[],
|
||||||
missingModified: any, // tslint:disable-line:no-any
|
missingModified: string[],
|
||||||
fileTimestamps: { [k: string]: number },
|
fileTimestamps: Map<string, number>,
|
||||||
contextTimestamps: { [k: string]: number },
|
contextTimestamps: Map<string, number>,
|
||||||
) => {
|
) => {
|
||||||
// Update fileTimestamps with timestamps from virtual files.
|
// Update fileTimestamps with timestamps from virtual files.
|
||||||
const virtualFilesStats = this._virtualInputFileSystem.getVirtualFilesPaths()
|
const virtualFilesStats = this._virtualInputFileSystem.getVirtualFilesPaths()
|
||||||
@ -132,11 +159,51 @@ export class VirtualWatchFileSystemDecorator extends NodeWatchFileSystem {
|
|||||||
path: fileName,
|
path: fileName,
|
||||||
mtime: +this._virtualInputFileSystem.statSync(fileName).mtime,
|
mtime: +this._virtualInputFileSystem.statSync(fileName).mtime,
|
||||||
}));
|
}));
|
||||||
virtualFilesStats.forEach(stats => fileTimestamps[stats.path] = +stats.mtime);
|
virtualFilesStats.forEach(stats => fileTimestamps.set(stats.path, +stats.mtime));
|
||||||
callback(err, filesModified, contextModified, missingModified, fileTimestamps,
|
callback(
|
||||||
contextTimestamps);
|
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),
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
return super.watch(files, dirs, missing, startTime, options, newCallback, callbackUndelayed);
|
const mapReplacements = (original: string[]): string[] => {
|
||||||
|
if (!this._replacements) {
|
||||||
|
return original;
|
||||||
|
}
|
||||||
|
const replacements = this._replacements;
|
||||||
|
|
||||||
|
return original.map(file => {
|
||||||
|
const replacement = replacements.get(normalize(file));
|
||||||
|
if (replacement) {
|
||||||
|
const fullReplacement = getSystemPath(replacement);
|
||||||
|
reverseReplacements.set(fullReplacement, file);
|
||||||
|
|
||||||
|
return fullReplacement;
|
||||||
|
} else {
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const watcher = super.watch(
|
||||||
|
mapReplacements(files),
|
||||||
|
mapReplacements(dirs),
|
||||||
|
mapReplacements(missing),
|
||||||
|
startTime,
|
||||||
|
options,
|
||||||
|
newCallback,
|
||||||
|
newCallbackUndelayed,
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
close: () => watcher.close(),
|
||||||
|
pause: () => watcher.pause(),
|
||||||
|
getFileTimestamps: () => reverseTimestamps(watcher.getFileTimestamps()),
|
||||||
|
getContextTimestamps: () => reverseTimestamps(watcher.getContextTimestamps()),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user