Skip to content

Fix file watching with file replacements #11509

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Jul 12, 2018
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,12 @@

// tslint:disable-next-line:no-implicit-dependencies
import * as ts from 'typescript';
import { AssetPatternObject, Budget, ExtraEntryPoint } from '../../browser/schema';
import {
AssetPatternObject,
Budget,
CurrentFileReplacement,
ExtraEntryPoint,
} from '../../browser/schema';

export interface BuildOptions {
optimization: boolean;
Expand Down Expand Up @@ -58,6 +63,7 @@ export interface BuildOptions {
stylePreprocessorOptions?: { includePaths: string[] };
lazyModules: string[];
platform?: 'browser' | 'server';
fileReplacements: CurrentFileReplacement[];
}

export interface WebpackTestOptions extends BuildOptions {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
*/
// tslint:disable
// TODO: cleanup this file, it's copied as is from Angular CLI.
import { tags, virtualFs } from '@angular-devkit/core';
import { virtualFs } from '@angular-devkit/core';
import { Stats } from 'fs';
import * as path from 'path';
import {
Expand All @@ -28,9 +28,9 @@ const webpackLoader: string = g['_DevKitIsLocal']
function _createAotPlugin(
wco: WebpackConfigOptions,
options: any,
host: virtualFs.Host<Stats>,
_host: virtualFs.Host<Stats>,
useMain = true,
extract = false
extract = false,
) {
const { root, buildOptions } = wco;
options.compilerOptions = options.compilerOptions || {};
Expand Down Expand Up @@ -62,6 +62,13 @@ function _createAotPlugin(
}
}

const hostReplacementPaths: { [replace: string]: string } = {};
if (buildOptions.fileReplacements) {
for (const replacement of buildOptions.fileReplacements) {
hostReplacementPaths[replacement.replace] = replacement.with;
}
}

const pluginOptions: AngularCompilerPluginOptions = {
mainPath: useMain ? path.join(root, buildOptions.main) : undefined,
...i18nFileAndFormat,
Expand All @@ -70,11 +77,11 @@ function _createAotPlugin(
missingTranslation: buildOptions.i18nMissingTranslation,
sourceMap: buildOptions.sourceMap,
additionalLazyModules,
hostReplacementPaths,
nameLazyFiles: buildOptions.namedChunks,
forkTypeChecker: buildOptions.forkTypeChecker,
contextElementDependencyConstructor: require('webpack/lib/dependencies/ContextElementDependency'),
...options,
host,
};
return new AngularCompilerPlugin(pluginOptions);
}
Expand Down
5 changes: 3 additions & 2 deletions packages/angular_devkit/build_angular/src/browser/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ import {
statsToString,
statsWarningsToString,
} from '../angular-cli-files/utilities/stats';
import { addFileReplacements, normalizeAssetPatterns } from '../utils';
import { normalizeAssetPatterns, normalizeFileReplacements } from '../utils';
import { AssetPatternObject, BrowserBuilderSchema, CurrentFileReplacement } from './schema';
const webpackMerge = require('webpack-merge');

Expand Down Expand Up @@ -64,7 +64,8 @@ export class BrowserBuilder implements Builder<BrowserBuilderSchema> {
concatMap(() => options.deleteOutputPath
? this._deleteOutputDir(root, normalize(options.outputPath), this.context.host)
: of(null)),
concatMap(() => addFileReplacements(root, host, options.fileReplacements)),
concatMap(() => normalizeFileReplacements(options.fileReplacements, host, root)),
tap(fileReplacements => options.fileReplacements = fileReplacements),
concatMap(() => normalizeAssetPatterns(
options.assets, host, root, projectRoot, builderConfig.sourceRoot)),
// Replace the assets in options with the normalized version.
Expand Down
5 changes: 3 additions & 2 deletions packages/angular_devkit/build_angular/src/dev-server/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import * as WebpackDevServer from 'webpack-dev-server';
import { checkPort } from '../angular-cli-files/utilities/check-port';
import { BrowserBuilder, NormalizedBrowserBuilderSchema, getBrowserLoggingCb } from '../browser/';
import { BrowserBuilderSchema } from '../browser/schema';
import { addFileReplacements, normalizeAssetPatterns } from '../utils';
import { normalizeAssetPatterns, normalizeFileReplacements } from '../utils';
const opn = require('opn');


Expand Down Expand Up @@ -78,7 +78,8 @@ export class DevServerBuilder implements Builder<DevServerBuilderOptions> {
tap((port) => options.port = port),
concatMap(() => this._getBrowserOptions(options)),
tap((opts) => browserOptions = opts),
concatMap(() => addFileReplacements(root, host, browserOptions.fileReplacements)),
concatMap(() => normalizeFileReplacements(browserOptions.fileReplacements, host, root)),
tap(fileReplacements => browserOptions.fileReplacements = fileReplacements),
concatMap(() => normalizeAssetPatterns(
browserOptions.assets, host, root, projectRoot, builderConfig.sourceRoot)),
// Replace the assets in options with the normalized version.
Expand Down
5 changes: 3 additions & 2 deletions packages/angular_devkit/build_angular/src/karma/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import {
import { readTsconfig } from '../angular-cli-files/utilities/read-tsconfig';
import { requireProjectModule } from '../angular-cli-files/utilities/require-project-module';
import { AssetPatternObject, CurrentFileReplacement } from '../browser/schema';
import { addFileReplacements, normalizeAssetPatterns } from '../utils';
import { normalizeAssetPatterns, normalizeFileReplacements } from '../utils';
import { KarmaBuilderSchema } from './schema';
const webpackMerge = require('webpack-merge');

Expand All @@ -47,7 +47,8 @@ export class KarmaBuilder implements Builder<KarmaBuilderSchema> {
const host = new virtualFs.AliasHost(this.context.host as virtualFs.Host<fs.Stats>);

return of(null).pipe(
concatMap(() => addFileReplacements(root, host, options.fileReplacements)),
concatMap(() => normalizeFileReplacements(options.fileReplacements, host, root)),
tap(fileReplacements => options.fileReplacements = fileReplacements),
concatMap(() => normalizeAssetPatterns(
options.assets, host, root, projectRoot, builderConfig.sourceRoot)),
// Replace the assets in options with the normalized version.
Expand Down
7 changes: 4 additions & 3 deletions packages/angular_devkit/build_angular/src/server/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { WebpackBuilder } from '@angular-devkit/build-webpack';
import { Path, getSystemPath, normalize, resolve, virtualFs } from '@angular-devkit/core';
import { Stats } from 'fs';
import { Observable, concat, of } from 'rxjs';
import { concatMap, last } from 'rxjs/operators';
import { concatMap, last, tap } from 'rxjs/operators';
import * as ts from 'typescript'; // tslint:disable-line:no-implicit-dependencies
import { WebpackConfigOptions } from '../angular-cli-files/models/build-options';
import {
Expand All @@ -30,7 +30,7 @@ import {
import { readTsconfig } from '../angular-cli-files/utilities/read-tsconfig';
import { requireProjectModule } from '../angular-cli-files/utilities/require-project-module';
import { getBrowserLoggingCb } from '../browser';
import { addFileReplacements } from '../utils';
import { normalizeFileReplacements } from '../utils';
import { BuildWebpackServerSchema } from './schema';
const webpackMerge = require('webpack-merge');

Expand All @@ -51,7 +51,8 @@ export class ServerBuilder implements Builder<BuildWebpackServerSchema> {
concatMap(() => options.deleteOutputPath
? this._deleteOutputDir(root, normalize(options.outputPath), this.context.host)
: of(null)),
concatMap(() => addFileReplacements(root, host, options.fileReplacements)),
concatMap(() => normalizeFileReplacements(options.fileReplacements, host, root)),
tap(fileReplacements => options.fileReplacements = fileReplacements),
concatMap(() => {
const webpackConfig = this.buildWebpackConfig(root, projectRoot, host, options);

Expand Down

This file was deleted.

2 changes: 1 addition & 1 deletion packages/angular_devkit/build_angular/src/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@
*/

export * from './run-module-as-observable-fork';
export * from './add-file-replacements';
export * from './normalize-file-replacements';
export * from './normalize-asset-patterns';
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* 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
*/

import {
BaseException,
Path,
getSystemPath,
join,
normalize,
virtualFs,
} from '@angular-devkit/core';
import { Observable, from, of } from 'rxjs';
import { concat, concatMap, ignoreElements, map, mergeMap, tap, toArray } from 'rxjs/operators';
import {
CurrentFileReplacement,
DeprecatedFileReplacment,
FileReplacement,
} from '../browser/schema';


export class MissingFileReplacementException extends BaseException {
constructor(path: String) {
super(`The ${path} path in file replacements does not exist.`);
}
}

export interface NormalizedFileReplacement {
replace: Path;
with: Path;
}

export function normalizeFileReplacements(
fileReplacements: FileReplacement[],
host: virtualFs.Host,
root: Path,
): Observable<NormalizedFileReplacement[]> {
if (fileReplacements.length === 0) {
return of([]);
}

// Ensure all the replacements exist.
const errorOnFalse = (path: Path) => tap((exists: boolean) => {
if (!exists) {
throw new MissingFileReplacementException(getSystemPath(path));
}
});

return from(fileReplacements).pipe(
map(replacement => normalizeFileReplacement(replacement, root)),
concatMap(normalized => {
return from([normalized.replace, normalized.with]).pipe(
mergeMap(path => host.exists(path).pipe(errorOnFalse(path))),
ignoreElements(),
concat(of(normalized)),
);
}),
toArray(),
);
}

function normalizeFileReplacement(
fileReplacement: FileReplacement,
root?: Path,
): NormalizedFileReplacement {
const currentFormat = fileReplacement as CurrentFileReplacement;
const maybeOldFormat = fileReplacement as DeprecatedFileReplacment;

let replacePath: Path;
let withPath: Path;
if (maybeOldFormat.src && maybeOldFormat.replaceWith) {
replacePath = normalize(maybeOldFormat.src);
withPath = normalize(maybeOldFormat.replaceWith);
} else {
replacePath = normalize(currentFormat.replace);
withPath = normalize(currentFormat.with);
}

// TODO: For 7.x should this only happen if not absolute?
if (root) {
replacePath = join(root, replacePath);
}
if (root) {
withPath = join(root, withPath);
}

return { replace: replacePath, with: withPath };
}
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,9 @@ export class WebpackFileSystemHostAdapter implements InputFileSystem {
return this._doHostCall(this._host.list(normalize('/' + path)), callback);
}

readFile(path: string, callback: Callback<string>): void {
readFile(path: string, callback: Callback<Buffer>): void {
const o = this._host.read(normalize('/' + path)).pipe(
map(content => virtualFs.fileBufferToString(content)),
map(content => Buffer.from(content)),
);

return this._doHostCall(o, callback);
Expand Down Expand Up @@ -134,15 +134,21 @@ export class WebpackFileSystemHostAdapter implements InputFileSystem {

return this._syncHost.list(normalize('/' + path));
}
readFileSync(path: string): string {
readFileSync(path: string): Buffer {
if (!this._syncHost) {
this._syncHost = new virtualFs.SyncDelegateHost(this._host);
}

return virtualFs.fileBufferToString(this._syncHost.read(normalize('/' + path)));
return Buffer.from(this._syncHost.read(normalize('/' + path)));
}
readJsonSync(path: string): string {
return JSON.parse(this.readFileSync(path));
readJsonSync(path: string): {} {
if (!this._syncHost) {
this._syncHost = new virtualFs.SyncDelegateHost(this._host);
}

const data = this._syncHost.read(normalize('/' + path));

return JSON.parse(virtualFs.fileBufferToString(data));
}
readlinkSync(path: string): string {
const err: NodeJS.ErrnoException = new Error('Not a symlink.');
Expand Down
Loading