-
Notifications
You must be signed in to change notification settings - Fork 21.5k
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
Automatically set Link header for each stylesheet and script #39939
Conversation
<link rel="preload"> elements[0] can be serialized in `Link` headers[1] to allow the browser to preload them before it parsed the HTML body. It is particularly useful for scripts included at the bottom of the document. [0] https://developer.mozilla.org/en-US/docs/Web/HTML/Preloading_content [1] https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Link
Sorry I missed this awhile back! Looks good, thanks! |
Thanks! |
@casperisfine @eileencodes
|
@fleck both good points. I'm swamped just now, but I'll see if I can come up with something early next week, unless you beat me to it. Causing pushes is definitely a bad idea, and if people want to do that then it should definitely be explicit. |
PR #39939 added support for the `Link` header being generated automatically when using `stylesheet_link_tag` and `javascript_include_tag`. However not everything should be preloaded, e.g. a link to a legacy IE stylesheet has no need to be preloaded because IE doesn't support the header and in some browsers it will trigger the preload even though it's not used since it's inside an IE conditional comment. This leads to increased bandwith costs and slower application performance. To allow more flexibility for sites that may have complex needs for the `Link` header this commit adds a configuration option that disables it completely and leaves it up to the application to decide how to handle generating a `Link` header.
PR #39939 added support for the `Link` header being generated automatically when using `stylesheet_link_tag` and `javascript_include_tag`. However not everything should be preloaded, e.g. a link to a legacy IE stylesheet has no need to be preloaded because IE doesn't support the header and in some browsers it will trigger the preload even though it's not used since it's inside an IE conditional comment. This leads to increased bandwith costs and slower application performance. To allow more flexibility for sites that may have complex needs for the `Link` header this commit adds a configuration option that disables it completely and leaves it up to the application to decide how to handle generating a `Link` header.
PR #39939 added support for the `Link` header being generated automatically when using `stylesheet_link_tag` and `javascript_include_tag`. However not everything should be preloaded, e.g. a link to a legacy IE stylesheet has no need to be preloaded because IE doesn't support the header and in some browsers it will trigger the preload even though it's not used since it's inside an IE conditional comment. This leads to increased bandwith costs and slower application performance. To allow more flexibility for sites that may have complex needs for the `Link` header this commit adds a configuration option that disables it completely and leaves it up to the application to decide how to handle generating a `Link` header. (cherry picked from commit 200083c)
…der` `nil` without Rails 6.1 defaults In rails#39939 we automatically set `Link` header for each stylesheet and script. In rails#40882 we added `config.action_view.preload_links_header` option to configure whether `stylesheet_link_tag` and `javascript_include_tag` should set automatically `Link` header. This commit adds test to make sure that it is disabled by default for updated apps that haven't adopted new '6.1' defaults. Also, added changes to Configuring guide - Mentioned this option in "Results of `config.load_defaults`" section - Mentioned this option in "Baseline defaults:" section (see ff88113)
Just in case anyone else bumps into this: This header can get very large in a dev environment with a lot of assets (like the Spree admin). If you're using Apache in front of a Rails dev server, like I am (in a VM, to test how it would work in prod) the header may overflow, Apache will truncate it to less than 8KiB and possibly break the response. In my case Apache was sending an incomplete response (missing the config.action_view.preload_links_header = false It's probably not a problem in production because CSS and JS will usually be concatenated into less files. Also,
I don't know if sending multiple Link headers would make a difference in this case, probably not. |
@zavan Any idea why apache chooses 8KB as the response limit? |
I don't know, the HTTP spec itself does not enforce or recommends a limit. A limit is needed, for sure, so maybe they just chose 8KB a long time ago and never really changed it, even though it could be larger nowadays without problems. Also note that this limit is for the headers only, not the entire response, of course. |
@zavan Based on your links it looks like every major tech that handles HTTP imposes a limit of 8192 bytes for headers. I'm guessing this adheres to the original RFC that recommends that any such limit be a minimum of 8 KB. |
I might have a patch for this: #42056 Would one of you be willing to test it? |
I'm happy to open a new issue/redirect to a forum to cover this if it's not suitable to add a comment/question here, but this functionality can cause an awful lot of data to get sent in headers when In my use case, this is happening with rendering a PDF -- the Does it definitely make sense to include |
No it doesn't that's an oversight and should be fixed. |
Currently this leads to a massive response header in development setup which breaches current default Jetty limits (of 8 kB) rails/rails#39939
Currently this leads to a massive response header in development setup which breaches current default Jetty limits (of 8 kB) rails/rails#39939
Currently this leads to a massive response header in development setup which breaches current default Jetty limits (of 8 kB) rails/rails#39939
Currently this leads to a massive response header in development setup which breaches current default Jetty limits (of 8 kB) rails/rails#39939
Currently this leads to a massive response header in development setup which breaches current default Jetty limits (of 8 kB) rails/rails#39939
elements can be serialized in
Link
headers to allow the browser to preload them before it parsed the HTML body.It is particularly useful for scripts included at the bottom of the document.
Implementation
This piggy backs on Early Hints as they are fundamentally the same feature, Early Hint simply tell the browser in advance what the
Link
header is likely to look like.In term of serialization, we can either send multiple
Link
headers, or set multiple comma separated values in a single header. I chose the later as it's a bit more compact.cc @eileencodes @tenderlove since you implemented early hints, you might have an opinion on this.
cc @rafaelfranca