55 * Use of this source code is governed by an MIT-style license that can be
66 * found in the LICENSE file at https://angular.io/license
77 */
8- // TODO: fix webpack typings.
9- // tslint:disable-next-line:no-global-tslint-disable
10- // tslint:disable:no-any
118import { dirname , normalize , resolve , virtualFs } from '@angular-devkit/core' ;
129import { ChildProcess , ForkOptions , fork } from 'child_process' ;
1310import * as fs from 'fs' ;
1411import * as path from 'path' ;
1512import * as ts from 'typescript' ;
13+ import { Compiler , compilation } from 'webpack' ;
1614import { time , timeEnd } from './benchmark' ;
1715import { WebpackCompilerHost , workaroundResolve } from './compiler_host' ;
1816import { resolveEntryModuleFromMain } from './entry_resolver' ;
@@ -53,6 +51,12 @@ import {
5351 VirtualFileSystemDecorator ,
5452 VirtualWatchFileSystemDecorator ,
5553} from './virtual_file_system_decorator' ;
54+ import {
55+ Callback ,
56+ InputFileSystem ,
57+ NodeWatchFileSystemInterface ,
58+ NormalModuleFactoryRequest ,
59+ } from './webpack' ;
5660
5761const treeKill = require ( 'tree-kill' ) ;
5862
@@ -598,18 +602,28 @@ export class AngularCompilerPlugin {
598602 }
599603
600604 // Registration hook for webpack plugin.
601- // tslint:disable-next-line:no-any
602- apply ( compiler : any ) {
605+ apply ( compiler : Compiler ) {
603606 // Decorate inputFileSystem to serve contents of CompilerHost.
604607 // Use decorated inputFileSystem in watchFileSystem.
605608 compiler . hooks . environment . tap ( 'angular-compiler' , ( ) => {
606- compiler . inputFileSystem = new VirtualFileSystemDecorator (
607- compiler . inputFileSystem , this . _compilerHost ) ;
608- compiler . watchFileSystem = new VirtualWatchFileSystemDecorator ( compiler . inputFileSystem ) ;
609+ // The webpack types currently do not include these
610+ const compilerWithFileSystems = compiler as Compiler & {
611+ inputFileSystem : InputFileSystem ,
612+ watchFileSystem : NodeWatchFileSystemInterface ,
613+ } ;
614+
615+ const inputDecorator = new VirtualFileSystemDecorator (
616+ compilerWithFileSystems . inputFileSystem ,
617+ this . _compilerHost ,
618+ ) ;
619+ compilerWithFileSystems . inputFileSystem = inputDecorator ;
620+ compilerWithFileSystems . watchFileSystem = new VirtualWatchFileSystemDecorator (
621+ inputDecorator ,
622+ ) ;
609623 } ) ;
610624
611625 // Add lazy modules to the context module for @angular /core
612- compiler . hooks . contextModuleFactory . tap ( 'angular-compiler' , ( cmf : any ) => {
626+ compiler . hooks . contextModuleFactory . tap ( 'angular-compiler' , cmf => {
613627 const angularCorePackagePath = require . resolve ( '@angular/core/package.json' ) ;
614628
615629 // APFv6 does not have single FESM anymore. Instead of verifying if we're pointing to
@@ -621,141 +635,139 @@ export class AngularCompilerPlugin {
621635 // We resolve any symbolic links in order to get the real path that would be used in webpack.
622636 const angularCoreDirname = fs . realpathSync ( path . dirname ( angularCorePackagePath ) ) ;
623637
624- cmf . hooks . afterResolve . tapAsync ( 'angular-compiler' ,
625- // tslint:disable-next-line:no-any
626- ( result : any , callback : ( err ?: Error , request ?: any ) => void ) => {
627- if ( ! result ) {
628- return callback ( ) ;
629- }
630-
638+ cmf . hooks . afterResolve . tapPromise ( 'angular-compiler' , async result => {
631639 // Alter only request from Angular.
632- if ( ! result . resource . startsWith ( angularCoreDirname ) ) {
633- return callback ( undefined , result ) ;
634- }
635- if ( ! this . done ) {
636- return callback ( undefined , result ) ;
640+ if ( ! result || ! this . done || ! result . resource . startsWith ( angularCoreDirname ) ) {
641+ return result ;
637642 }
638643
639- this . done . then ( ( ) => {
640- // This folder does not exist, but we need to give webpack a resource.
641- // TODO: check if we can't just leave it as is (angularCoreModuleDir) .
642- result . resource = path . join ( this . _basePath , '$$_lazy_route_resource' ) ;
643- result . dependencies . forEach ( ( d : any ) => d . critical = false ) ;
644- result . resolveDependencies = ( _fs : any , resourceOrOptions : any , recursiveOrCallback : any ,
645- _regExp : RegExp , cb : any ) => {
646- const dependencies = Object . keys ( this . _lazyRoutes )
647- . map ( ( key ) => {
648- const modulePath = this . _lazyRoutes [ key ] ;
649- const importPath = key . split ( '#' ) [ 0 ] ;
650- if ( modulePath !== null ) {
651- const name = importPath . replace ( / ( \. n g f a c t o r y ) ? \. ( j s | t s ) $ / , '' ) ;
652-
653- return new this . _contextElementDependencyConstructor ( modulePath , name ) ;
654- } else {
655- return null ;
656- }
657- } )
658- . filter ( x => ! ! x ) ;
659- if ( typeof cb !== 'function' && typeof recursiveOrCallback === 'function' ) {
660- // Webpack 4 only has 3 parameters
661- cb = recursiveOrCallback ;
644+ return this . done . then (
645+ ( ) => {
646+ // This folder does not exist, but we need to give webpack a resource .
647+ // TODO: check if we can't just leave it as is (angularCoreModuleDir).
648+ result . resource = path . join ( this . _basePath , '$$_lazy_route_resource' ) ;
649+ // tslint:disable-next-line:no- any
650+ result . dependencies . forEach ( ( d : any ) => d . critical = false ) ;
651+ // tslint:disable-next-line:no-any
652+ result . resolveDependencies = ( _fs : any , options : any , callback : Callback ) => {
653+ const dependencies = Object . keys ( this . _lazyRoutes )
654+ . map ( ( key ) => {
655+ const modulePath = this . _lazyRoutes [ key ] ;
656+ const importPath = key . split ( '#' ) [ 0 ] ;
657+ if ( modulePath !== null ) {
658+ const name = importPath . replace ( / ( \. n g f a c t o r y ) ? \. ( j s | t s ) $ / , '' ) ;
659+
660+ return new this . _contextElementDependencyConstructor ( modulePath , name ) ;
661+ } else {
662+ return null ;
663+ }
664+ } )
665+ . filter ( x => ! ! x ) ;
666+
662667 if ( this . _options . nameLazyFiles ) {
663- resourceOrOptions . chunkName = '[request]' ;
668+ options . chunkName = '[request]' ;
664669 }
665- }
666- cb ( null , dependencies ) ;
667- } ;
668670
669- return callback ( undefined , result ) ;
670- } , ( ) => callback ( ) )
671- . catch ( err => callback ( err ) ) ;
671+ callback ( null , dependencies ) ;
672+ } ;
673+
674+ return result ;
675+ } ,
676+ ( ) => undefined ,
677+ ) ;
672678 } ) ;
673679 } ) ;
674680
675681 // Create and destroy forked type checker on watch mode.
676- compiler . hooks . watchRun . tapAsync ( 'angular-compiler' , ( _compiler : any , callback : any ) => {
682+ compiler . hooks . watchRun . tap ( 'angular-compiler' , ( ) => {
677683 if ( this . _forkTypeChecker && ! this . _typeCheckerProcess ) {
678684 this . _createForkedTypeChecker ( ) ;
679685 }
680- callback ( ) ;
681686 } ) ;
682687 compiler . hooks . watchClose . tap ( 'angular-compiler' , ( ) => this . _killForkedTypeChecker ( ) ) ;
683688
684689 // Remake the plugin on each compilation.
685- compiler . hooks . make . tapAsync (
686- 'angular-compiler' ,
687- ( compilation : any , cb : any ) => this . _make ( compilation , cb ) ,
688- ) ;
690+ compiler . hooks . make . tapPromise ( 'angular-compiler' , compilation => this . _make ( compilation ) ) ;
689691 compiler . hooks . invalid . tap ( 'angular-compiler' , ( ) => this . _firstRun = false ) ;
690- compiler . hooks . afterEmit . tapAsync ( 'angular-compiler' , ( compilation : any , cb : any ) => {
691- compilation . _ngToolsWebpackPluginInstance = null ;
692- cb ( ) ;
692+ compiler . hooks . afterEmit . tap ( 'angular-compiler' , compilation => {
693+ // tslint:disable-next-line:no-any
694+ ( compilation as any ) . _ngToolsWebpackPluginInstance = null ;
693695 } ) ;
694696 compiler . hooks . done . tap ( 'angular-compiler' , ( ) => {
695697 this . _donePromise = null ;
696698 } ) ;
697699
698- compiler . hooks . afterResolvers . tap ( 'angular-compiler' , ( compiler : any ) => {
699- compiler . hooks . normalModuleFactory . tap ( 'angular-compiler' , ( nmf : any ) => {
700+ compiler . hooks . afterResolvers . tap ( 'angular-compiler' , compiler => {
701+ compiler . hooks . normalModuleFactory . tap ( 'angular-compiler' , nmf => {
700702 // Virtual file system.
701703 // TODO: consider if it's better to remove this plugin and instead make it wait on the
702704 // VirtualFileSystemDecorator.
703705 // Wait for the plugin to be done when requesting `.ts` files directly (entry points), or
704706 // when the issuer is a `.ts` or `.ngfactory.js` file.
705- nmf . hooks . beforeResolve . tapAsync ( 'angular-compiler' , ( request : any , callback : any ) => {
706- if ( this . done
707- && ( request && ( request . request . endsWith ( '.ts' ) || request . request . endsWith ( '.tsx' ) )
708- || ( request && request . context . issuer
709- && / \. t s | n g f a c t o r y \. j s $ / . test ( request . context . issuer ) ) ) ) {
710- this . done . then ( ( ) => callback ( null , request ) , ( ) => callback ( null , request ) ) ;
711- } else {
712- callback ( null , request ) ;
713- }
714- } ) ;
715- } ) ;
716- } ) ;
707+ nmf . hooks . beforeResolve . tapPromise (
708+ 'angular-compiler' ,
709+ async ( request ?: NormalModuleFactoryRequest ) => {
710+ if ( this . done && request ) {
711+ const name = request . request ;
712+ const issuer = request . contextInfo . issuer ;
713+ if ( name . endsWith ( '.ts' ) || name . endsWith ( '.tsx' )
714+ || ( issuer && / \. t s | n g f a c t o r y \. j s $ / . test ( issuer ) ) ) {
715+ try {
716+ await this . done ;
717+ } catch { }
718+ }
719+ }
717720
718- compiler . hooks . normalModuleFactory . tap ( 'angular-compiler' , ( nmf : any ) => {
719- nmf . hooks . beforeResolve . tapAsync ( 'angular-compiler' , ( request : any , callback : any ) => {
720- resolveWithPaths (
721- request ,
722- callback ,
723- this . _compilerOptions ,
724- this . _compilerHost ,
725- this . _moduleResolutionCache ,
721+ return request ;
722+ } ,
726723 ) ;
727724 } ) ;
728725 } ) ;
726+
727+ compiler . hooks . normalModuleFactory . tap ( 'angular-compiler' , nmf => {
728+ nmf . hooks . beforeResolve . tapAsync (
729+ 'angular-compiler' ,
730+ ( request : NormalModuleFactoryRequest , callback : Callback < NormalModuleFactoryRequest > ) => {
731+ resolveWithPaths (
732+ request ,
733+ callback ,
734+ this . _compilerOptions ,
735+ this . _compilerHost ,
736+ this . _moduleResolutionCache ,
737+ ) ;
738+ } ,
739+ ) ;
740+ } ) ;
729741 }
730742
731- private _make ( compilation : any , cb : ( err ?: any , request ?: any ) => void ) {
743+ private async _make ( compilation : compilation . Compilation ) {
732744 time ( 'AngularCompilerPlugin._make' ) ;
733745 this . _emitSkipped = true ;
734- if ( compilation . _ngToolsWebpackPluginInstance ) {
735- return cb ( new Error ( 'An @ngtools/webpack plugin already exist for this compilation.' ) ) ;
746+ // tslint:disable-next-line:no-any
747+ if ( ( compilation as any ) . _ngToolsWebpackPluginInstance ) {
748+ throw new Error ( 'An @ngtools/webpack plugin already exist for this compilation.' ) ;
736749 }
737750
738751 // Set a private variable for this plugin instance.
739- compilation . _ngToolsWebpackPluginInstance = this ;
752+ // tslint:disable-next-line:no-any
753+ ( compilation as any ) . _ngToolsWebpackPluginInstance = this ;
740754
741755 // Update the resource loader with the new webpack compilation.
742756 this . _resourceLoader . update ( compilation ) ;
743757
744- this . _donePromise = Promise . resolve ( )
758+ return this . _donePromise = Promise . resolve ( )
745759 . then ( ( ) => this . _update ( ) )
746760 . then ( ( ) => {
747761 this . pushCompilationErrors ( compilation ) ;
748762 timeEnd ( 'AngularCompilerPlugin._make' ) ;
749- cb ( ) ;
750- } , ( err : any ) => {
763+ } , err => {
751764 compilation . errors . push ( err ) ;
752765 this . pushCompilationErrors ( compilation ) ;
753766 timeEnd ( 'AngularCompilerPlugin._make' ) ;
754- cb ( ) ;
755767 } ) ;
756768 }
757769
758- private pushCompilationErrors ( compilation : any ) {
770+ private pushCompilationErrors ( compilation : compilation . Compilation ) {
759771 compilation . errors . push ( ...this . _errors ) ;
760772 compilation . warnings . push ( ...this . _warnings ) ;
761773 this . _errors = [ ] ;
0 commit comments