11import path from 'node:path'
22import MagicString from 'magic-string'
3- import type { EmittedAsset , OutputChunk } from 'rollup'
3+ import type { OutputChunk } from 'rollup'
44import type { ResolvedConfig } from '../config'
55import type { Plugin } from '../plugin'
66import type { ViteDevServer } from '../server'
@@ -14,9 +14,11 @@ import {
1414import { cleanUrl } from '../../shared/utils'
1515import { fileToUrl } from './asset'
1616
17+ type WorkerBundleAsset = { fileName : string ; source : string | Uint8Array }
18+
1719interface WorkerCache {
1820 // save worker all emit chunk avoid rollup make the same asset unique.
19- assets : Map < string , EmittedAsset >
21+ assets : Map < string , WorkerBundleAsset >
2022
2123 // worker bundle don't deps on any more worker runtime info an id only had a result.
2224 // save worker bundled file id to avoid repeated execution of bundles
@@ -38,11 +40,10 @@ const workerCache = new WeakMap<ResolvedConfig, WorkerCache>()
3840
3941function saveEmitWorkerAsset (
4042 config : ResolvedConfig ,
41- asset : EmittedAsset ,
43+ asset : WorkerBundleAsset ,
4244) : void {
43- const fileName = asset . fileName !
4445 const workerMap = workerCache . get ( config . mainConfig || config ) !
45- workerMap . assets . set ( fileName , asset )
46+ workerMap . assets . set ( asset . fileName , asset )
4647}
4748
4849async function bundleWorkerEntry (
@@ -96,7 +97,6 @@ async function bundleWorkerEntry(
9697 saveEmitWorkerAsset ( config , {
9798 fileName : outputChunk . fileName ,
9899 source : outputChunk . code ,
99- type : 'asset' ,
100100 } )
101101 }
102102 } )
@@ -121,7 +121,6 @@ function emitSourcemapForWorkerEntry(
121121 const mapFileName = chunk . fileName + '.map'
122122 saveEmitWorkerAsset ( config , {
123123 fileName : mapFileName ,
124- type : 'asset' ,
125124 source : data ,
126125 } )
127126 }
@@ -156,7 +155,6 @@ export async function workerFileToUrl(
156155 saveEmitWorkerAsset ( config , {
157156 fileName,
158157 source : outputChunk . code ,
159- type : 'asset' ,
160158 } )
161159 workerMap . bundle . set ( id , fileName )
162160 }
@@ -410,16 +408,42 @@ export function webWorkerPlugin(config: ResolvedConfig): Plugin {
410408 return result ( )
411409 } ,
412410
413- generateBundle ( opts ) {
411+ generateBundle ( opts , bundle ) {
414412 // @ts -expect-error asset emits are skipped in legacy bundle
415413 if ( opts . __vite_skip_asset_emit__ || isWorker ) {
416414 return
417415 }
418416 const workerMap = workerCache . get ( config ) !
419417 workerMap . assets . forEach ( ( asset ) => {
420- this . emitFile ( asset )
421- workerMap . assets . delete ( asset . fileName ! )
418+ const duplicateAsset = bundle [ asset . fileName ]
419+ if ( duplicateAsset ) {
420+ const content =
421+ duplicateAsset . type === 'asset'
422+ ? duplicateAsset . source
423+ : duplicateAsset . code
424+ // don't emit if the file name and the content is same
425+ if ( isSameContent ( content , asset . source ) ) {
426+ return
427+ }
428+ }
429+
430+ this . emitFile ( {
431+ type : 'asset' ,
432+ fileName : asset . fileName ,
433+ source : asset . source ,
434+ } )
422435 } )
436+ workerMap . assets . clear ( )
423437 } ,
424438 }
425439}
440+
441+ function isSameContent ( a : string | Uint8Array , b : string | Uint8Array ) {
442+ if ( typeof a === 'string' ) {
443+ if ( typeof b === 'string' ) {
444+ return a === b
445+ }
446+ return Buffer . from ( a ) . equals ( b )
447+ }
448+ return Buffer . from ( b ) . equals ( a )
449+ }
0 commit comments