@@ -3,6 +3,8 @@ import type { ParserOptions, TransformOptions, types as t } from '@babel/core'
33import * as babel from '@babel/core'
44import { createFilter , normalizePath } from 'vite'
55import type { Plugin , PluginOption , ResolvedConfig } from 'vite'
6+ import MagicString from 'magic-string'
7+ import type { SourceMap } from 'magic-string'
68import {
79 addRefreshWrapper ,
810 isRefreshBoundary ,
@@ -88,11 +90,14 @@ declare module 'vite' {
8890 }
8991}
9092
93+ const prependReactImportCode = "import React from 'react'; "
94+
9195export default function viteReact ( opts : Options = { } ) : PluginOption [ ] {
9296 // Provide default values for Rollup compat.
9397 let devBase = '/'
9498 let resolvedCacheDir : string
9599 let filter = createFilter ( opts . include , opts . exclude )
100+ let needHiresSourcemap = false
96101 let isProduction = true
97102 let projectRoot = process . cwd ( )
98103 let skipFastRefresh = opts . fastRefresh === false
@@ -135,6 +140,8 @@ export default function viteReact(opts: Options = {}): PluginOption[] {
135140 filter = createFilter ( opts . include , opts . exclude , {
136141 resolve : projectRoot
137142 } )
143+ needHiresSourcemap =
144+ config . command === 'build' && ! ! config . build . sourcemap
138145 isProduction = config . isProduction
139146 skipFastRefresh ||= isProduction || config . command === 'build'
140147
@@ -217,6 +224,7 @@ export default function viteReact(opts: Options = {}): PluginOption[] {
217224 }
218225
219226 let ast : t . File | null | undefined
227+ let prependReactImport = false
220228 if ( ! isProjectFile || isJSX ) {
221229 if ( useAutomaticRuntime ) {
222230 // By reverse-compiling "React.createElement" calls into JSX,
@@ -261,11 +269,23 @@ export default function viteReact(opts: Options = {}): PluginOption[] {
261269 // Even if the automatic JSX runtime is not used, we can still
262270 // inject the React import for .jsx and .tsx modules.
263271 if ( ! skipReactImport && ! importReactRE . test ( code ) ) {
264- code = `import React from 'react'; ` + code
272+ prependReactImport = true
265273 }
266274 }
267275 }
268276
277+ let inputMap : SourceMap | undefined
278+ if ( prependReactImport ) {
279+ if ( needHiresSourcemap ) {
280+ const s = new MagicString ( code )
281+ s . prepend ( prependReactImportCode )
282+ code = s . toString ( )
283+ inputMap = s . generateMap ( { hires : true , source : id } )
284+ } else {
285+ code = prependReactImportCode + code
286+ }
287+ }
288+
269289 // Plugins defined through this Vite plugin are only applied
270290 // to modules within the project root, but "babel.config.js"
271291 // files can define plugins that need to be applied to every
@@ -275,10 +295,11 @@ export default function viteReact(opts: Options = {}): PluginOption[] {
275295 ! babelOptions . configFile &&
276296 ! ( isProjectFile && babelOptions . babelrc )
277297
298+ // Avoid parsing if no plugins exist.
278299 if ( shouldSkip ) {
279- // Avoid parsing if no plugins exist.
280300 return {
281- code
301+ code,
302+ map : inputMap ?? null
282303 }
283304 }
284305
@@ -326,7 +347,7 @@ export default function viteReact(opts: Options = {}): PluginOption[] {
326347 plugins,
327348 sourceMaps : true ,
328349 // Vite handles sourcemap flattening
329- inputSourceMap : false as any
350+ inputSourceMap : inputMap ?? ( false as any )
330351 } )
331352
332353 if ( result ) {
0 commit comments