@@ -38,6 +38,7 @@ import {
38
38
import type { PluginContainer } from '../server/pluginContainer'
39
39
import { createPluginContainer } from '../server/pluginContainer'
40
40
import { transformGlobImport } from '../plugins/importMetaGlob'
41
+ import { loadTsconfigJsonForFile } from '../plugins/esbuild'
41
42
42
43
type ResolveIdOptions = Parameters < PluginContainer [ 'resolveId' ] > [ 2 ]
43
44
@@ -217,6 +218,21 @@ async function prepareEsbuildScanner(
217
218
const { plugins = [ ] , ...esbuildOptions } =
218
219
config . optimizeDeps ?. esbuildOptions ?? { }
219
220
221
+ // The plugin pipeline automatically loads the closest tsconfig.json.
222
+ // But esbuild doesn't support reading tsconfig.json if the plugin has resolved the path (https://github.com/evanw/esbuild/issues/2265).
223
+ // Due to syntax incompatibilities between the experimental decorators in TypeScript and TC39 decorators,
224
+ // we cannot simply set `"experimentalDecorators": true` or `false`. (https://github.com/vitejs/vite/pull/15206#discussion_r1417414715)
225
+ // Therefore, we use the closest tsconfig.json from the root to make it work in most cases.
226
+ let tsconfigRaw = esbuildOptions . tsconfigRaw
227
+ if ( ! tsconfigRaw && ! esbuildOptions . tsconfig ) {
228
+ const tsconfigResult = await loadTsconfigJsonForFile (
229
+ path . join ( config . root , '_dummy.js' ) ,
230
+ )
231
+ if ( tsconfigResult . compilerOptions ?. experimentalDecorators ) {
232
+ tsconfigRaw = { compilerOptions : { experimentalDecorators : true } }
233
+ }
234
+ }
235
+
220
236
return await esbuild . context ( {
221
237
absWorkingDir : process . cwd ( ) ,
222
238
write : false ,
@@ -229,6 +245,7 @@ async function prepareEsbuildScanner(
229
245
logLevel : 'silent' ,
230
246
plugins : [ ...plugins , plugin ] ,
231
247
...esbuildOptions ,
248
+ tsconfigRaw,
232
249
} )
233
250
}
234
251
0 commit comments