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

add support for link preload/prefetch #7056

Merged
merged 9 commits into from Apr 17, 2018
Merged

add support for link preload/prefetch #7056

merged 9 commits into from Apr 17, 2018

Conversation

sokra
Copy link
Member

@sokra sokra commented Apr 16, 2018

What kind of change does this PR introduce?
feature

Did you add tests for your changes?
yes

If relevant, link to documentation update:
TODO

Summary
This adds support for a webpackPreload resp. webpackPrefetch magic comment at import() which automatically adds <link rel="preload/prefetch"> tags after the parent chunk is loaded. This prefetches the scripts when the browser is idle and improves latency resp. preloads a script that is expected to be used imediately. When multiple import()s are accessible they are prefetch/preloading by importance (highest first, can be provided as number argument).

Prefetching is similar to precaching the whole application in a service worker, but this PR only prefetches the next possible on-demand chunks and in the order you specify. This saves bandwidth and more likely accessed chunks can be prefetched first.

Preload allows the browser to prepare the script in background which also improves performance, and elimitates waterfall-like import(). Use preload wisely and only when you know what you are doing.

Preloading/prefetching is also available on entry points but this requires support by the plugin you are using to generate the HTML. webpack now provides preload/prefetch info in the json stats object in entrypoints.childAssets. This can be used to generate <link> tags in the HTML (Note that the normal assets for the entrypoint also need to be added as <link> tags to ensure they load first, when using preload).

Does this PR introduce a breaking change?
I hope not, but there are a few API changes which should be backward-compatible

Other information
see also https://github.com/GoogleChromeLabs/preload-webpack-plugin. Compared to this plugin this PR prefetches only the next layer in the application and allows to specify the order. cc @addyosmani

As guideline:

  • add webpackPrefetch: true to import()s that the user will likely visit in future.
  • add webpackPreload: true to import()s that your code will always load immediately.
  • don't add anything if it's unlikely that the user will visit this in future (don't waste bandwidth).
  • add webpackPrefetch: -10 to import()s that the user will probably visit in future and low latency is very important.

`import(/* webpackPrefetchPriority: 10 */ "...")`
`import(/* webpackPreloadPriority: 10 */ "...")`
@sokra sokra changed the title add support for link preload add support for link preload/prefetch Apr 16, 2018
@webpack-bot
Copy link
Contributor

Thank you for your pull request! The most important CI builds succeeded, we’ll review the pull request soon.

@iamakulov
Copy link

iamakulov commented Apr 16, 2018

A question here. Would it make sense to add aliases for common use cases of preloads? I’m thinking of something like

import(/* webpackPreloadPriority: "preload" */ './foo.js')
import(/* webpackPrefetchPriority: "prefetch" */ './foo.js')
import(/* webpackPrefetchPriority: "prefetch-unlikely" */ './foo.js')

in addition to

import(/* webpackPreloadPriority: 1 */ './foo.js')
import(/* webpackPrefetchPriority: 1 */ './foo.js')
import(/* webpackPrefetchPriority: 5 */ './foo.js')

The reason I’m thinking about this is

  1. most users don’t need to care about priority numbers, and comments like /* webpackPreloadPriority: 1 */ would bring a mental overhead for them (“why is there 1? what would happen if I put 2 there?”)

  2. string values express the intent better

@iamakulov
Copy link

Oh, wait, I’m dumb, that’s not a priority, that’s an order

@iamakulov
Copy link

iamakulov commented Apr 16, 2018

Well, OK. Would it make sense to rename webpackPreloadPriority/webpackPrefetchPriority to something like webpackPreloadOrder/webpackPrefetchOrder? For me, that’d give a much better explanation of what these numbers do. (“Order” is plain and simple. “Priority” is something more complex; plus it’s not clear if priority: 1 is higher or lower than priority: 5)

Continuing on

most users don’t need to care about priority numbers

the following might do a great job in making the feature simpler (& more popular!):

import(/* webpackPreload: true */ 'foo.js') // Works as webpackPreloadOrder: 1
import(/* webpackPrefetch: true */ 'foo.js') // Works as webpackPrefetchOrder: 1

rename webpackPreloadPriority to webpackPreload
allow true as parameter (equals 0)
@sokra
Copy link
Member Author

sokra commented Apr 16, 2018

Thanks for the feedback @iamakulov

I changed it to import(/* webpackPrefetch: true */ "...") and for advanced use cases also a number argument which is relative to the "true": import(/* webpackPrefetch: 10 */) is more important than "true" and fetched before that. import(/* webpackPrefetch: -10 */) is less important and fetched after "true". ("true" equals 0)

@webpack-bot
Copy link
Contributor

The minimum test ratio has been reached. Thanks!

@sokra
Copy link
Member Author

sokra commented Apr 16, 2018

  • Todo tests for ChunkGroup.compareTo

@sokra sokra merged commit ec4ec8e into master Apr 17, 2018
@sokra sokra deleted the feature/preload branch April 17, 2018 09:06
MLoughry added a commit to MLoughry/webpack that referenced this pull request May 29, 2018
Following up on @sokra's work in webpack#7056, this change addresses webpack#7084 to have webpack prefetch and preload designated chunks from the entry chunk.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants