Skip to content

Commit 466dfb6

Browse files
committed
fix(@angular/cli): use the new compiler API for listLazyRoutes
Replacing the old API. We keep the old API because we need it for JIT (with either --aot=false or unittests). Depends on angular/angular#19836
1 parent 5364bbc commit 466dfb6

File tree

2 files changed

+58
-4
lines changed

2 files changed

+58
-4
lines changed

packages/@ngtools/webpack/src/angular_compiler_plugin.ts

+51-4
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,11 @@ import {
4141
CompilerHost,
4242
Diagnostics,
4343
CustomTransformers,
44+
EmitFlags,
45+
LazyRoute,
4446
createProgram,
4547
createCompilerHost,
4648
formatDiagnostics,
47-
EmitFlags,
4849
} from './ngtools_api';
4950
import { findAstNodes } from './transformers/ast_helpers';
5051

@@ -87,7 +88,7 @@ export class AngularCompilerPlugin implements Tapable {
8788
private _compilerOptions: ts.CompilerOptions;
8889
private _angularCompilerOptions: CompilerOptions;
8990
private _tsFilenames: string[];
90-
private _program: ts.Program | Program;
91+
private _program: (ts.Program | Program);
9192
private _compilerHost: WebpackCompilerHost;
9293
private _moduleResolutionCache: ts.ModuleResolutionCache;
9394
private _angularCompilerHost: WebpackCompilerHost & CompilerHost;
@@ -111,6 +112,14 @@ export class AngularCompilerPlugin implements Tapable {
111112
private _forkTypeChecker = true;
112113
private _typeCheckerProcess: ChildProcess;
113114

115+
private get _ngCompilerSupportsNewApi() {
116+
if (this._JitMode) {
117+
return false;
118+
} else {
119+
return !!(this._program as Program).listLazyRoutes;
120+
}
121+
}
122+
114123
constructor(options: AngularCompilerPluginOptions) {
115124
CompilerCliIsSupported();
116125
this._options = Object.assign({}, options);
@@ -364,8 +373,10 @@ export class AngularCompilerPlugin implements Tapable {
364373
timeEnd('AngularCompilerPlugin._createOrUpdateProgram.ng.createProgram');
365374

366375
time('AngularCompilerPlugin._createOrUpdateProgram.ng.loadNgStructureAsync');
367-
return this._program.loadNgStructureAsync().then(() =>
368-
timeEnd('AngularCompilerPlugin._createOrUpdateProgram.ng.loadNgStructureAsync'));
376+
return this._program.loadNgStructureAsync()
377+
.then(() => {
378+
timeEnd('AngularCompilerPlugin._createOrUpdateProgram.ng.loadNgStructureAsync');
379+
});
369380
}
370381
}
371382

@@ -409,6 +420,32 @@ export class AngularCompilerPlugin implements Tapable {
409420
return result;
410421
}
411422

423+
private _listLazyRoutesFromProgram(): LazyRouteMap {
424+
const ngProgram = this._program as Program;
425+
if (!ngProgram.listLazyRoutes) {
426+
throw new Error('_listLazyRoutesFromProgram was called with an old program.');
427+
}
428+
429+
const lazyRoutes = ngProgram.listLazyRoutes();
430+
431+
return lazyRoutes.reduce(
432+
(acc: LazyRouteMap, curr: LazyRoute) => {
433+
const ref = curr.route;
434+
if (ref in acc && acc[ref] !== curr.referencedModule.filePath) {
435+
throw new Error(
436+
+ `Duplicated path in loadChildren detected: "${ref}" is used in 2 loadChildren, `
437+
+ `but they point to different modules "(${acc[ref]} and `
438+
+ `"${curr.referencedModule.filePath}"). Webpack cannot distinguish on context and `
439+
+ 'would fail to load the proper one.'
440+
);
441+
}
442+
acc[ref] = curr.referencedModule.filePath;
443+
return acc;
444+
},
445+
{} as LazyRouteMap
446+
);
447+
}
448+
412449
// Process the lazy routes discovered, adding then to _lazyRoutes.
413450
// TODO: find a way to remove lazy routes that don't exist anymore.
414451
// This will require a registry of known references to a lazy route, removing it when no
@@ -666,6 +703,10 @@ export class AngularCompilerPlugin implements Tapable {
666703

667704
return Promise.resolve()
668705
.then(() => {
706+
if (this._ngCompilerSupportsNewApi) {
707+
return;
708+
}
709+
669710
// Try to find lazy routes.
670711
// We need to run the `listLazyRoutes` the first time because it also navigates libraries
671712
// and other things that we might miss using the (faster) findLazyRoutesInAst.
@@ -684,6 +725,12 @@ export class AngularCompilerPlugin implements Tapable {
684725
return this._createOrUpdateProgram();
685726
}
686727
})
728+
.then(() => {
729+
if (this._ngCompilerSupportsNewApi) {
730+
// TODO: keep this when the new ngCompiler supports the new lazy routes API.
731+
this._lazyRoutes = this._listLazyRoutesFromProgram();
732+
}
733+
})
687734
.then(() => {
688735
// Build transforms, emit and report errors if there are changes or it's the first run.
689736
if (changedFiles.length > 0 || this._firstRun) {

packages/@ngtools/webpack/src/ngtools_api.ts

+7
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ export interface Program {
7676
getNgSemanticDiagnostics(fileName?: string, cancellationToken?: ts.CancellationToken):
7777
Diagnostic[];
7878
loadNgStructureAsync(): Promise<void>;
79+
listLazyRoutes?(): LazyRoute[];
7980
emit({ emitFlags, cancellationToken, customTransformers, emitCallback }: {
8081
emitFlags?: any;
8182
cancellationToken?: ts.CancellationToken;
@@ -84,6 +85,12 @@ export interface Program {
8485
}): ts.EmitResult;
8586
}
8687

88+
export interface LazyRoute {
89+
route: string;
90+
module: { name: string, filePath: string };
91+
referencedModule: { name: string, filePath: string };
92+
}
93+
8794
export declare type Diagnostics = Array<ts.Diagnostic | Diagnostic>;
8895

8996
// Interfaces for the function declarations.

0 commit comments

Comments
 (0)