-
Notifications
You must be signed in to change notification settings - Fork 2.7k
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
Early hints and modulepreload
#7854
Comments
+1 for the suggestion. I'd like to hear @hiroshige-g's opinion. Note that Chromium's current implementation is somewhat different from the ideal. As the design document explains it makes a request upon a reception of an Early Hints preload and put the response in the HTTP cache (no network request happens when there is a fresh response in the cache already). When the document makes a request for the same resource the response hopefully comes from the HTTP cache. It doesn't recognize the semantics of We don't think the current approach is a long-term solution and we would like to have a proper implementation in the future -- doing so requires a lot of engineering work and we are trying to figure out a reasonable approach. cc: @yutakahirano |
Just to clarify, does this mean the following?
Note that preload the script graph anyway doesn't fetch the dependencies (at least in Chromium). Step 3 is marked as "optionally perform". |
Right, with the "special" aspects of
Exactly, passing in the response we already have and modifying that algorithm to optionally accept a response argument.
Right, but at the very least the module is added to the module map, and this "optionally perform" would become viable for early hints. |
Thanks for clarification! After looking further at the Chromium Early Hints source code, "preload the scripts as if they were |
Yes, that's what I meant by "special" aspects of |
Anyway, I can work on a PR along those lines, where early hints performs the |
Created a PR to try to express the proposal. |
In a project I'm working on, I made the choice to adopt ES6+ syntax and ESM native modules, with an "importmap" to faccilitate versioning/cache busting. Upon transitioning the preload strategy, I believe I am now stuck with no options available that aren't actively harmful in some way. The reason the project has a preload strategy, is that some endpoints involve non-trivial server-side logic where Page Load Time benefits from concurrently requesting static assets (flush headers before the HTTP body. HTTP body is cannot feasibly be flushed in parts). AssumptionsLet me back up a bit, and share what my assumptions are at this point. Correct me if any of this is wrong!
ObservationsIt seeems thus that today, when transitioning from having 3 classic scripts to 3 ESM files in a project, there is currently no option available that provides the same level of correct/complete preloading as was already available to classic scripts. What I tried:
So... in conclusion, it appears there are no options available to progressively enhance performance by preloading some (or all) ESM files as module scripts. Each of the options I found is actively harmful in at least one major browser. I'm leaving this here in case I've missed something. I'd love to know of a way that I can at least declare one of the JS resources for preloading, in a way that works in 1 browser and is safely ignored in any browsers that don't support it yet. |
* The majority of time (e.g. 350ms out of 370ms) is spent in the backend Hound API request. * The php-mustache compiler (the Apache/PECL version, not the Composer dev version) is about 2x faster than the JS version was prior to I3eb612748, e.g. 40-50ms (render JS) vs 8-10ms (render php-mustache). We can make things even faster by flushing the HTTP headers with a few things so that the browser can start pulling these (likely browser cache hits) from its disk and/or from the network if following a permalink. I've not added HTTP Link headers for preloading the JavaScript files because: 1. The JS code in this repo is (as of I3eb612748) entirely progressive enhancement. Using a preload for these would needly starve bandwidth from the HTML and CSS responses, since preloads are naturally given a high fetch priority. There is no benefit to preloading with low fetchpriority either, since browsers already discover these early in the `<head>`. We don't have deep chains of indirects requests, where low fetchpriority could solve a discovery bottleneck. 2. I made the choice to adopt ES6 syntax and ESM native modules, with an "importmap" to ensure cache busting. Unfortunately, despite preload for classic JS being nearly 10 years old in browsers, preloading is still pretty broken for ES6/ESM even in the latest version of Firefox/Chrome/Safari. We could go compromise and use modern ES6+ via regular <script> instead of ESM (with a global variable instead of imports), but I kept what we have given little to no benefit per reason 1. Longer sad story about lack of ESM preloading at: whatwg/html#7854 (comment) Change-Id: Ic7d01d9de8bcb78aff8c55fe4d3485be0428f098
@Krinkle, apologies for the delay; my understanding of the modulepreload side of the problem is this: Early Hints modulepreload and import maps can't work together because conceptually, Early Hints prepends a However, Chromium seems to have a bug3 where Early Hint modulepreloads don't disable the import map, (but having an actual Here's a minimal repro of the current situation: https://github.com/zqianem/modulepreload-krinkle-repro For both Firefox and Chromium, the recursion from the Early Hints only starts after Footnotes |
Currently in the spec, early hints work only for
preload
(and soon forpreconnect
).In Chromium source code (as I understand it) and in WPT,
modulepreload
is also supported, but it's treated like apreload
in the sense that it doesn't start loading module dependencies. It still uses the special fetching defaults/parameters ofmodulepreload
like havingscript
as the default foras
.I see how it's problematic to start creating actual script objects before the document is initialized, but it also changes the semantics of
modulepreload
when it's an early hint, which might be confusing - e.g. if the developer doesn't add an actual equivalent<link rel=modulepreload>
to the document, the dependencies will only be fetched when the module is imported in practice.I suggest the following strategy in the spec (and implementation):
modulepreload
header.The text was updated successfully, but these errors were encountered: