Skip to content

Commit 53cf9fe

Browse files
authored
Add flag to re-enable deep dynamic chunk optimization (#4837)
* Add flag for deep chunk optimization * Add documentation * Improve wording
1 parent d88c935 commit 53cf9fe

8 files changed

Lines changed: 45 additions & 12 deletions

File tree

docs/configuration-options/index.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2269,6 +2269,16 @@ These options reflect new features that have not yet been fully finalized. Avail
22692269
22702270
Determines after how many runs cached assets that are no longer used by plugins should be removed.
22712271
2272+
### experimentalDeepDynamicChunkOptimization
2273+
2274+
| | |
2275+
| --: | :-- |
2276+
| Type: | `number` |
2277+
| CLI: | `--experimentalDeepDynamicChunkOptimization`/`--no-experimentalDeepDynamicChunkOptimization` |
2278+
| Default: | `false` |
2279+
2280+
Currently, chunk generation may create too many chunks if many dynamic imports are used. This is because the algorithm aborts optimization when certain thresholds are surpassed to avoid performance issues. Set this flag to `true` to create potentially fewer chunks at the cost of build performance.
2281+
22722282
### experimentalMinChunkSize
22732283
22742284
| | |

src/Bundle.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -165,8 +165,13 @@ export default class Bundle {
165165
bundle: OutputBundleWithPlaceholders,
166166
getHashPlaceholder: HashPlaceholderGenerator
167167
): Promise<Chunk[]> {
168-
const { experimentalMinChunkSize, inlineDynamicImports, manualChunks, preserveModules } =
169-
this.outputOptions;
168+
const {
169+
experimentalDeepDynamicChunkOptimization,
170+
experimentalMinChunkSize,
171+
inlineDynamicImports,
172+
manualChunks,
173+
preserveModules
174+
} = this.outputOptions;
170175
const manualChunkAliasByEntry =
171176
typeof manualChunks === 'object'
172177
? await this.addManualChunks(manualChunks)
@@ -188,7 +193,8 @@ export default class Bundle {
188193
: getChunkAssignments(
189194
this.graph.entryModules,
190195
manualChunkAliasByEntry,
191-
experimentalMinChunkSize
196+
experimentalMinChunkSize,
197+
experimentalDeepDynamicChunkOptimization
192198
)) {
193199
sortByExecutionOrder(modules);
194200
const chunk = new Chunk(

src/rollup/types.d.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -647,6 +647,7 @@ export interface OutputOptions {
647647
dynamicImportInCjs?: boolean;
648648
entryFileNames?: string | ((chunkInfo: PreRenderedChunk) => string);
649649
esModule?: boolean | 'if-default-prop';
650+
experimentalDeepDynamicChunkOptimization?: boolean;
650651
experimentalMinChunkSize?: number;
651652
exports?: 'default' | 'named' | 'none' | 'auto';
652653
extend?: boolean;
@@ -700,6 +701,7 @@ export interface NormalizedOutputOptions {
700701
dynamicImportInCjs: boolean;
701702
entryFileNames: string | ((chunkInfo: PreRenderedChunk) => string);
702703
esModule: boolean | 'if-default-prop';
704+
experimentalDeepDynamicChunkOptimization: boolean;
703705
experimentalMinChunkSize: number;
704706
exports: 'default' | 'named' | 'none' | 'auto';
705707
extend: boolean;

src/utils/chunkAssignment.ts

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ type ChunkDefinitions = { alias: string | null; modules: Module[] }[];
1111
export function getChunkAssignments(
1212
entries: readonly Module[],
1313
manualChunkAliasByEntry: ReadonlyMap<Module, string>,
14-
minChunkSize: number
14+
minChunkSize: number,
15+
deepChunkOptimization: boolean
1516
): ChunkDefinitions {
1617
const chunkDefinitions: ChunkDefinitions = [];
1718
const modulesInManualChunks = new Set(manualChunkAliasByEntry.keys());
@@ -41,7 +42,8 @@ export function getChunkAssignments(
4142
assignedEntriesByModule,
4243
modulesInManualChunks,
4344
staticEntries,
44-
dynamicallyDependentEntriesByDynamicEntry
45+
dynamicallyDependentEntriesByDynamicEntry,
46+
deepChunkOptimization
4547
);
4648
}
4749
}
@@ -141,7 +143,8 @@ function assignEntryToStaticDependencies(
141143
assignedEntriesByModule: DependentModuleMap,
142144
modulesInManualChunks: ReadonlySet<Module>,
143145
staticEntries: ReadonlySet<Module>,
144-
dynamicallyDependentEntriesByDynamicEntry: ReadonlyDependentModuleMap
146+
dynamicallyDependentEntriesByDynamicEntry: ReadonlyDependentModuleMap,
147+
deepChunkOptimization: boolean
145148
) {
146149
const dynamicallyDependentEntries = dynamicallyDependentEntriesByDynamicEntry.get(entry);
147150
const modulesToHandle = new Set([entry]);
@@ -153,7 +156,8 @@ function assignEntryToStaticDependencies(
153156
dynamicallyDependentEntries,
154157
dependentEntriesByModule.get(module)!,
155158
staticEntries,
156-
dynamicallyDependentEntriesByDynamicEntry
159+
dynamicallyDependentEntriesByDynamicEntry,
160+
deepChunkOptimization
157161
)
158162
) {
159163
continue;
@@ -178,9 +182,13 @@ function isModuleAlreadyLoaded(
178182
dynamicallyDependentEntries: ReadonlySet<Module>,
179183
containedIn: ReadonlySet<Module>,
180184
staticEntries: ReadonlySet<Module>,
181-
dynamicallyDependentEntriesByDynamicEntry: ReadonlyDependentModuleMap
185+
dynamicallyDependentEntriesByDynamicEntry: ReadonlyDependentModuleMap,
186+
deepChunkOptimization: boolean
182187
): boolean {
183-
if (dynamicallyDependentEntries.size > MAX_ENTRIES_TO_CHECK_FOR_SHARED_DEPENDENCIES) {
188+
if (
189+
!deepChunkOptimization &&
190+
dynamicallyDependentEntries.size > MAX_ENTRIES_TO_CHECK_FOR_SHARED_DEPENDENCIES
191+
) {
184192
return false;
185193
}
186194
const entriesToCheck = new Set(dynamicallyDependentEntries);
@@ -190,7 +198,10 @@ function isModuleAlreadyLoaded(
190198
return false;
191199
}
192200
const dynamicallyDependentEntries = dynamicallyDependentEntriesByDynamicEntry.get(entry)!;
193-
if (dynamicallyDependentEntries.size > MAX_ENTRIES_TO_CHECK_FOR_SHARED_DEPENDENCIES) {
201+
if (
202+
!deepChunkOptimization &&
203+
dynamicallyDependentEntries.size > MAX_ENTRIES_TO_CHECK_FOR_SHARED_DEPENDENCIES
204+
) {
194205
return false;
195206
}
196207
for (const dependentEntry of dynamicallyDependentEntries) {

src/utils/options/mergeOptions.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,7 @@ async function mergeOutputOptions(
233233
dynamicImportInCjs: getOption('dynamicImportInCjs'),
234234
entryFileNames: getOption('entryFileNames'),
235235
esModule: getOption('esModule'),
236+
experimentalDeepDynamicChunkOptimization: getOption('experimentalDeepDynamicChunkOptimization'),
236237
experimentalMinChunkSize: getOption('experimentalMinChunkSize'),
237238
exports: getOption('exports'),
238239
extend: getOption('extend'),

src/utils/options/normalizeOutputOptions.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ export async function normalizeOutputOptions(
6666
dynamicImportInCjs: config.dynamicImportInCjs ?? true,
6767
entryFileNames: getEntryFileNames(config, unsetOptions),
6868
esModule: config.esModule ?? 'if-default-prop',
69+
experimentalDeepDynamicChunkOptimization:
70+
config.experimentalDeepDynamicChunkOptimization || false,
6971
experimentalMinChunkSize: config.experimentalMinChunkSize || 0,
7072
exports: getExports(config, unsetOptions),
7173
extend: config.extend || false,

test/function/samples/output-options-hook/_config.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ module.exports = {
2727
dynamicImportInCjs: true,
2828
entryFileNames: '[name].js',
2929
esModule: 'if-default-prop',
30+
experimentalDeepDynamicChunkOptimization: false,
3031
experimentalMinChunkSize: 0,
3132
exports: 'auto',
3233
extend: false,

test/misc/optionList.js

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)