1
1
import path from 'node:path'
2
2
import MagicString from 'magic-string'
3
- import type { EmittedAsset , OutputChunk } from 'rollup'
3
+ import type { OutputChunk } from 'rollup'
4
4
import type { ResolvedConfig } from '../config'
5
5
import type { Plugin } from '../plugin'
6
6
import type { ViteDevServer } from '../server'
@@ -14,9 +14,11 @@ import {
14
14
import { cleanUrl } from '../../shared/utils'
15
15
import { fileToUrl } from './asset'
16
16
17
+ type WorkerBundleAsset = { fileName : string ; source : string | Uint8Array }
18
+
17
19
interface WorkerCache {
18
20
// save worker all emit chunk avoid rollup make the same asset unique.
19
- assets : Map < string , EmittedAsset >
21
+ assets : Map < string , WorkerBundleAsset >
20
22
21
23
// worker bundle don't deps on any more worker runtime info an id only had a result.
22
24
// save worker bundled file id to avoid repeated execution of bundles
@@ -38,11 +40,10 @@ const workerCache = new WeakMap<ResolvedConfig, WorkerCache>()
38
40
39
41
function saveEmitWorkerAsset (
40
42
config : ResolvedConfig ,
41
- asset : EmittedAsset ,
43
+ asset : WorkerBundleAsset ,
42
44
) : void {
43
- const fileName = asset . fileName !
44
45
const workerMap = workerCache . get ( config . mainConfig || config ) !
45
- workerMap . assets . set ( fileName , asset )
46
+ workerMap . assets . set ( asset . fileName , asset )
46
47
}
47
48
48
49
async function bundleWorkerEntry (
@@ -96,7 +97,6 @@ async function bundleWorkerEntry(
96
97
saveEmitWorkerAsset ( config , {
97
98
fileName : outputChunk . fileName ,
98
99
source : outputChunk . code ,
99
- type : 'asset' ,
100
100
} )
101
101
}
102
102
} )
@@ -121,7 +121,6 @@ function emitSourcemapForWorkerEntry(
121
121
const mapFileName = chunk . fileName + '.map'
122
122
saveEmitWorkerAsset ( config , {
123
123
fileName : mapFileName ,
124
- type : 'asset' ,
125
124
source : data ,
126
125
} )
127
126
}
@@ -156,7 +155,6 @@ export async function workerFileToUrl(
156
155
saveEmitWorkerAsset ( config , {
157
156
fileName,
158
157
source : outputChunk . code ,
159
- type : 'asset' ,
160
158
} )
161
159
workerMap . bundle . set ( id , fileName )
162
160
}
@@ -410,16 +408,42 @@ export function webWorkerPlugin(config: ResolvedConfig): Plugin {
410
408
return result ( )
411
409
} ,
412
410
413
- generateBundle ( opts ) {
411
+ generateBundle ( opts , bundle ) {
414
412
// @ts -expect-error asset emits are skipped in legacy bundle
415
413
if ( opts . __vite_skip_asset_emit__ || isWorker ) {
416
414
return
417
415
}
418
416
const workerMap = workerCache . get ( config ) !
419
417
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
+ } )
422
435
} )
436
+ workerMap . assets . clear ( )
423
437
} ,
424
438
}
425
439
}
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