Skip to content

Commit

Permalink
Merge pull request #48553 from ghiculescu/preload_links_header-invoca…
Browse files Browse the repository at this point in the history
…tion

Allow opting in/out of `Link preload` headers when calling `stylesheet_link_tag` or `javascript_include_tag`
  • Loading branch information
guilleiguaran committed Jun 30, 2023
2 parents b790387 + 5b116c5 commit 8a158ed
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 4 deletions.
12 changes: 12 additions & 0 deletions actionview/CHANGELOG.md
@@ -1,3 +1,15 @@
* Allow opting in/out of `Link preload` headers when calling `stylesheet_link_tag` or `javascript_include_tag`

```ruby
# will exclude header, even if setting is enabled:
javascript_include_tag("http://example.com/all.js", preload_links_header: false)

# will include header, even if setting is disabled:
stylesheet_link_tag("http://example.com/all.js", preload_links_header: true)
```

*Alex Ghiculescu*

* Stop generating `Link preload` headers once it has reached 1KB.

Some proxies have trouble handling large headers, but more importantly preload links
Expand Down
10 changes: 6 additions & 4 deletions actionview/lib/action_view/helpers/asset_tag_helper.rb
Expand Up @@ -112,6 +112,7 @@ def javascript_include_tag(*sources)
options = sources.extract_options!.stringify_keys
path_options = options.extract!("protocol", "extname", "host", "skip_pipeline").symbolize_keys
preload_links = []
use_preload_links_header = options["preload_links_header"].nil? ? preload_links_header : options.delete("preload_links_header")
nopush = options["nopush"].nil? ? true : options.delete("nopush")
crossorigin = options.delete("crossorigin")
crossorigin = "anonymous" if crossorigin == true
Expand All @@ -120,7 +121,7 @@ def javascript_include_tag(*sources)

sources_tags = sources.uniq.map { |source|
href = path_to_javascript(source, path_options)
if preload_links_header && !options["defer"] && href.present? && !href.start_with?("data:")
if use_preload_links_header && !options["defer"] && href.present? && !href.start_with?("data:")
preload_link = "<#{href}>; rel=#{rel}; as=script"
preload_link += "; crossorigin=#{crossorigin}" unless crossorigin.nil?
preload_link += "; integrity=#{integrity}" unless integrity.nil?
Expand All @@ -137,7 +138,7 @@ def javascript_include_tag(*sources)
content_tag("script", "", tag_options)
}.join("\n").html_safe

if preload_links_header
if use_preload_links_header
send_preload_links_header(preload_links)
end

Expand Down Expand Up @@ -192,6 +193,7 @@ def javascript_include_tag(*sources)
def stylesheet_link_tag(*sources)
options = sources.extract_options!.stringify_keys
path_options = options.extract!("protocol", "extname", "host", "skip_pipeline").symbolize_keys
use_preload_links_header = options["preload_links_header"].nil? ? preload_links_header : options.delete("preload_links_header")
preload_links = []
crossorigin = options.delete("crossorigin")
crossorigin = "anonymous" if crossorigin == true
Expand All @@ -200,7 +202,7 @@ def stylesheet_link_tag(*sources)

sources_tags = sources.uniq.map { |source|
href = path_to_stylesheet(source, path_options)
if preload_links_header && href.present? && !href.start_with?("data:")
if use_preload_links_header && href.present? && !href.start_with?("data:")
preload_link = "<#{href}>; rel=preload; as=style"
preload_link += "; crossorigin=#{crossorigin}" unless crossorigin.nil?
preload_link += "; integrity=#{integrity}" unless integrity.nil?
Expand All @@ -220,7 +222,7 @@ def stylesheet_link_tag(*sources)
tag(:link, tag_options)
}.join("\n").html_safe

if preload_links_header
if use_preload_links_header
send_preload_links_header(preload_links)
end

Expand Down
17 changes: 17 additions & 0 deletions actionview/test/template/asset_tag_helper_test.rb
Expand Up @@ -642,6 +642,23 @@ def test_should_not_set_preload_links_for_data_url
end
end

def test_should_not_set_preload_links_if_opted_out_at_invokation
with_preload_links_header do
stylesheet_link_tag("http://example.com/style.css", preload_links_header: false)
javascript_include_tag("http://example.com/all.js", preload_links_header: false)
assert_nil @response.headers["Link"]
end
end

def test_should_set_preload_links_if_opted_in_at_invokation
with_preload_links_header(false) do
stylesheet_link_tag("http://example.com/style.css", preload_links_header: true)
javascript_include_tag("http://example.com/all.js", preload_links_header: true)
expected = "<http://example.com/style.css>; rel=preload; as=style; nopush,<http://example.com/all.js>; rel=preload; as=script; nopush"
assert_equal expected, @response.headers["Link"]
end
end

def test_should_generate_links_under_the_max_size
with_preload_links_header do
100.times do |i|
Expand Down

0 comments on commit 8a158ed

Please sign in to comment.