8000 draft for extended renderDynamicImport hook by iczero · Pull Request #5870 · rollup/rollup · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

draft for extended renderDynamicImport hook #5870

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

Merged
merged 8 commits into from
Mar 17, 2025

Conversation

iczero
Copy link
Contributor
@iczero iczero commented Mar 5, 2025

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:

Description

When using dynamic imports, there is the parent module (the module containing the import() expression), the target module (whatever got imported by the dynamic import), and optionally also any transitively imported modules (anything that is imported by the target module via import statement). Sometimes, transitively imported modules will be included in a separate chunk from the target module. In this case, the dynamic import will require the equivalent of two network round trips before completing, because the transitive import will not be loaded until after the target of the original dynamic import is loaded.

For "static" import statements, there seems to be a feature (hoistTransitiveImports) that moves transitive imports upwards. In the case of an import chain A -> B -> C, assuming all 3 modules are bundled into separate chunks, chunk A will contain an import statement for chunk C to avoid an extra RTT. Unfortunately, this currently does not appear to be directly possible for dynamic imports, as chunk information is not available in the renderDynamicImport hook. By exposing chunk import information in renderDynamicImport, plugins can easily insert a call to import or preload transitively imported chunks at the dynamic import site.

Todo:

  • Update documentation once the API is mostly done
  • Imports added by hoistTransitiveImports currently don't appear in the imports list, which defeats the entire purpose of this PR
  • Import paths are not resolved

Copy link
vercel bot commented Mar 5, 2025

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
rollup ✅ Ready (Inspect) Visit Preview 💬 Add feedback Mar 17, 2025 5:55am

@iczero
Copy link
Contributor Author
iczero commented Mar 6, 2025

Test resolve-file-url has the following diff:

- actual
+ expected
                  const asset$1 = 'resolved';
                  const chunk$1 = 'resolved';
 
                  const asset = new URL('assets/asset-unresolved-B7Qh6_pN.txt', module.meta.url).href;
-                 const chunk = new URL('nested/chunk.js', module.meta.url).href;
+                 const chunk = new URL('nested/chunk2.js', module.meta.url).href;
 
-                 module.import('./nested/chunk2.js').then(result => console.log(result, chunk$1, chunk, asset$1, asset));
+                 module.import('./nested/chunk.js').then(result => console.log(result, chunk$1, chunk, asset$1, asset));
 
          })
  };
 }));

I believe it is because I moved getImportPath into the render phase. Is this fine?

Edit: fixed, mostly

Copy link
Member
@lukastaegert lukastaegert left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi, this is a really good idea! Some impressions first:

  • Why did you put the logic into the "render" method, and why did you create an interface where the plugin returns a function to be called again with the import info? I would have hoped we can just put this information into the argument of renderDynamicImport?
  • If this is about performance and you only want to calculate the paths if needed, we could also think about other solutions, e.g. to give the plugin all the information to calculate the relative path on their own? Then we could just add e.g. chunk.getPreRenderedChunkInfo() as targetChunk to the options argument in the renderDynamicImport hook, and put this information into the PreRenderedChunk type as well (this is already cached). The importing chunk could also be added a a chunk: PreRenderedChunk argument.
  • It would be nice to update src/rollup/types.d.ts to contain the new arguments.

Copy link
codecov bot commented Mar 7, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 98.55%. Comparing base (7710d69) to head (bfb2f89).
Report is 5 commits behind head on master.

Additional details and impacted files
@@           Coverage Diff           @@
##           master    #5870   +/-   ##
=======================================
  Coverage   98.54%   98.55%           
=======================================
  Files         269      269           
  Lines        8550     8563   +13     
  Branches     1467     1470    +3     
=======================================
+ Hits         8426     8439   +13     
  Misses         92       92           
  Partials       32       32           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@iczero
Copy link
Contributor Author
iczero commented Mar 7, 2025

Hi, thanks for the review.

  • Sorry, I appear to have misunderstood the code. I will rewrite this.
  • Sounds good, perhaps we can add a getChunkImportPath(from: PreRenderedChunk, to: PreRenderedChunk): string function to the plugin context to do this? looks like this isn't the best fit. I've replaced it with another interface.
    • I believe calling this function could affect the order of the output.chunkFileNames hook and chunk filename deduplication behavior. Specifically, calling this function would cause the imported chunk (and its dependencies) to generate a filename, potentially before it is rendered. I believe I encountered this here: draft for extended renderDynamicImport hook #5870 (comment). Is this acceptable?
  • Noted, I will move the interfaces to there.

Regarding this comment #5870 (comment), currently the patch does include hoisted transitive dependencies in the object it passes to the hook (please see https://github.com/rollup/rollup/pull/5870/files#diff-665b5d9bb97c88c8f65a65f1904d1742223d88909e8978eac1c186d6749b6a98, specifically generated-leaf.js). The chunk.inlineTransitiveImports change moves hoisting before chunks are rendered, and since the resolveDynamicImport hook runs during the render, it receives hoisted imports as well. Previously, since hoisting was performed during chunk render, the hook would sometimes reference chunks that were not rendered, and therefore did not have their imports hoisted yet.

Copy link
Member
@lukastaegert lukastaegert left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks actually quite good to me now. Please check out if we can replace PreRenderedChunk with RenderedChunk, I think the latter might actually already be completely available at this point.

@iczero
Copy link
Contributor Author
iczero commented Mar 11, 2025

I've changed ImportedInternalChunk to have fileName: string like ImportedExternalChunk. It now directly uses the PreRenderedChunk type and also makes the API easier to use. Not sure why I didn't have it that way before. chunk and targetChunk from the renderDynamicImport hook still use the type with preliminaryFileName in case plugins want to do their own path resolution or something.

Copy link
Member
@lukastaegert lukastaegert left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks a lot, this looks really good to me now, including documentation, will see that we can merge this now.

@lukastaegert lukastaegert enabled auto-merge March 17, 2025 05:57
@lukastaegert lukastaegert added this pull request to the merge queue Mar 17, 2025
Merged via the queue into rollup:master with commit 7f0164e Mar 17, 2025
40 checks passed
@iczero
Copy link
Contributor Author
iczero commented Mar 17, 2025

Thank you as well for the excellent bundler!

Copy link

This PR has been released as part of rollup@4.36.0. You can test it via npm install rollup.

605D 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.

2 participants
0