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

Fetch priority #16991

Closed
wants to merge 14 commits into from
Closed

Fetch priority #16991

wants to merge 14 commits into from

Conversation

aboktor
Copy link
Collaborator

@aboktor aboktor commented Apr 14, 2023

Summary

fixes #16989

🤖 Generated by Copilot at 0619c3e

This pull request adds a new feature to webpack that allows users and plugins to control the fetch priority of dynamic imports, which can affect the performance and resource management of chunk loading. It introduces a new option dynamicImportFetchPriority in the webpack configuration, and a new property fetchPriority in the ChunkGroup class and the import options object. It also modifies several runtime modules and the LoadScriptRuntimeModule class to support the fetchPriority option. Additionally, it adds a .gitattributes file to enforce consistent line endings for JavaScript files.

Details

Adds webpackFetchPriority to magic comments
Adds dynamicImportFetchPriorityto module.parser.javascript
Consumes that and sets ChunkGroup.options.fetchPriority
Passes ChunkGroup.options.fetchPriority down to ensure chunk and co to set the right priority on the script tag

Currently completely untested but looking for early feedback

🤖 Generated by Copilot at 0619c3e

  • Add a .gitattributes file to enforce LF line endings for JavaScript files (link)
  • Introduce a new fetchPriority property for ChunkGroup class to represent the priority of fetching a chunk group dynamically (link)
  • Add a new dynamicImportFetchPriority option to the webpack configuration to specify the global default value for the fetchPriority property (link, link)
  • Add a new webpackFetchPriority option to the import options object to allow overriding the global default value for the fetchPriority property for a specific dynamic import (link)
  • Include the fetchPriority option when generating the code for the ensureChunk function in different runtime modules (RuntimeTemplate, EnsureChunkRuntimeModule, JsonpChunkLoadingRuntimeModule) (link, link, link, link)
  • Set the fetchPriority attribute on the script tag when loading a chunk via loadScript function in LoadScriptRuntimeModule (link, link)

@linux-foundation-easycla
Copy link

linux-foundation-easycla bot commented Apr 14, 2023

CLA Signed

The committers listed above are authorized under a signed CLA.

@webpack-bot
Copy link
Contributor

webpack-bot commented Apr 14, 2023

For maintainers only:

  • This needs to be documented (issue in webpack/webpack.js.org will be filed when merged)
  • This needs to be backported to webpack 4 (issue will be created when merged)

.gitattributes Outdated Show resolved Hide resolved
Copy link
Member

@alexander-akait alexander-akait left a comment

Choose a reason for hiding this comment

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

Looks good, now we need a test cases

Copy link
Member

@TheLarkInn TheLarkInn left a comment

Choose a reason for hiding this comment

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

This implementation looks great.

We need test cases for at least two/three scenarios:

  • I can use module.parser.javascript.dynamicImportFetchPriority and it works correctly w/ high/low/auto
  • I can not use module.parser.javascript.dynamicImportFetchPriority but instead use magic comments /* webpackFetchPriority: "high/low/etc." */ and it works
  • I can use both features and override at the import() level using webpackFetchPriority: and it works correctly.

Here is example test cases you can leverage/learn from:

declarations/WebpackOptions.d.ts Show resolved Hide resolved
@alexander-akait
Copy link
Member

@TheLarkInn Yeah, right, like we do for other import(...) options

@TheLarkInn
Copy link
Member

@aboktor we merged a few PR's for tomorrow release, and now we have some merge conflicts. Would you mind rebasing, and you can probably move this over to "Ready for review" once you've done so.

@aboktor
Copy link
Collaborator Author

aboktor commented Apr 19, 2023

The CI is failing on many of the integration tests. Some of those failures I understand (e.g. ConfigTestCases › async-commons-chunk › existing-name › exported tests › should not have duplicate chunks in blocks), and the rest of them I don't. The problem is, I can't repro these failures locally. I tried running yarn cover:integration:a -t async-commons-chunk (tried cover:integration:b as well) and they pass (except for may be open handles)
Ask: How do I repro the CI failures?
@alexander-akait

@alexander-akait
Copy link
Member

@aboktor yeah, I will look at this soon, we will merge it to the next release, don't worry

@alexander-akait
Copy link
Member

alexander-akait commented Apr 22, 2023

Notes for me:

  • implement it for ImportMetaContextDependecyParserPlugin.js
  • use mapping/function style (becaue ESM import(...) doesn't support it and we can't implement this for ESM)
  • test with externals our externals don't support prefetch/preload, so I will not implement fetchPriority too, but it is a potential improvement, but only for externalsType: "script"
  • webpackFetchPriority: false
  • less size of runtime generation
  • more tests to cover all cases

@webpack-bot
Copy link
Contributor

@alexander-akait Thanks for your update.

I labeled the Pull Request so reviewers will review it again.

@TheLarkInn Please review the new changes.

@alexander-akait alexander-akait marked this pull request as ready for review April 23, 2023 00:36
@TheLarkInn
Copy link
Member

@alexander-akait can you fix the merge conflicts and I'd also like @aboktor's

@aboktor
Copy link
Collaborator Author

aboktor commented Apr 26, 2023

One comment on @alexander-akait's changes: Now the fetch priority is set per chunk at compile time. From what I see in the code, the chunk will pick a random priority (based on execution order of the code in ChunkPrefetchPreloadPlugin.js) from any of the ChunkGroups it belongs to.
Is my understanding correct here?

/**
* function to return webpack's Trusted Types policy
* Arguments: () => TrustedTypePolicy
*/
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Inaccurate comment.

@alexander-akait
Copy link
Member

alexander-akait commented Apr 26, 2023

One comment on @alexander-akait's changes: Now the fetch priority is set per chunk at compile time. From what I see in the code, the chunk will pick a random priority (based on execution order of the code in ChunkPrefetchPreloadPlugin.js) from any of the ChunkGroups it belongs to.
Is my understanding correct here?

It is not random, I just move all runtime code to own function and create an object like { "chunkId": "featchPriority" }, so we don't have extra runtime I see what do you mean, we should use the featchPriority property from the first loaded async chunk (i.e. apply order), because another featchPriority doesn't make sense, chunk already loaded

@TheLarkInn
Copy link
Member

Let's sort out this design for next Wednesdays release. Need to handle rebase conflicts in addition to make sure we are on the same page.

/** @type {ExpressionNode} */ (prop.value)
);
if (expr.isBoolean()) {
groupOptions.fetchPriority = "auto";
Copy link
Contributor

@Zlatkovsky Zlatkovsky May 2, 2023

Choose a reason for hiding this comment

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

@aboktor , what is the purpose of allowing a boolean at all, when setting it (and regardless of the value) will result in "auto"? I would think just keeping it to the three enums -- "high", "low", "auto" -- would keep it both simpler and more understandable

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I believe @alexander-akait added that code. I do see that pattern followed throughout webpack though.

@@ -5579,6 +5579,11 @@ declare interface JavascriptParserOptions {
*/
createRequire?: string | boolean;

/**
* Specifies global fetchPriority for dynamic import.
Copy link
Contributor

Choose a reason for hiding this comment

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

@aboktor , I think it would be helpful to note the default value is "auto" (by which I assume it means that we leave it up to the browser's defaults); and also what a boolean value would mean.

(Though like I mentioned in another comment, I'm finding it hard to understand what true or false would mean in this case at all; do we need them?)

Copy link
Member

Choose a reason for hiding this comment

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

I agree, let's remove true, false requires to disable it, you can have a parent module with webpackFetchPriority: "high" and want to disable it for some deep modules, would say it's fine tuning, we use the same logic for any magic comments, also some libraries can use webpackFetchPriority comment too but you don't want it, so we allow to disable it

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: Shipped
Development

Successfully merging this pull request may close these issues.

"fetchPriority" for script tags
5 participants