@@ -3,19 +3,21 @@ import * as child_process from "child_process";
33import * as semver from "semver" ;
44import { EventEmitter } from "events" ;
55import { performanceLog } from "../../common/decorators" ;
6- import { WEBPACK_COMPILATION_COMPLETE } from "../../constants" ;
6+ import { WEBPACK_COMPILATION_COMPLETE , WEBPACK_PLUGIN_NAME } from "../../constants" ;
77
88export class WebpackCompilerService extends EventEmitter implements IWebpackCompilerService {
99 private webpackProcesses : IDictionary < child_process . ChildProcess > = { } ;
1010 private expectedHash : string = null ;
1111
1212 constructor (
13+ private $errors : IErrors ,
1314 private $childProcess : IChildProcess ,
1415 public $hooksService : IHooksService ,
1516 public $hostInfo : IHostInfo ,
1617 private $logger : ILogger ,
1718 private $mobileHelper : Mobile . IMobileHelper ,
18- private $cleanupService : ICleanupService
19+ private $cleanupService : ICleanupService ,
20+ private $packageInstallationManager : IPackageInstallationManager
1921 ) { super ( ) ; }
2022
2123 public async compileWithWatch ( platformData : IPlatformData , projectData : IProjectData , prepareData : IPrepareData ) : Promise < any > {
@@ -27,67 +29,71 @@ export class WebpackCompilerService extends EventEmitter implements IWebpackComp
2729
2830 let isFirstWebpackWatchCompilation = true ;
2931 prepareData . watch = true ;
30- const childProcess = await this . startWebpackProcess ( platformData , projectData , prepareData ) ;
32+ try {
33+ const childProcess = await this . startWebpackProcess ( platformData , projectData , prepareData ) ;
3134
32- childProcess . on ( "message" , ( message : string | IWebpackEmitMessage ) => {
33- if ( message === "Webpack compilation complete." ) {
34- this . $logger . info ( "Webpack build done!" ) ;
35- resolve ( childProcess ) ;
36- }
35+ childProcess . on ( "message" , ( message : string | IWebpackEmitMessage ) => {
36+ if ( message === "Webpack compilation complete." ) {
37+ this . $logger . info ( "Webpack build done!" ) ;
38+ resolve ( childProcess ) ;
39+ }
3740
38- message = message as IWebpackEmitMessage ;
39- if ( message . emittedFiles ) {
40- if ( isFirstWebpackWatchCompilation ) {
41- isFirstWebpackWatchCompilation = false ;
41+ message = message as IWebpackEmitMessage ;
42+ if ( message . emittedFiles ) {
43+ if ( isFirstWebpackWatchCompilation ) {
44+ isFirstWebpackWatchCompilation = false ;
4245 this . expectedHash = message . hash ;
43- return ;
44- }
46+ return ;
47+ }
4548
46- let result ;
49+ let result ;
4750
48- if ( prepareData . hmr ) {
51+ if ( prepareData . hmr ) {
4952 result = this . getUpdatedEmittedFiles ( message . emittedFiles , message . chunkFiles , message . hash ) ;
50- } else {
51- result = { emittedFiles : message . emittedFiles , fallbackFiles : < string [ ] > [ ] , hash : "" } ;
53+ } else {
54+ result = { emittedFiles : message . emittedFiles , fallbackFiles : < string [ ] > [ ] , hash : "" } ;
55+ }
56+
57+ const files = result . emittedFiles
58+ . map ( ( file : string ) => path . join ( platformData . appDestinationDirectoryPath , "app" , file ) ) ;
59+ const fallbackFiles = result . fallbackFiles
60+ . map ( ( file : string ) => path . join ( platformData . appDestinationDirectoryPath , "app" , file ) ) ;
61+
62+ const data = {
63+ files,
64+ hasOnlyHotUpdateFiles : files . every ( f => f . indexOf ( "hot-update" ) > - 1 ) ,
65+ hmrData : {
66+ hash : result . hash ,
67+ fallbackFiles
68+ } ,
69+ platform : platformData . platformNameLowerCase
70+ } ;
71+
72+ if ( data . files . length ) {
73+ this . emit ( WEBPACK_COMPILATION_COMPLETE , data ) ;
74+ }
5275 }
76+ } ) ;
5377
54- const files = result . emittedFiles
55- . map ( ( file : string ) => path . join ( platformData . appDestinationDirectoryPath , "app" , file ) ) ;
56- const fallbackFiles = result . fallbackFiles
57- . map ( ( file : string ) => path . join ( platformData . appDestinationDirectoryPath , "app" , file ) ) ;
58-
59- const data = {
60- files,
61- hasOnlyHotUpdateFiles : files . every ( f => f . indexOf ( "hot-update" ) > - 1 ) ,
62- hmrData : {
63- hash : result . hash ,
64- fallbackFiles
65- } ,
66- platform : platformData . platformNameLowerCase
67- } ;
68-
69- if ( data . files . length ) {
70- this . emit ( WEBPACK_COMPILATION_COMPLETE , data ) ;
71- }
72- }
73- } ) ;
78+ childProcess . on ( "error" , ( err ) => {
79+ this . $logger . trace ( `Unable to start webpack process in watch mode. Error is: ${ err } ` ) ;
80+ delete this . webpackProcesses [ platformData . platformNameLowerCase ] ;
81+ reject ( err ) ;
82+ } ) ;
7483
75- childProcess . on ( "error" , ( err ) => {
76- this . $logger . trace ( `Unable to start webpack process in watch mode. Error is: ${ err } ` ) ;
77- delete this . webpackProcesses [ platformData . platformNameLowerCase ] ;
84+ childProcess . on ( "close" , async ( arg : any ) => {
85+ await this . $cleanupService . removeKillProcess ( childProcess . pid . toString ( ) ) ;
86+
87+ const exitCode = typeof arg === "number" ? arg : arg && arg . code ;
88+ this . $logger . trace ( `Webpack process exited with code ${ exitCode } when we expected it to be long living with watch.` ) ;
89+ const error = new Error ( `Executing webpack failed with exit code ${ exitCode } .` ) ;
90+ error . code = exitCode ;
91+ delete this . webpackProcesses [ platformData . platformNameLowerCase ] ;
92+ reject ( error ) ;
93+ } ) ;
94+ } catch ( err ) {
7895 reject ( err ) ;
79- } ) ;
80-
81- childProcess . on ( "close" , async ( arg : any ) => {
82- await this . $cleanupService . removeKillProcess ( childProcess . pid . toString ( ) ) ;
83-
84- const exitCode = typeof arg === "number" ? arg : arg && arg . code ;
85- this . $logger . trace ( `Webpack process exited with code ${ exitCode } when we expected it to be long living with watch.` ) ;
86- const error = new Error ( `Executing webpack failed with exit code ${ exitCode } .` ) ;
87- error . code = exitCode ;
88- delete this . webpackProcesses [ platformData . platformNameLowerCase ] ;
89- reject ( error ) ;
90- } ) ;
96+ }
9197 } ) ;
9298 }
9399
@@ -98,26 +104,30 @@ export class WebpackCompilerService extends EventEmitter implements IWebpackComp
98104 return ;
99105 }
100106
101- const childProcess = await this . startWebpackProcess ( platformData , projectData , prepareData ) ;
102- childProcess . on ( "error" , ( err ) => {
103- this . $logger . trace ( `Unable to start webpack process in non-watch mode. Error is: ${ err } ` ) ;
104- delete this . webpackProcesses [ platformData . platformNameLowerCase ] ;
107+ try {
108+ const childProcess = await this . startWebpackProcess ( platformData , projectData , prepareData ) ;
109+ childProcess . on ( "error" , ( err ) => {
110+ this . $logger . trace ( `Unable to start webpack process in non-watch mode. Error is: ${ err } ` ) ;
111+ delete this . webpackProcesses [ platformData . platformNameLowerCase ] ;
112+ reject ( err ) ;
113+ } ) ;
114+
115+ childProcess . on ( "close" , async ( arg : any ) => {
116+ await this . $cleanupService . removeKillProcess ( childProcess . pid . toString ( ) ) ;
117+
118+ delete this . webpackProcesses [ platformData . platformNameLowerCase ] ;
119+ const exitCode = typeof arg === "number" ? arg : arg && arg . code ;
120+ if ( exitCode === 0 ) {
121+ resolve ( ) ;
122+ } else {
123+ const error = new Error ( `Executing webpack failed with exit code ${ exitCode } .` ) ;
124+ error . code = exitCode ;
125+ reject ( error ) ;
126+ }
127+ } ) ;
128+ } catch ( err ) {
105129 reject ( err ) ;
106- } ) ;
107-
108- childProcess . on ( "close" , async ( arg : any ) => {
109- await this . $cleanupService . removeKillProcess ( childProcess . pid . toString ( ) ) ;
110-
111- delete this . webpackProcesses [ platformData . platformNameLowerCase ] ;
112- const exitCode = typeof arg === "number" ? arg : arg && arg . code ;
113- if ( exitCode === 0 ) {
114- resolve ( ) ;
115- } else {
116- const error = new Error ( `Executing webpack failed with exit code ${ exitCode } .` ) ;
117- error . code = exitCode ;
118- reject ( error ) ;
119- }
120- } ) ;
130+ }
121131 } ) ;
122132 }
123133
@@ -136,7 +146,7 @@ export class WebpackCompilerService extends EventEmitter implements IWebpackComp
136146 @performanceLog ( )
137147 private async startWebpackProcess ( platformData : IPlatformData , projectData : IProjectData , prepareData : IPrepareData ) : Promise < child_process . ChildProcess > {
138148 const envData = this . buildEnvData ( platformData . platformNameLowerCase , projectData , prepareData ) ;
139- const envParams = this . buildEnvCommandLineParams ( envData , platformData , prepareData ) ;
149+ const envParams = await this . buildEnvCommandLineParams ( envData , platformData , projectData , prepareData ) ;
140150 const additionalNodeArgs = semver . major ( process . version ) <= 8 ? [ "--harmony" ] : [ ] ;
141151
142152 const args = [
@@ -198,14 +208,22 @@ export class WebpackCompilerService extends EventEmitter implements IWebpackComp
198208 return envData ;
199209 }
200210
201- private buildEnvCommandLineParams ( envData : any , platformData : IPlatformData , prepareData : IPrepareData ) {
211+ private async buildEnvCommandLineParams ( envData : any , platformData : IPlatformData , projectData : IProjectData , prepareData : IPrepareData ) {
202212 const envFlagNames = Object . keys ( envData ) ;
203- const shouldSnapshot = prepareData . release && ! this . $hostInfo . isWindows && this . $mobileHelper . isAndroidPlatform ( platformData . normalizedPlatformName ) ;
204- if ( envData && envData . snapshot && ! shouldSnapshot ) {
205- this . $logger . warn ( "Stripping the snapshot flag. " +
206- "Bear in mind that snapshot is only available in release builds and " +
207- "is NOT available on Windows systems." ) ;
208- envFlagNames . splice ( envFlagNames . indexOf ( "snapshot" ) , 1 ) ;
213+ const canSnapshot = prepareData . release && this . $mobileHelper . isAndroidPlatform ( platformData . normalizedPlatformName ) ;
214+ if ( envData && envData . snapshot ) {
215+ if ( ! canSnapshot ) {
216+ this . $logger . warn ( "Stripping the snapshot flag. " +
217+ "Bear in mind that snapshot is only available in Android release builds." ) ;
218+ envFlagNames . splice ( envFlagNames . indexOf ( "snapshot" ) , 1 ) ;
219+ } else if ( this . $hostInfo . isWindows ) {
220+ const minWebpackPluginWithWinSnapshotsVersion = "1.3.0" ;
221+ const installedWebpackPluginVersion = await this . $packageInstallationManager . getInstalledDependencyVersion ( WEBPACK_PLUGIN_NAME , projectData . projectDir ) ;
222+ const hasWebpackPluginWithWinSnapshotsSupport = ! ! installedWebpackPluginVersion ? semver . gte ( installedWebpackPluginVersion , minWebpackPluginWithWinSnapshotsVersion ) : true ;
223+ if ( ! hasWebpackPluginWithWinSnapshotsSupport ) {
224+ this . $errors . fail ( `In order to generate Snapshots on Windows, please upgrade your Webpack plugin version (npm i nativescript-dev-webpack@latest).` ) ;
225+ }
226+ }
209227 }
210228
211229 const args : any [ ] = [ ] ;
0 commit comments