From 14dcbd762dc549c5f8642dcc1631e47b695cbce1 Mon Sep 17 00:00:00 2001 From: ivan Date: Sun, 19 Mar 2023 11:58:28 +0800 Subject: [PATCH 1/3] fix: make file name deterministic in parallel emits (fix #4909) --- src/utils/FileEmitter.ts | 25 ++++++++----- .../emit-file/deduplicate-assets/_config.js | 35 ++++++++++++++----- ...ring-473287f8.txt => string1-473287f8.txt} | 0 ...ring-473287f8.txt => string1-473287f8.txt} | 0 ...ring-473287f8.txt => string1-473287f8.txt} | 0 ...ring-473287f8.txt => string1-473287f8.txt} | 0 6 files changed, 44 insertions(+), 16 deletions(-) rename test/chunking-form/samples/emit-file/deduplicate-assets/_expected/amd/assets/{string-473287f8.txt => string1-473287f8.txt} (100%) rename test/chunking-form/samples/emit-file/deduplicate-assets/_expected/cjs/assets/{string-473287f8.txt => string1-473287f8.txt} (100%) rename test/chunking-form/samples/emit-file/deduplicate-assets/_expected/es/assets/{string-473287f8.txt => string1-473287f8.txt} (100%) rename test/chunking-form/samples/emit-file/deduplicate-assets/_expected/system/assets/{string-473287f8.txt => string1-473287f8.txt} (100%) diff --git a/src/utils/FileEmitter.ts b/src/utils/FileEmitter.ts index cb950b72c8c..4cd952b84bb 100644 --- a/src/utils/FileEmitter.ts +++ b/src/utils/FileEmitter.ts @@ -365,14 +365,23 @@ export class FileEmitter { if (!fileName) { const sourceHash = getSourceHash(source); fileName = fileNamesBySource.get(sourceHash); - if (!fileName) { - fileName = generateAssetFileName( - consumedFile.name, - source, - sourceHash, - outputOptions, - bundle - ); + const newFileName = generateAssetFileName( + consumedFile.name, + source, + sourceHash, + outputOptions, + bundle + ); + // make sure file name deterministic in parallel emits, always use the shorter and smaller file name + if ( + !fileName || + fileName.length > newFileName.length || + (fileName.length === newFileName.length && fileName.localeCompare(newFileName) > 0) + ) { + if (fileName) { + delete bundle[fileName]; + } + fileName = newFileName; fileNamesBySource.set(sourceHash, fileName); } } diff --git a/test/chunking-form/samples/emit-file/deduplicate-assets/_config.js b/test/chunking-form/samples/emit-file/deduplicate-assets/_config.js index 41d3beb4ca0..b15311f6848 100644 --- a/test/chunking-form/samples/emit-file/deduplicate-assets/_config.js +++ b/test/chunking-form/samples/emit-file/deduplicate-assets/_config.js @@ -1,16 +1,35 @@ +function asyncify(callback) { + const time = Math.round(Math.random() * 100); + + return new Promise(resolve => { + setTimeout(() => { + callback(); + resolve(); + }, time); + }); +} module.exports = { description: 'deduplicates asset that have the same source', + solo: true, options: { input: ['main.js'], plugins: { - buildStart() { - this.emitFile({ type: 'asset', name: 'string.txt', source: 'string' }); - this.emitFile({ type: 'asset', name: 'stringSameSource.txt', source: 'string' }); - this.emitFile({ - type: 'asset', - name: 'sameStringAsBuffer.txt', - source: Buffer.from('string') // Test cross Buffer/string deduplication - }); + async buildStart() { + await Promise.all([ + asyncify(() => this.emitFile({ type: 'asset', name: 'string1.txt', source: 'string' })), + asyncify(() => this.emitFile({ type: 'asset', name: 'string2.txt', source: 'string' })), + asyncify(() => + this.emitFile({ type: 'asset', name: 'stringSameSource.txt', source: 'string' }) + ), + asyncify(() => + this.emitFile({ + type: 'asset', + name: 'sameStringAsBuffer.txt', + source: Buffer.from('string') // Test cross Buffer/string deduplication + }) + ) + ]); + // Different string source this.emitFile({ type: 'asset', name: 'otherString.txt', source: 'otherString' }); diff --git a/test/chunking-form/samples/emit-file/deduplicate-assets/_expected/amd/assets/string-473287f8.txt b/test/chunking-form/samples/emit-file/deduplicate-assets/_expected/amd/assets/string1-473287f8.txt similarity index 100% rename from test/chunking-form/samples/emit-file/deduplicate-assets/_expected/amd/assets/string-473287f8.txt rename to test/chunking-form/samples/emit-file/deduplicate-assets/_expected/amd/assets/string1-473287f8.txt diff --git a/test/chunking-form/samples/emit-file/deduplicate-assets/_expected/cjs/assets/string-473287f8.txt b/test/chunking-form/samples/emit-file/deduplicate-assets/_expected/cjs/assets/string1-473287f8.txt similarity index 100% rename from test/chunking-form/samples/emit-file/deduplicate-assets/_expected/cjs/assets/string-473287f8.txt rename to test/chunking-form/samples/emit-file/deduplicate-assets/_expected/cjs/assets/string1-473287f8.txt diff --git a/test/chunking-form/samples/emit-file/deduplicate-assets/_expected/es/assets/string-473287f8.txt b/test/chunking-form/samples/emit-file/deduplicate-assets/_expected/es/assets/string1-473287f8.txt similarity index 100% rename from test/chunking-form/samples/emit-file/deduplicate-assets/_expected/es/assets/string-473287f8.txt rename to test/chunking-form/samples/emit-file/deduplicate-assets/_expected/es/assets/string1-473287f8.txt diff --git a/test/chunking-form/samples/emit-file/deduplicate-assets/_expected/system/assets/string-473287f8.txt b/test/chunking-form/samples/emit-file/deduplicate-assets/_expected/system/assets/string1-473287f8.txt similarity index 100% rename from test/chunking-form/samples/emit-file/deduplicate-assets/_expected/system/assets/string-473287f8.txt rename to test/chunking-form/samples/emit-file/deduplicate-assets/_expected/system/assets/string1-473287f8.txt From a5154cb5b043a9fc3e79b765d03c3873f584ed3b Mon Sep 17 00:00:00 2001 From: ivan Date: Mon, 20 Mar 2023 09:59:05 +0800 Subject: [PATCH 2/3] refactor: use > determine emit file name --- src/utils/FileEmitter.ts | 2 +- .../samples/emit-file/deduplicate-assets/_config.js | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/utils/FileEmitter.ts b/src/utils/FileEmitter.ts index 4cd952b84bb..5b7ceab90be 100644 --- a/src/utils/FileEmitter.ts +++ b/src/utils/FileEmitter.ts @@ -376,7 +376,7 @@ export class FileEmitter { if ( !fileName || fileName.length > newFileName.length || - (fileName.length === newFileName.length && fileName.localeCompare(newFileName) > 0) + (fileName.length === newFileName.length && fileName > newFileName) ) { if (fileName) { delete bundle[fileName]; diff --git a/test/chunking-form/samples/emit-file/deduplicate-assets/_config.js b/test/chunking-form/samples/emit-file/deduplicate-assets/_config.js index b15311f6848..53e5831b4e7 100644 --- a/test/chunking-form/samples/emit-file/deduplicate-assets/_config.js +++ b/test/chunking-form/samples/emit-file/deduplicate-assets/_config.js @@ -10,7 +10,6 @@ function asyncify(callback) { } module.exports = { description: 'deduplicates asset that have the same source', - solo: true, options: { input: ['main.js'], plugins: { From 0129e9efd36477bbe6956992f88a444b979b6df9 Mon Sep 17 00:00:00 2001 From: ivan Date: Mon, 20 Mar 2023 10:11:28 +0800 Subject: [PATCH 3/3] test: emit file in a random order --- .../emit-file/deduplicate-assets/_config.js | 35 ++++++------------- 1 file changed, 10 insertions(+), 25 deletions(-) diff --git a/test/chunking-form/samples/emit-file/deduplicate-assets/_config.js b/test/chunking-form/samples/emit-file/deduplicate-assets/_config.js index 53e5831b4e7..7fdfc9c6913 100644 --- a/test/chunking-form/samples/emit-file/deduplicate-assets/_config.js +++ b/test/chunking-form/samples/emit-file/deduplicate-assets/_config.js @@ -1,33 +1,18 @@ -function asyncify(callback) { - const time = Math.round(Math.random() * 100); - - return new Promise(resolve => { - setTimeout(() => { - callback(); - resolve(); - }, time); - }); -} module.exports = { description: 'deduplicates asset that have the same source', options: { input: ['main.js'], plugins: { - async buildStart() { - await Promise.all([ - asyncify(() => this.emitFile({ type: 'asset', name: 'string1.txt', source: 'string' })), - asyncify(() => this.emitFile({ type: 'asset', name: 'string2.txt', source: 'string' })), - asyncify(() => - this.emitFile({ type: 'asset', name: 'stringSameSource.txt', source: 'string' }) - ), - asyncify(() => - this.emitFile({ - type: 'asset', - name: 'sameStringAsBuffer.txt', - source: Buffer.from('string') // Test cross Buffer/string deduplication - }) - ) - ]); + buildStart() { + // emit 'string' source in a random order + this.emitFile({ type: 'asset', name: 'stringSameSource.txt', source: 'string' }); + this.emitFile({ type: 'asset', name: 'string2.txt', source: 'string' }); + this.emitFile({ type: 'asset', name: 'string1.txt', source: 'string' }); + this.emitFile({ + type: 'asset', + name: 'sameStringAsBuffer.txt', + source: Buffer.from('string') // Test cross Buffer/string deduplication + }); // Different string source this.emitFile({ type: 'asset', name: 'otherString.txt', source: 'otherString' });