@@ -64,6 +64,18 @@ interface CharacteristicsGermaneToCaching {
6464  configFilePath : string  |  undefined 
6565} 
6666
67+ function  shouldSkipBabel ( 
68+   transformMode : 'standalone'  |  'default' , 
69+   configFilePath : string  |  undefined , 
70+   hasReactCompiler : boolean 
71+ )  { 
72+   return  ( 
73+     transformMode  ===  'standalone'  && 
74+     configFilePath  ==  null  && 
75+     ! hasReactCompiler 
76+   ) 
77+ } 
78+ 
6779const  fileExtensionRegex  =  / \. ( [ a - z ] + ) $ / 
6880async  function  getCacheCharacteristics ( 
6981  loaderOptions : NextBabelLoaderOptions , 
@@ -91,19 +103,39 @@ async function getCacheCharacteristics(
91103  const  hasModuleExports  =  source . indexOf ( 'module.exports' )  !==  - 1 
92104  const  fileExt  =  fileExtensionRegex . exec ( filename ) ?. [ 1 ]  ||  'unknown' 
93105
106+   let  { 
107+     reactCompilerPlugins, 
108+     reactCompilerExclude, 
109+     configFile : configFilePath , 
110+     transformMode, 
111+   }  =  loaderOptions 
112+ 
94113  // Compute `hasReactCompiler` as part of the cache characteristics / key, 
95114  // rather than inside of `getFreshConfig`: 
96115  // - `isReactCompilerRequired` depends on the file contents 
97116  // - `node_modules` and `reactCompilerExclude` depend on the file path, which 
98117  //   isn't part of the cache characteristics 
99-   let  {  reactCompilerPlugins,  reactCompilerExclude }  =  loaderOptions 
100-   reactCompilerPlugins  ??=  [ ] 
101-   const  hasReactCompiler  = 
118+   let  hasReactCompiler  = 
119+     reactCompilerPlugins  !=  null  && 
102120    reactCompilerPlugins . length  !==  0  && 
103121    ! loaderOptions . isServer  && 
104122    ! / [ / \\ ] n o d e _ m o d u l e s [ / \\ ] / . test ( filename )  && 
105-     ! reactCompilerExclude ?.( filename )  && 
106-     ( await  isReactCompilerRequired ( filename ) ) 
123+     // Assumption: `reactCompilerExclude` is cheap because it should only 
124+     // operate on the file path and *not* the file contents (it's sync) 
125+     ! reactCompilerExclude ?.( filename ) 
126+ 
127+   // `isReactCompilerRequired` is expensive to run (parses/visits with SWC), so 
128+   // only run it if there's a good chance we might be able to skip calling Babel 
129+   // entirely (speculatively call `shouldSkipBabel`). 
130+   // 
131+   // Otherwise, we can let react compiler handle this logic for us. It should 
132+   // behave equivalently. 
133+   if  ( 
134+     hasReactCompiler  && 
135+     shouldSkipBabel ( transformMode ,  configFilePath ,  /*hasReactCompiler*/  false ) 
136+   )  { 
137+     hasReactCompiler  &&=  await  isReactCompilerRequired ( filename ) 
138+   } 
107139
108140  return  { 
109141    isStandalone, 
@@ -113,7 +145,7 @@ async function getCacheCharacteristics(
113145    hasModuleExports, 
114146    hasReactCompiler, 
115147    fileExt, 
116-     configFilePath :  loaderOptions . configFile , 
148+     configFilePath, 
117149  } 
118150} 
119151
@@ -336,8 +368,9 @@ async function getFreshConfig(
336368  const  {  hasReactCompiler,  configFilePath,  fileExt }  =  cacheCharacteristics 
337369
338370  let  customConfig  =  configFilePath  &&  getCustomBabelConfig ( configFilePath ) 
339-   if  ( transformMode  ===  'standalone'  &&  ! customConfig  &&  ! hasReactCompiler )  { 
340-     // Optimization: There's nothing useful to do, bail out and skip babel on this file 
371+   if  ( shouldSkipBabel ( transformMode ,  configFilePath ,  hasReactCompiler ) )  { 
372+     // Optimization: There's nothing useful to do, bail out and skip babel on 
373+     // this file 
341374    return  null 
342375  } 
343376
0 commit comments