@@ -13,7 +13,6 @@ import {
1313 LoaderOptions ,
1414 TSFiles ,
1515 TSInstance ,
16- TSInstances ,
1716 WebpackError ,
1817} from './interfaces' ;
1918import * as logger from './logger' ;
@@ -34,7 +33,8 @@ import {
3433} from './utils' ;
3534import { makeWatchRun } from './watch-run' ;
3635
37- const instances = { } as TSInstances ;
36+ const instances = new Map < string , TSInstance > ( ) ;
37+ const instancesBySolutionBuilderConfigs = new Map < FilePathKey , TSInstance > ( ) ;
3838
3939/**
4040 * The loader is executed once for each file seen by webpack. However, we need to keep
@@ -47,20 +47,26 @@ export function getTypeScriptInstance(
4747 loaderOptions : LoaderOptions ,
4848 loader : webpack . loader . LoaderContext
4949) : { instance ?: TSInstance ; error ?: WebpackError } {
50- if ( instances . hasOwnProperty ( loaderOptions . instance ) ) {
51- const instance = instances [ loaderOptions . instance ] ;
52- if ( ! instance . initialSetupPending ) {
53- ensureProgram ( instance ) ;
50+ const existing = instances . get ( loaderOptions . instance ) ;
51+ if ( existing ) {
52+ if ( ! existing . initialSetupPending ) {
53+ ensureProgram ( existing ) ;
5454 }
55- return { instance : instances [ loaderOptions . instance ] } ;
55+ return { instance : existing } ;
5656 }
5757
5858 const colors = new chalk . constructor ( { enabled : loaderOptions . colors } ) ;
5959 const log = logger . makeLogger ( loaderOptions , colors ) ;
6060 const compiler = getCompiler ( loaderOptions , log ) ;
6161
6262 if ( compiler . errorMessage !== undefined ) {
63- return { error : makeError ( colors . red ( compiler . errorMessage ) , undefined ) } ;
63+ return {
64+ error : makeError (
65+ loaderOptions ,
66+ colors . red ( compiler . errorMessage ) ,
67+ undefined
68+ ) ,
69+ } ;
6470 }
6571
6672 return successfulTypeScriptInstance (
@@ -121,13 +127,25 @@ function successfulTypeScriptInstance(
121127 const { message, file } = configFileAndPath . configFileError ;
122128 return {
123129 error : makeError (
130+ loaderOptions ,
124131 colors . red ( 'error while reading tsconfig.json:' + EOL + message ) ,
125132 file
126133 ) ,
127134 } ;
128135 }
129136
130137 const { configFilePath, configFile } = configFileAndPath ;
138+ const filePathKeyMapper = createFilePathKeyMapper ( compiler , loaderOptions ) ;
139+ if ( configFilePath && loaderOptions . projectReferences ) {
140+ const configFileKey = filePathKeyMapper ( configFilePath ) ;
141+ const existing = getExistingSolutionBuilderHost ( configFileKey ) ;
142+ if ( existing ) {
143+ // Reuse the instance if config file for project references is shared.
144+ instances . set ( loaderOptions . instance , existing ) ;
145+ return { instance : existing } ;
146+ }
147+ }
148+
131149 const basePath = loaderOptions . context || path . dirname ( configFilePath || '' ) ;
132150 const configParseResult = getConfigParseResult (
133151 compiler ,
@@ -151,6 +169,7 @@ function successfulTypeScriptInstance(
151169
152170 return {
153171 error : makeError (
172+ loaderOptions ,
154173 colors . red ( 'error while parsing tsconfig.json' ) ,
155174 configFilePath
156175 ) ,
@@ -174,12 +193,11 @@ function successfulTypeScriptInstance(
174193 filePath
175194 )
176195 : ( filePath : string ) => filePath ;
177- const filePathKeyMapper = createFilePathKeyMapper ( compiler , loaderOptions ) ;
178196
179197 if ( loaderOptions . transpileOnly ) {
180198 // quick return for transpiling
181199 // we do need to check for any issues with TS options though
182- const transpileInstance : TSInstance = ( instances [ loaderOptions . instance ] = {
200+ const transpileInstance : TSInstance = {
183201 compiler,
184202 compilerOptions,
185203 appendTsTsxSuffixesIfRequired,
@@ -198,8 +216,8 @@ function successfulTypeScriptInstance(
198216 configParseResult,
199217 log,
200218 filePathKeyMapper,
201- } ) ;
202-
219+ } ;
220+ instances . set ( loaderOptions . instance , transpileInstance ) ;
203221 return { instance : transpileInstance } ;
204222 }
205223
@@ -223,6 +241,7 @@ function successfulTypeScriptInstance(
223241 } catch ( exc ) {
224242 return {
225243 error : makeError (
244+ loaderOptions ,
226245 colors . red (
227246 `A file specified in tsconfig.json could not be found: ${ normalizedFilePath ! } `
228247 ) ,
@@ -231,7 +250,7 @@ function successfulTypeScriptInstance(
231250 } ;
232251 }
233252
234- const instance : TSInstance = ( instances [ loaderOptions . instance ] = {
253+ const instance : TSInstance = {
235254 compiler,
236255 compilerOptions,
237256 appendTsTsxSuffixesIfRequired,
@@ -249,11 +268,22 @@ function successfulTypeScriptInstance(
249268 configParseResult,
250269 log,
251270 filePathKeyMapper,
252- } ) ;
253-
271+ } ;
272+ instances . set ( loaderOptions . instance , instance ) ;
254273 return { instance } ;
255274}
256275
276+ function getExistingSolutionBuilderHost ( key : FilePathKey ) {
277+ const existing = instancesBySolutionBuilderConfigs . get ( key ) ;
278+ if ( existing ) return existing ;
279+ for ( const instance of instancesBySolutionBuilderConfigs . values ( ) ) {
280+ if ( instance . solutionBuilderHost ! . configFileInfo . has ( key ) ) {
281+ return instance ;
282+ }
283+ }
284+ return undefined ;
285+ }
286+
257287export function initializeInstance (
258288 loader : webpack . loader . LoaderContext ,
259289 instance : TSInstance
@@ -421,13 +451,17 @@ export function buildSolutionReferences(
421451 loader ,
422452 instance
423453 ) ;
424- instance . solutionBuilder = instance . compiler . createSolutionBuilderWithWatch (
454+ const solutionBuilder = instance . compiler . createSolutionBuilderWithWatch (
425455 instance . solutionBuilderHost ,
426456 instance . configParseResult . projectReferences ! . map ( ref => ref . path ) ,
427457 { verbose : true }
428458 ) ;
429- instance . solutionBuilder ! . build ( ) ;
459+ solutionBuilder . build ( ) ;
430460 ensureAllReferences ( instance ) ;
461+ instancesBySolutionBuilderConfigs . set (
462+ instance . filePathKeyMapper ( instance . configFilePath ! ) ,
463+ instance
464+ ) ;
431465 } else {
432466 instance . solutionBuilderHost . buildReferences ( ) ;
433467 }
0 commit comments