@@ -102,13 +102,26 @@ export function sentryOrchestrionPlugin(options: SentryOrchestrionPluginOptions
102102 const codeTransformerArray : UnknownPlugin [ ] = Array . isArray ( codeTransformerPlugins )
103103 ? codeTransformerPlugins
104104 : [ codeTransformerPlugins ] ;
105+ const serverCodeTransformerArray = codeTransformerArray . map ( plugin => serverEnvironmentOnly ( plugin ) ) ;
105106 return [
106107 bundlerMarkerPlugin ( ) ,
107108 ...( options . registerIntegrations ? [ registerIntegrationsPlugin ( ) ] : [ ] ) ,
108- ...codeTransformerArray ,
109+ ...serverCodeTransformerArray ,
109110 ] ;
110111}
111112
113+ /** Keeps environment-aware Vite builds from transforming client bundles. */
114+ function serverEnvironmentOnly ( plugin : UnknownPlugin ) : UnknownPlugin {
115+ const applyToEnvironment = plugin . applyToEnvironment ;
116+ return {
117+ ...plugin ,
118+ applyToEnvironment ( this : unknown , environment : { config ?: { consumer ?: string } } ) : unknown {
119+ if ( environment . config ?. consumer === 'client' ) return false ;
120+ return applyToEnvironment ?. call ( this , environment ) ?? true ;
121+ } ,
122+ } ;
123+ }
124+
112125/**
113126 * Builds the `injectDiagnostics` callback for the code transformer: it records
114127 * the packages the transformer actually transformed — and those whose transform
@@ -193,9 +206,10 @@ function registerIntegrationsPlugin(): UnknownPlugin {
193206
194207 // `serve` (vite dev) vs `build`; drives entry detection in `transform`.
195208 let command = 'build' ;
196- // Dev only: environments the registration import has already been injected
197- // into, so each is injected exactly once (into its first source module).
198- const injectedServeEnvironments = new Set < string > ( ) ;
209+ // Dev only: records which source module receives registration in each
210+ // environment. Re-transforming that module must inject again because HMR can
211+ // start a fresh isolate from the newly transformed output.
212+ const injectedServeModules = new Map < string , string > ( ) ;
199213
200214 function injectRegisterImport ( code : string ) : { code : string ; map : unknown } | null {
201215 if ( code . includes ( REGISTER_MODULE_ID ) ) return null ;
@@ -252,8 +266,9 @@ function registerIntegrationsPlugin(): UnknownPlugin {
252266 // pre-bundled deps, node_modules source, and virtual modules so the import
253267 // lands in the user's entry, not an incidental early module.
254268 const environment = this ?. environment ?. name ?? '' ;
255- if ( injectedServeEnvironments . has ( environment ) ) return null ;
256269 const cleanId = id . split ( '?' ) [ 0 ] ?? id ;
270+ const injectedModule = injectedServeModules . get ( environment ) ;
271+ if ( injectedModule && injectedModule !== cleanId ) return null ;
257272 if (
258273 id . startsWith ( '\0' ) ||
259274 cleanId . includes ( '/node_modules/' ) ||
@@ -263,7 +278,7 @@ function registerIntegrationsPlugin(): UnknownPlugin {
263278 return null ;
264279 }
265280 const result = injectRegisterImport ( code ) ;
266- if ( result ) injectedServeEnvironments . add ( environment ) ;
281+ if ( result ) injectedServeModules . set ( environment , cleanId ) ;
267282 return result ;
268283 } ,
269284 } ;
@@ -276,9 +291,18 @@ function bundlerMarkerPlugin(): UnknownPlugin {
276291 '' ,
277292 ] . join ( '\n' ) ;
278293
294+ let command = 'build' ;
295+ const injectedServeModules = new Map < string , string > ( ) ;
296+
279297 return {
280298 name : 'sentry-orchestrion-marker' ,
281299 enforce : 'pre' as const ,
300+ applyToEnvironment ( environment : { config ?: { consumer ?: string } } ) : boolean {
301+ return environment . config ?. consumer !== 'client' ;
302+ } ,
303+ configResolved ( config : { command : string } ) : void {
304+ command = config . command ;
305+ } ,
282306 config ( ) : { ssr : { noExternal : string [ ] } } {
283307 // Force-bundle every instrumented package so the code transform actually
284308 // sees its source. Vite externalizes dependencies in SSR builds by
@@ -321,8 +345,35 @@ function bundlerMarkerPlugin(): UnknownPlugin {
321345 } ,
322346 } ;
323347 } ,
324- renderChunk ( code : string , chunk : { isEntry : boolean } ) : { code : string ; map : unknown } | null {
325- if ( ! chunk . isEntry ) return null ;
348+ transform (
349+ this : { environment ?: { name ?: string ; config ?: { consumer ?: string } } } | undefined ,
350+ code : string ,
351+ id : string ,
352+ ) : { code : string ; map : unknown } | null {
353+ if ( command !== 'serve' || this ?. environment ?. config ?. consumer === 'client' ) return null ;
354+ const cleanId = id . split ( '?' ) [ 0 ] ?? id ;
355+ const environment = this ?. environment ?. name ?? '' ;
356+ const injectedModule = injectedServeModules . get ( environment ) ;
357+ if ( injectedModule && injectedModule !== cleanId ) return null ;
358+ if (
359+ id . startsWith ( '\0' ) ||
360+ cleanId . includes ( '/node_modules/' ) ||
361+ cleanId . includes ( '/.vite/' ) ||
362+ ! / \. [ c m ] ? [ j t ] s x ? $ / . test ( cleanId )
363+ ) {
364+ return null ;
365+ }
366+ injectedServeModules . set ( environment , cleanId ) ;
367+ const ms = new MagicString ( code ) ;
368+ ms . prepend ( banner ) ;
369+ return { code : ms . toString ( ) , map : ms . generateMap ( { hires : true } ) } ;
370+ } ,
371+ renderChunk (
372+ this : { environment ?: { config ?: { consumer ?: string } } } | undefined ,
373+ code : string ,
374+ chunk : { isEntry : boolean } ,
375+ ) : { code : string ; map : unknown } | null {
376+ if ( ! chunk . isEntry || this ?. environment ?. config ?. consumer === 'client' ) return null ;
326377 // Prepend via magic-string so the entry chunk's sourcemap stays aligned —
327378 // returning `map: null` here would shift every mapping by the banner's
328379 // line count and misattribute server stack traces.
0 commit comments