Rails 6.1 new framework defaults: what they do and how to safely uncomment them
By: Dylan Reile
Tags: Rails, Ruby on Rails, Rails 6

16. Rails.application.config.action_view.preload_links_header = true

What does this do?

Imagine that we want to execute some JavaScript on a page when it’s finished loading. We might do something like this:

<html>

<head>

<!-- The 'defer' attribute tells the browser to wait until it

finishes parsing all the HTML before loading/executing

the script. This is roughly equivalent to putting the

script tag at the bottom of the body. --> <%= javascript_include_tag('some.js'), defer: true %>

</head>

<body>

</body>

</html>

The page loads, then the script is downloaded, then the script is executed. Wouldn’t it be more performant if the browser could download the script while it’s parsing the HTML?

We can do that with a preload Link element:

<html>

<head>

<!-- This helper generates an element that looks like this:

<link rel="preload" href="/some.js" as="script">

This tells the browser 'go ahead and download this, but

don't execute it yet, I'll do something with it later'.

-->

<%= preload_link_tag('some.js') %>

<%= javascript_include_tag('some.js'), defer: true %>

</head>

<body>

</body>

</html>

Now the browser downloads the script at the same time that it’s parsing the HTML. Then the preloaded script is executed. That’s great, but the browser still has to parse the markup until it reaches our preload directive. Wouldn’t it be more performant if the browser knew to preload the script before it even looked at the HTML?

We can do that too, with a Link header:

# /app/controllers/some_controller.rb

class SomeController < ApplicationController # This is the action responsible for rendering our ERB.

# Browsers allow Link elements to be serialized as HTTP headers.

# This moves the preload directive out of the response body.

# The browser now knows to preload the script without even

# looking at the HTML.

def show

response.set_header('Link','</some.js>; rel=preload; as=script')

end

end

That’s great, but littering our controllers with custom headers isn’t ideal. Wouldn’t it be convenient if Rails automatically included them for you?

That’s exactly what uncommenting this flag does! Uncommenting this flag will include Link header preload directives when you use javascript_include_tag or stylesheet_link_tag .

How to safely uncomment?

This flag can be safely uncommented. Browsers that support Link headers will get a performance boost. Browsers that don’t will ignore them.

Edge case: HTTP response header overflow

It's common to set config.assets.debug = true in the development environment. This will split concatenated assets into their constituent files and include them all separately. This may result in an exceptionally long Link header that exceeds the (effective) maximum 8192 bytes for HTTP response headers.

If this is causing problems for you, I recommend disabling this feature in development:

# /config/environments/development.rb

Rails.application.config.action_view.preload_links_header = false

Edge case: IE 5–9 conditional assets

Does your site support IE 5–9? If so, you may be using IE conditional comments to ensure your IE-specific assets are only being loaded on IE.

Since Link headers aren’t aware of these comments, they can cause non-IE browsers to unnecessarily download IE assets. Note that they won’t be applied on those browsers, just preloaded. At worse this would unnecessarily consume bandwidth.

If you’re in this situation, your options are:

Let non-IE browsers unnecessarily download some assets they won’t use. Disable this feature altogether. Stop supporting IE 5–9. What’s wrong with you? Write a helper that disables this feature on a per-asset basis (named something like javascript_include_tag_without_preload ). Here’s an example.

Now what?

Once all 16 flags are uncommented, you don’t need config/initializers/new_framework_defaults_6_1.rb anymore. Delete that file and add load_defaults 6.1 to your config/application.rb . This is functionaly equivalent to having all the flags uncommented.

Would you like to work with the latest Rails?

The Bridge Services team at Evidation Health is hiring! We always work with the latest tech—not to mention competetitive pay and great WLB.