Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit bcb1b6d

Browse filesBrowse files
chunk: merge allow-extension modules (#5891)
Co-authored-by: Lukas Taegert-Atkinson <lukastaegert@users.noreply.github.com>
1 parent d970e29 commit bcb1b6d
Copy full SHA for bcb1b6d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Dismiss banner
Expand file treeCollapse file tree

87 files changed

+636
-397
lines changed

‎src/Chunk.ts

Copy file name to clipboardExpand all lines: src/Chunk.ts
+54-7Lines changed: 54 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,8 @@ export default class Chunk {
198198
private readonly renderedModules: Record<string, RenderedModule> = Object.create(null);
199199
private sortedExportNames: string[] | null = null;
200200
private strictFacade = false;
201+
/** Modules with 'allow-extension' that should have preserved exports within the chunk */
202+
private allowExtensionModules = new Set<Module>();
201203

202204
constructor(
203205
private readonly orderedModules: readonly Module[],
@@ -375,6 +377,18 @@ export default class Chunk {
375377
remainingExports.delete(variable);
376378
}
377379
}
380+
381+
for (const module of this.allowExtensionModules) {
382+
const exportNamesByVariable = module.getExportNamesByVariable();
383+
for (const [variable, exportNames] of exportNamesByVariable) {
384+
this.exportNamesByVariable.set(variable, [...exportNames]);
385+
for (const exportName of exportNames) {
386+
this.exportsByName.set(exportName, variable);
387+
}
388+
remainingExports.delete(variable);
389+
}
390+
}
391+
378392
if (this.outputOptions.minifyInternalExports) {
379393
assignExportsToMangledNames(remainingExports, this.exportsByName, this.exportNamesByVariable);
380394
} else {
@@ -395,17 +409,25 @@ export default class Chunk {
395409
const exposedVariables = new Set<Variable>(
396410
this.dynamicEntryModules.map(({ namespace }) => namespace)
397411
);
412+
398413
for (const module of entryModules) {
399-
if (module.preserveSignature) {
400-
for (const exportedVariable of module.getExportNamesByVariable().keys()) {
401-
// We need to expose all entry exports from this chunk
402-
if (this.chunkByModule.get(exportedVariable.module as Module) === this) {
403-
exposedVariables.add(exportedVariable);
414+
if (module.preserveSignature === 'allow-extension') {
415+
const canPreserveExports = this.canPreserveModuleExports(module);
416+
417+
if (canPreserveExports) {
418+
this.allowExtensionModules.add(module);
419+
420+
if (!this.facadeModule) {
421+
this.facadeModule = module;
422+
this.strictFacade = false;
423+
this.assignFacadeName({}, module, this.outputOptions.preserveModules);
404424
}
425+
this.facadeChunkByModule.set(module, this);
426+
427+
continue;
405428
}
406429
}
407-
}
408-
for (const module of entryModules) {
430+
409431
const requiredFacades: FacadeName[] = Array.from(
410432
new Set(
411433
module.chunkNames.filter(({ isUserDefined }) => isUserDefined).map(({ name }) => name)
@@ -486,9 +508,34 @@ export default class Chunk {
486508
if (!this.outputOptions.preserveModules) {
487509
this.addNecessaryImportsForFacades();
488510
}
511+
489512
return facades;
490513
}
491514

515+
private canPreserveModuleExports(module: Module): boolean {
516+
const exportNamesByVariable = module.getExportNamesByVariable();
517+
518+
// Check for conflicts - an export name is a conflict if it points to a different module or definition
519+
for (const [variable, exportNames] of exportNamesByVariable) {
520+
for (const exportName of exportNames) {
521+
const existingVariable = this.exportsByName.get(exportName);
522+
// It's ok if the same export name in two modules references the exact same variable
523+
if (existingVariable && existingVariable !== variable) {
524+
return false;
525+
}
526+
}
527+
}
528+
529+
// No actual conflicts found, add export names for future conflict checks
530+
for (const [variable, exportNames] of exportNamesByVariable) {
531+
for (const exportName of exportNames) {
532+
this.exportsByName.set(exportName, variable);
533+
}
534+
}
535+
536+
return true;
537+
}
538+
492539
getChunkName(): string {
493540
return (this.name ??= this.outputOptions.sanitizeFileName(this.getFallbackChunkName()));
494541
}
+22Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
const preserveSignature = 'allow-extension';
2+
module.exports = defineTest({
3+
description: 'preserves exports for modules with allow-extension signature',
4+
options: {
5+
input: 'main',
6+
output: {
7+
manualChunks: {
8+
libs: ['lib1', 'lib2', 'lib3']
9+
}
10+
},
11+
plugins: [
12+
{
13+
name: 'allow-extension-plugin',
14+
buildStart() {
15+
this.emitFile({ type: 'chunk', id: 'lib1', preserveSignature });
16+
this.emitFile({ type: 'chunk', id: 'lib2', preserveSignature });
17+
this.emitFile({ type: 'chunk', id: 'lib3', preserveSignature });
18+
}
19+
}
20+
]
21+
}
22+
});
+24Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
define(['exports'], (function (exports) { 'use strict';
2+
3+
// This should be included directly in the chunk with preserved exports
4+
const value1$1 = 'lib1-value';
5+
6+
// This will have conflicting exports and need a facade
7+
const value2 = 'lib2-value';
8+
const value1 = 'conflict-value'; // Conflicting name
9+
10+
// This should be included directly in the chunk with preserved exports
11+
const value3 = 'lib3-value';
12+
13+
var lib3 = /*#__PURE__*/Object.freeze({
14+
__proto__: null,
15+
value3: value3
16+
});
17+
18+
exports.lib3 = lib3;
19+
exports.value1 = value1$1;
20+
exports.value1$1 = value1;
21+
exports.value2 = value2;
22+
exports.value3 = value3;
23+
24+
}));
+8Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
define(['exports', './generated-lib1'], (function (exports, libs) { 'use strict';
2+
3+
4+
5+
exports.value1 = libs.value1$1;
6+
exports.value2 = libs.value2;
7+
8+
}));
+8Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
define(['require', './generated-lib1'], (function (require, libs) { 'use strict';
2+
3+
console.log(libs.value1);
4+
console.log(libs.value1$1);
5+
console.log(libs.value2);
6+
console.log(new Promise(function (resolve, reject) { require(['./generated-lib1'], resolve, reject); }).then(function (n) { return n.lib3; }).then(m => m.value3));
7+
8+
}));
+22Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
'use strict';
2+
3+
// This should be included directly in the chunk with preserved exports
4+
const value1$1 = 'lib1-value';
5+
6+
// This will have conflicting exports and need a facade
7+
const value2 = 'lib2-value';
8+
const value1 = 'conflict-value'; // Conflicting name
9+
10+
// This should be included directly in the chunk with preserved exports
11+
const value3 = 'lib3-value';
12+
13+
var lib3 = /*#__PURE__*/Object.freeze({
14+
__proto__: null,
15+
value3: value3
16+
});
17+
18+
exports.lib3 = lib3;
19+
exports.value1 = value1$1;
20+
exports.value1$1 = value1;
21+
exports.value2 = value2;
22+
exports.value3 = value3;
+8Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
'use strict';
2+
3+
var libs = require('./generated-lib1.js');
4+
5+
6+
7+
exports.value1 = libs.value1$1;
8+
exports.value2 = libs.value2;
+8Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
'use strict';
2+
3+
var libs = require('./generated-lib1.js');
4+
5+
console.log(libs.value1);
6+
console.log(libs.value1$1);
7+
console.log(libs.value2);
8+
console.log(Promise.resolve().then(function () { return require('./generated-lib1.js'); }).then(function (n) { return n.lib3; }).then(m => m.value3));
+16Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// This should be included directly in the chunk with preserved exports
2+
const value1$1 = 'lib1-value';
3+
4+
// This will have conflicting exports and need a facade
5+
const value2 = 'lib2-value';
6+
const value1 = 'conflict-value'; // Conflicting name
7+
8+
// This should be included directly in the chunk with preserved exports
9+
const value3 = 'lib3-value';
10+
11+
var lib3 = /*#__PURE__*/Object.freeze({
12+
__proto__: null,
13+
value3: value3
14+
});
15+
16+
export { value2 as a, lib3 as l, value1 as v, value1$1 as value1, value3 };
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { v as value1, a as value2 } from './generated-lib1.js';
+6Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import { value1, v as value1$1, a as value2 } from './generated-lib1.js';
2+
3+
console.log(value1);
4+
console.log(value1$1);
5+
console.log(value2);
6+
console.log(import('./generated-lib1.js').then(function (n) { return n.l; }).then(m => m.value3));
+24Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
System.register([], (function (exports) {
2+
'use strict';
3+
return {
4+
execute: (function () {
5+
6+
// This should be included directly in the chunk with preserved exports
7+
const value1$1 = exports("value1", 'lib1-value');
8+
9+
// This will have conflicting exports and need a facade
10+
const value2 = exports("a", 'lib2-value');
11+
const value1 = exports("v", 'conflict-value'); // Conflicting name
12+
13+
// This should be included directly in the chunk with preserved exports
14+
const value3 = exports("value3", 'lib3-value');
15+
16+
var lib3 = /*#__PURE__*/Object.freeze({
17+
__proto__: null,
18+
value3: value3
19+
});
20+
exports("l", lib3);
21+
22+
})
23+
};
24+
}));
+13Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
System.register(['./generated-lib1.js'], (function (exports) {
2+
'use strict';
3+
return {
4+
setters: [function (module) {
5+
exports({ value1: module.v, value2: module.a });
6+
}],
7+
execute: (function () {
8+
9+
10+
11+
})
12+
};
13+
}));
+19Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
System.register(['./generated-lib1.js'], (function (exports, module) {
2+
'use strict';
3+
var value1, value1$1, value2;
4+
return {
5+
setters: [function (module) {
6+
value1 = module.value1;
7+
value1$1 = module.v;
8+
value2 = module.a;
9+
}],
10+
execute: (function () {
11+
12+
console.log(value1);
13+
console.log(value1$1);
14+
console.log(value2);
15+
console.log(module.import('./generated-lib1.js').then(function (n) { return n.l; }).then(m => m.value3));
16+
17+
})
18+
};
19+
}));
+2Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
// This should be included directly in the chunk with preserved exports
2+
export const value1 = 'lib1-value';
+3Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
// This will have conflicting exports and need a facade
2+
export const value2 = 'lib2-value';
3+
export const value1 = 'conflict-value'; // Conflicting name
+2Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
// This should be included directly in the chunk with preserved exports
2+
export const value3 = 'lib3-value';
+7Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { value1 } from './lib1.js';
2+
import { value1 as v1, value2 } from './lib2.js';
3+
4+
console.log(value1);
5+
console.log(v1);
6+
console.log(value2);
7+
console.log(import('./lib3.js').then(m => m.value3));
+21Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
const preserveSignature = 'allow-extension';
2+
module.exports = defineTest({
3+
description: 'merges same exports for modules with allow-extension signature',
4+
options: {
5+
input: 'main',
6+
output: {
7+
manualChunks: {
8+
libs: ['lib1', 'lib2']
9+
}
10+
},
11+
plugins: [
12+
{
13+
name: 'allow-extension-plugin',
14+
buildStart() {
15+
this.emitFile({ type: 'chunk', id: 'lib1', preserveSignature });
16+
this.emitFile({ type: 'chunk', id: 'lib2', preserveSignature });
17+
}
18+
}
19+
]
20+
}
21+
});
+13Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
define(['exports'], (function (exports) { 'use strict';
2+
3+
const bar = 'vendor-bar';
4+
5+
const value1 = 'lib1-value';
6+
7+
const value2 = 'lib2-value';
8+
9+
exports.bar = bar;
10+
exports.value1 = value1;
11+
exports.value2 = value2;
12+
13+
}));
+8Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
define(['./generated-lib1'], (function (libs) { 'use strict';
2+
3+
console.log(libs.value1);
4+
console.log(libs.bar);
5+
console.log(libs.value2);
6+
console.log(libs.bar);
7+
8+
}));
+11Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
'use strict';
2+
3+
const bar = 'vendor-bar';
4+
5+
const value1 = 'lib1-value';
6+
7+
const value2 = 'lib2-value';
8+
9+
exports.bar = bar;
10+
exports.value1 = value1;
11+
exports.value2 = value2;
+8Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
'use strict';
2+
3+
var libs = require('./generated-lib1.js');
4+
5+
console.log(libs.value1);
6+
console.log(libs.bar);
7+
console.log(libs.value2);
8+
console.log(libs.bar);
+7Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
const bar = 'vendor-bar';
2+
3+
const value1 = 'lib1-value';
4+
5+
const value2 = 'lib2-value';
6+
7+
export { bar, value1, value2 };
+6Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import { value1, bar, value2 } from './generated-lib1.js';
2+
3+
console.log(value1);
4+
console.log(bar);
5+
console.log(value2);
6+
console.log(bar);

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.