1- import  {  BuildContext ,  BuildState ,  BuildUpdateMessage  }  from  './util/interfaces' ; 
1+ import  {  FILE_CHANGE_EVENT ,  FILE_DELETE_EVENT  }  from  './util/constants' ; 
2+ import  {  BuildContext ,  BuildState ,  BuildUpdateMessage ,  ChangedFile  }  from  './util/interfaces' ; 
23import  {  BuildError  }  from  './util/errors' ; 
4+ import  {  readFileAsync  }  from  './util/helpers' ; 
35import  {  bundle ,  bundleUpdate  }  from  './bundle' ; 
46import  {  clean  }  from  './clean' ; 
57import  {  copy  }  from  './copy' ; 
@@ -121,7 +123,7 @@ function buildDev(context: BuildContext) {
121123} 
122124
123125
124- export  function  buildUpdate ( event :  string ,   filePath :  string ,  context : BuildContext )  { 
126+ export  function  buildUpdate ( changedFiles :  ChangedFile [ ] ,  context : BuildContext )  { 
125127 return  new  Promise ( resolve  =>  { 
126128 const  logger  =  new  Logger ( 'build' ) ; 
127129
@@ -151,13 +153,20 @@ export function buildUpdate(event: string, filePath: string, context: BuildConte
151153 // this one is useful when only a sass changed happened 
152154 // and the webpack only needs to livereload the css 
153155 // but does not need to do a full page refresh 
154-  emit ( EventType . FileChange ,  resolveValue . changedFile ) ; 
156+  emit ( EventType . FileChange ,  resolveValue . changedFiles ) ; 
155157 } 
156158
157-  if  ( filePath . endsWith ( '.ts' ) )  { 
159+  let  requiresLintUpdate  =  false ; 
160+  for  ( const  changedFile  of  changedFiles )  { 
161+  if  ( changedFile . ext  ===  '.ts'  &&  changedFile . event  ===  'ch' )  { 
162+  requiresLintUpdate  =  true ; 
163+  break ; 
164+  } 
165+  } 
166+  if  ( requiresLintUpdate )  { 
158167 // a ts file changed, so let's lint it too, however 
159168 // this task should run as an after thought 
160-  lintUpdate ( event ,   filePath ,  context ) ; 
169+  lintUpdate ( changedFiles ,  context ) ; 
161170 } 
162171
163172 logger . finish ( 'green' ,  true ) ; 
@@ -170,16 +179,16 @@ export function buildUpdate(event: string, filePath: string, context: BuildConte
170179
171180 // kick off all the build tasks 
172181 // and the tasks that can run parallel to all the build tasks 
173-  const  buildTasksPromise  =  buildUpdateTasks ( event ,   filePath ,  context ) ; 
174-  const  parallelTasksPromise  =  buildUpdateParallelTasks ( event ,   filePath ,  context ) ; 
182+  const  buildTasksPromise  =  buildUpdateTasks ( changedFiles ,  context ) ; 
183+  const  parallelTasksPromise  =  buildUpdateParallelTasks ( changedFiles ,  context ) ; 
175184
176185 // whether it was resolved or rejected, we need to do the same thing 
177186 buildTasksPromise 
178187 . then ( buildTasksDone ) 
179188 . catch ( ( )  =>  { 
180189 buildTasksDone ( { 
181190 requiresAppReload : false , 
182-  changedFile :  filePath 
191+  changedFiles :  changedFiles 
183192 } ) ; 
184193 } ) ; 
185194 } ) ; 
@@ -189,18 +198,21 @@ export function buildUpdate(event: string, filePath: string, context: BuildConte
189198 * Collection of all the build tasks than need to run 
190199 * Each task will only run if it's set with eacn BuildState. 
191200 */ 
192- function  buildUpdateTasks ( event :  string ,   filePath :  string ,  context : BuildContext )  { 
201+ function  buildUpdateTasks ( changedFiles :  ChangedFile [ ] ,  context : BuildContext )  { 
193202 const  resolveValue : BuildTaskResolveValue  =  { 
194203 requiresAppReload : false , 
195-  changedFile :  filePath 
204+  changedFiles :  [ ] 
196205 } ; 
197206
198207 return  Promise . resolve ( ) 
208+  . then ( ( )  =>  { 
209+  return  loadFiles ( changedFiles ,  context ) ; 
210+  } ) 
199211 . then ( ( )  =>  { 
200212 // TEMPLATE 
201213 if  ( context . templateState  ===  BuildState . RequiresUpdate )  { 
202214 resolveValue . requiresAppReload  =  true ; 
203-  return  templateUpdate ( event ,   filePath ,  context ) ; 
215+  return  templateUpdate ( changedFiles ,  context ) ; 
204216 } 
205217 // no template updates required 
206218 return  Promise . resolve ( ) ; 
@@ -213,7 +225,7 @@ function buildUpdateTasks(event: string, filePath: string, context: BuildContext
213225 // we've already had a successful transpile once, only do an update 
214226 // not that we've also already started a transpile diagnostics only 
215227 // build that only needs to be completed by the end of buildUpdate 
216-  return  transpileUpdate ( event ,   filePath ,  context ) ; 
228+  return  transpileUpdate ( changedFiles ,  context ) ; 
217229
218230 }  else  if  ( context . transpileState  ===  BuildState . RequiresBuild )  { 
219231 // run the whole transpile 
@@ -229,7 +241,7 @@ function buildUpdateTasks(event: string, filePath: string, context: BuildContext
229241 if  ( context . bundleState  ===  BuildState . RequiresUpdate )  { 
230242 // we need to do a bundle update 
231243 resolveValue . requiresAppReload  =  true ; 
232-  return  bundleUpdate ( event ,   filePath ,  context ) ; 
244+  return  bundleUpdate ( changedFiles ,  context ) ; 
233245
234246 }  else  if  ( context . bundleState  ===  BuildState . RequiresBuild )  { 
235247 // we need to do a full bundle build 
@@ -244,14 +256,30 @@ function buildUpdateTasks(event: string, filePath: string, context: BuildContext
244256 // SASS 
245257 if  ( context . sassState  ===  BuildState . RequiresUpdate )  { 
246258 // we need to do a sass update 
247-  return  sassUpdate ( event ,  filePath ,  context ) . then ( outputCssFile  =>  { 
248-  resolveValue . changedFile  =  outputCssFile ; 
259+  return  sassUpdate ( changedFiles ,  context ) . then ( outputCssFile  =>  { 
260+  const  changedFile : ChangedFile  =  { 
261+  event : FILE_CHANGE_EVENT , 
262+  ext : '.css' , 
263+  filePath : outputCssFile 
264+  } ; 
265+ 
266+  context . fileCache . set ( outputCssFile ,  {  path : outputCssFile ,  content : outputCssFile } ) ; 
267+ 
268+  resolveValue . changedFiles . push ( changedFile ) ; 
249269 } ) ; 
250270
251271 }  else  if  ( context . sassState  ===  BuildState . RequiresBuild )  { 
252272 // we need to do a full sass build 
253273 return  sass ( context ) . then ( outputCssFile  =>  { 
254-  resolveValue . changedFile  =  outputCssFile ; 
274+  const  changedFile : ChangedFile  =  { 
275+  event : FILE_CHANGE_EVENT , 
276+  ext : '.css' , 
277+  filePath : outputCssFile 
278+  } ; 
279+ 
280+  context . fileCache . set ( outputCssFile ,  {  path : outputCssFile ,  content : outputCssFile } ) ; 
281+ 
282+  resolveValue . changedFiles . push ( changedFile ) ; 
255283 } ) ; 
256284 } 
257285 // no sass build required 
@@ -262,17 +290,37 @@ function buildUpdateTasks(event: string, filePath: string, context: BuildContext
262290 } ) ; 
263291} 
264292
293+ function  loadFiles ( changedFiles : ChangedFile [ ] ,  context : BuildContext )  { 
294+  // UPDATE IN-MEMORY FILE CACHE 
295+  let  promises : Promise < any > [ ]  =  [ ] ; 
296+  for  ( const  changedFile  of  changedFiles )  { 
297+  if  ( changedFile . event  ===  FILE_DELETE_EVENT )  { 
298+  // remove from the cache on delete 
299+  context . fileCache . remove ( changedFile . filePath ) ; 
300+  }  else  { 
301+  // load the latest since the file changed 
302+  const  promise  =  readFileAsync ( changedFile . filePath ) ; 
303+  promises . push ( promise ) ; 
304+  promise . then ( ( content : string )  =>  { 
305+  context . fileCache . set ( changedFile . filePath ,  {  path : changedFile . filePath ,  content : content } ) ; 
306+  } ) ; 
307+  } 
308+  } 
309+ 
310+  return  Promise . all ( promises ) ; 
311+ } 
312+ 
265313interface  BuildTaskResolveValue  { 
266314 requiresAppReload : boolean ; 
267-  changedFile :  string ; 
315+  changedFiles :  ChangedFile [ ] ; 
268316} 
269317
270318/** 
271319 * parallelTasks are for any tasks that can run parallel to the entire 
272320 * build, but we still need to make sure they've completed before we're 
273321 * all done, it's also possible there are no parallelTasks at all 
274322 */ 
275- function  buildUpdateParallelTasks ( event :  string ,   filePath :  string ,  context : BuildContext )  { 
323+ function  buildUpdateParallelTasks ( changedFiles :  ChangedFile [ ] ,  context : BuildContext )  { 
276324 const  parallelTasks : Promise < any > [ ]  =  [ ] ; 
277325
278326 if  ( context . transpileState  ===  BuildState . RequiresUpdate )  { 
0 commit comments