@@ -49,6 +49,9 @@ interface TSInstances {
4949
5050var instances = < TSInstances > { } ;
5151
52+ // Take TypeScript errors, parse them and "pretty-print" to a passed-in function
53+ // The passed-in function can either console.log them or add them to webpack's
54+ // list of errors
5255function handleErrors ( diagnostics : typescript . Diagnostic [ ] , compiler : typeof typescript , outputFn : ( prettyMessage : string , rawMessage : string , loc : { line : number , character : number } ) => any ) {
5356 diagnostics . forEach ( diagnostic => {
5457 var messageText = compiler . flattenDiagnosticMessageText ( diagnostic . messageText , os . EOL ) ;
@@ -66,6 +69,8 @@ function handleErrors(diagnostics: typescript.Diagnostic[], compiler: typeof typ
6669 } ) ;
6770}
6871
72+ // The tsconfig.json is found using the same method as `tsc`, starting in the current directory
73+ // and continuing up the parent directory chain.
6974function findConfigFile ( compiler : typeof typescript , searchPath : string , configFileName : string ) : string {
7075 while ( true ) {
7176 var fileName = path . join ( searchPath , configFileName ) ;
@@ -81,6 +86,11 @@ function findConfigFile(compiler: typeof typescript, searchPath: string, configF
8186 return undefined ;
8287}
8388
89+ // The loader is executed once for each file seen by webpack. However, we need to keep
90+ // a persistent instance of TypeScript that contains all of the files in the program
91+ // along with definition files and options. This function either creates an instance
92+ // or returns the existing one. Multiple instances are possible by using the
93+ // `instance` property.
8494function ensureTypeScriptInstance ( options : Options , loader : any ) : TSInstance {
8595
8696 function log ( ...messages : string [ ] ) : void {
@@ -104,6 +114,7 @@ function ensureTypeScriptInstance(options: Options, loader: any): TSInstance {
104114 module : typescript . ModuleKind . CommonJS
105115 } ;
106116
117+ // Load any available tsconfig.json file
107118 var filesToLoad = [ ] ;
108119 var configFilePath = findConfigFile ( compiler , path . dirname ( loader . resourcePath ) , options . configFileName ) ;
109120 if ( configFilePath ) {
@@ -127,8 +138,8 @@ function ensureTypeScriptInstance(options: Options, loader: any): TSInstance {
127138
128139 var libFileName = 'lib.d.ts' ;
129140
141+ // Special handling for ES6 targets
130142 if ( compilerOptions . target == typescript . ScriptTarget . ES6 ) {
131- // Special handling for ES6 targets
132143 compilerOptions . module = typescript . ModuleKind . None ;
133144 libFileName = 'lib.es6.d.ts' ;
134145 }
@@ -137,6 +148,7 @@ function ensureTypeScriptInstance(options: Options, loader: any): TSInstance {
137148 filesToLoad . push ( path . join ( path . dirname ( require . resolve ( 'typescript' ) ) , libFileName ) ) ;
138149 }
139150
151+ // Load initial files (core lib files, any files specified in tsconfig.json)
140152 filesToLoad . forEach ( filePath => {
141153 filePath = path . normalize ( filePath ) ;
142154 files [ filePath ] = {
@@ -145,13 +157,16 @@ function ensureTypeScriptInstance(options: Options, loader: any): TSInstance {
145157 }
146158 } ) ;
147159
160+ // Create the TypeScript language service
148161 var servicesHost = {
149162 getScriptFileNames : ( ) => Object . keys ( files ) ,
150163 getScriptVersion : fileName => {
151164 fileName = path . normalize ( fileName ) ;
152165 return files [ fileName ] && files [ fileName ] . version . toString ( ) ;
153166 } ,
154167 getScriptSnapshot : fileName => {
168+ // This is called any time TypeScript needs a file's text
169+ // We either load from memory or from disk
155170 fileName = path . normalize ( fileName ) ;
156171 var file = files [ fileName ] ;
157172
@@ -243,17 +258,20 @@ function loader(contents) {
243258 file = instance . files [ filePath ] ,
244259 langService = instance . languageService ;
245260
261+ // Update TypeScript with the new file contents
246262 if ( ! file ) {
247263 file = instance . files [ filePath ] = < TSFile > { version : 0 } ;
248264 }
249265
250266 file . text = contents ;
251267 file . version ++ ;
252268
269+ // Make this file dependent on *all* definition files in the program
253270 this . clearDependencies ( ) ;
254271 this . addDependency ( filePath ) ;
255272 Object . keys ( instance . files ) . filter ( filePath => ! ! filePath . match ( / \. d \. t s $ / ) ) . forEach ( this . addDependency . bind ( this ) ) ;
256273
274+ // Emit Javascript
257275 var output = langService . getEmitOutput ( filePath ) ;
258276 handleErrors (
259277 langService . getSyntacticDiagnostics ( filePath ) . concat ( langService . getSemanticDiagnostics ( filePath ) ) ,
@@ -283,6 +301,9 @@ function loader(contents) {
283301 contents = output . outputFiles [ 0 ] . text ;
284302 }
285303
304+ // Make sure webpack is aware that even though the emitted JavaScript may be the same as
305+ // a previously cached version the TypeScript may be different and therefore should be
306+ // treated as new
286307 this . _module . meta [ 'tsLoaderFileVersion' ] = file . version ;
287308
288309 callback ( null , contents , sourceMap )
0 commit comments