Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extend manualChunks API #3542

Merged
merged 12 commits into from May 10, 2020
Merged

Extend manualChunks API #3542

merged 12 commits into from May 10, 2020

Conversation

lukastaegert
Copy link
Member

@lukastaegert lukastaegert commented May 8, 2020

This PR contains:

  • bugfix
  • feature
  • refactor
  • documentation
  • other

Are tests included?

  • yes (bugfixes and features will not be merged without tests)
  • no

Breaking Changes?

  • yes (breaking changes will not be merged unless absolutely necessary)
  • no

List any relevant issue numbers:
Resolves #3520

Description

This will extend the manualChunks function so that it gets a second parameter of the form

{
  getModuleInfo: GetModuleInfo;
  getModuleIds: () => IterableIterator<string>;
}

where getModuleInfo is the same function as on the plugin context.

  • TODO: I will also soft-deprecate this.moduleIds on the plugin context in favour of an explicit this.getModuleIds().

Additionally, the object returned by getModuleInfo is extended by importers: string[] and dynamicImporters: string[] which allow traversing the graph backwards in order to find out e.g. which entries import a module.

For instance consider a scenario where you have a set of components, each of which dynamically imports a set of translated strings, i.e.

// Inside the "foo" component

function getTranslatedStrings(currentLanguage) {
  switch (currentLanguage) {
    case 'en': return import('./foo.strings.en.js');
    case 'de': return import('./foo.strings.de.js');
    // ...
  }
}

If many components are used together, this will result in a lot of dynamic imports of very small chunks even though it is known that all language files of the same language that are imported by the same chunk will always be used together.

The following code will merge all files of the same language that are only used by a single entry point, and put all files that are used by multiple entry points into "shared" chunks:

manualChunks(id, { getModuleInfo }) {
  const match = /.*\.strings\.(\w+)\.js/.exec(id);
  if (match) {
    const language = match[1];
    const dependentEntryPoints = [];

    // we use a Set here so we handle each module at most once, which
    // prevents infinite loops in case of circular dependencies
    const idsToHandle = new Set(getModuleInfo(id).dynamicImporters);

    for (const moduleId of idsToHandle) {
      const { isEntry, isDynamicEntry, importers } = getModuleInfo(moduleId);
      if (isEntry || isDynamicEntry) dependentEntryPoints.push(moduleId);

      // The Set iterator is intelligent enough to iterate over elements that
      // are added during iteration
      for (const importerId of importers) idsToHandle.add(importerId);
    }

    // If there is a unique entry, we put into into a chunk based on the entry name
    if (dependentEntryPoints.length === 1) {
      return `${dependentEntryPoints[0].split('/').slice(-1)[0]}.strings.${language}`;
    }
    // For multiple entries, we put it into a "shared"  chunk
    if (dependentEntryPoints.length > 1) {
      return `shared.strings.${language}`;
    }
  }
}

@lukastaegert lukastaegert mentioned this pull request May 8, 2020
@rollup-bot
Copy link
Collaborator

rollup-bot commented May 8, 2020

Thank you for your contribution! ❤️

You can try out this pull request locally by installing Rollup via

npm install rollup/rollup#manual-chunks-api

or load it into the REPL:
https://rollupjs.org/repl/?circleci=10933

@codecov
Copy link

codecov bot commented May 8, 2020

Codecov Report

Merging #3542 into master will increase coverage by 0.04%.
The diff coverage is 100.00%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #3542      +/-   ##
==========================================
+ Coverage   96.25%   96.29%   +0.04%     
==========================================
  Files         176      176              
  Lines        6027     6040      +13     
  Branches     1778     1781       +3     
==========================================
+ Hits         5801     5816      +15     
  Misses        112      112              
+ Partials      114      112       -2     
Impacted Files Coverage Δ
src/utils/parseOptions.ts 100.00% <ø> (ø)
src/Chunk.ts 99.78% <100.00%> (ø)
src/ExternalModule.ts 98.03% <100.00%> (+0.08%) ⬆️
src/Graph.ts 98.84% <100.00%> (+0.11%) ⬆️
src/Module.ts 98.90% <100.00%> (+<0.01%) ⬆️
src/ModuleLoader.ts 99.53% <100.00%> (+0.47%) ⬆️
src/finalisers/system.ts 97.75% <100.00%> (+1.12%) ⬆️
src/utils/PluginContext.ts 100.00% <100.00%> (ø)
src/utils/chunkAssignment.ts 100.00% <100.00%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update e6d6876...47ec66d. Read the comment docs.

@lukastaegert lukastaegert marked this pull request as ready for review May 9, 2020 19:55
@lukastaegert
Copy link
Member Author

This PR is now fully documented and ready to be released

@lukastaegert lukastaegert merged commit f63e54d into master May 10, 2020
@lukastaegert lukastaegert deleted the manual-chunks-api branch May 10, 2020 06:45
@LarsDenBakker
Copy link
Contributor

@lukastaegert in the example code snippet you mention isDynamicEntry, but I don't see this reflected in getModuleInfo here: https://github.com/rollup/rollup/pull/3542/files#diff-7c1e6304262c178e7fe268b62060e26bR265

It comes up undefined for every module when I try it out.

@lukastaegert
Copy link
Member Author

True, that is wrong. Instead you should check if there are dynamicImporters. Will try to update the docs by tomorrow, otherwise doc PR welcome!

@LarsDenBakker
Copy link
Contributor

No problem, I'll check if I can make it work using dynamicImporters and update the docs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Influence chunking
3 participants