Skip to content

Optimize preload response headers to prioritize critical assets#10612

Merged
aduth merged 6 commits intomainfrom
aduth-preload-headers-optimize
May 14, 2024
Merged

Optimize preload response headers to prioritize critical assets#10612
aduth merged 6 commits intomainfrom
aduth-preload-headers-optimize

Conversation

@aduth
Copy link
Copy Markdown
Contributor

@aduth aduth commented May 13, 2024

🛠 Summary of changes

Updates asset rendering in common layouts and critical paths to optimize loading and deprioritize non-blocking assets.

Specifically:

These changes stem from a discovery that Rails (as of ActionView 7.1) caps link preload headers at 1kb. Since we aggressively split assets into small stylesheets and scripts, we currently exceed this limit, and therefore some assets are not preloaded using the response headers.

For example, application-*.js is not included as a preloaded asset in production today, despite being common to every page of the application and controlling critical, high visibility UI elements.

curl -I --silent https://secure.login.gov | grep link

It may be possible to configure or override the default value, though it is currently configured as a module constant ActionView::Helpers::AssetTagHelper::MAX_HEADER_SIZE. The changelog note about "diminishing returns" is a valid consideration as well., though further analysis is required.

In the meantime, the changes here are intended to eliminate some low-hanging fruit for more granular control over preloaded assets.

📜 Testing Plan

  1. curl -I --silent http://localhost:3000 | grep link

Observe:

  • No nopush anywhere in the header
  • dap, session-expire-session, and platform-authenticator-available are not included in the header
  • application is included in the header
  • PublicSans-Bold and PublicSans-Regular are preloaded as root-relative paths rather than fully-qualified URLs

Example:

Before:

link: </assets/init-6ad4cfee.js>; rel=preload; as=script; nopush,<http://localhost:3000/assets/public-sans/PublicSans-Bold-7ae9760d.woff2>; rel=preload; as=font; type=font/woff2; crossorigin=anonymous,<http://localhost:3000/assets/public-sans/PublicSans-Regular-838cb6e3.woff2>; rel=preload; as=font; type=font/woff2; crossorigin=anonymous,</assets/tab_navigation_component-1df00155.css>; rel=preload; as=style; nopush,</assets/password_toggle_component-b3bd600a.css>; rel=preload; as=style; nopush,</assets/icon_component-4ccec652.css>; rel=preload; as=style; nopush,</assets/application-312c5cee.css>; rel=preload; as=style; nopush,</packs/js/validated_field_component.js>; rel=preload; as=script; nopush,</packs/js/password_toggle_component.js>; rel=preload; as=script; nopush,</packs/js/submit_button_component.js>; rel=preload; as=script; nopush,</packs/js/platform-authenticator-available.js>; rel=preload; as=script; nopush,</packs/js/session-expire-session.js>; rel=preload; as=script; nopush

After:

link: </assets/init-6ad4cfee.js>; rel=preload; as=script,</assets/public-sans/PublicSans-Bold-7ae9760d.woff2>; rel=preload; as=font; type=font/woff2; crossorigin=anonymous,</assets/public-sans/PublicSans-Regular-838cb6e3.woff2>; rel=preload; as=font; type=font/woff2; crossorigin=anonymous,</assets/tab_navigation_component-1df00155.css>; rel=preload; as=style,</assets/password_toggle_component-b3bd600a.css>; rel=preload; as=style,</assets/icon_component-4ccec652.css>; rel=preload; as=style,</assets/application-312c5cee.css>; rel=preload; as=style,</packs/js/validated_field_component.js>; rel=preload; as=script,</packs/js/password_toggle_component.js>; rel=preload; as=script,</packs/js/submit_button_component.js>; rel=preload; as=script,</packs/js/application.js>; rel=preload; as=script

aduth added 3 commits May 13, 2024 14:03
changelog: Internal, Performance, Optimize preload response headers to prioritize critical assets
@aduth
Copy link
Copy Markdown
Contributor Author

aduth commented May 13, 2024

It may be possible to configure or override the default value, though it is currently configured as a module constant ActionView::Helpers::AssetTagHelper::MAX_HEADER_SIZE. The changelog note about "diminishing returns" is a valid consideration as well., though further analysis is required.

For future consideration: Thinking that since we control most asset rendering through javascript_packs_tag_once and stylesheet_tag_once anyways, we could control this centrally by disabling default preload_links_header behavior across the board, and then re-implementing a custom implementation to send the preload hints.

This could also have a few more optimizations:

  • Remove excess whitespace from link values
  • Increase or eliminate header size limit

aduth and others added 2 commits May 13, 2024 15:58
Co-authored-by: Zach Margolis <zachmargolis@users.noreply.github.com>
@aduth aduth merged commit 2d469a9 into main May 14, 2024
@aduth aduth deleted the aduth-preload-headers-optimize branch May 14, 2024 12:14
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.

3 participants