Skip to content
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

Remove unused stylesheets when navigating #1128

Merged
merged 1 commit into from Jan 15, 2024
Merged

Conversation

kevinmcconnell
Copy link
Collaborator

When navigating to another page, Turbo merges the <head> contents from the current and new pages, which results in a <head> containing the superset of both.

For certain items, like scripts, this makes sense. We have no way to remove a running script. But that's not the case for styles: styles can be unloaded easily, and for the page to display properly, we need to do so. Otherwise styles kept in scope from a previous page could cause a page to render incorrectly.

The common way to avoid this has been to use data-turbo-track="reload" to force a reload if styles change. This works, but it's a bit heavy-handed, causing full page reloads that could have been avoided.

There are a couple of common cases where updating styles on the fly would be useful:

  • Deploying a CSS change. Clients should be able to pick up the change without having to reload.

  • Allowing pages to include their own specific styles, rather than bundle them all together for the whole site. This can reduce the size of the loaded CSS, and make it easier to avoid style conflicts.

await mergedHeadElements
await newStylesheetElements

if (this.willRender) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@afcapel this condition is needed because of the way frame navigations reuse the page renderer to make snapshots. We should refactor the frame head handling to make this sort of thing unnecessary. But let's do that separately, as it has wider implications.

Also, given our recent discussions about potential impact of instaclick, we should see where that's heading before pulling on the snapshotting thread.

Copy link
Collaborator

@afcapel afcapel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, nice one! 👏

src/tests/functional/drive_stylesheet_merging_tests.js Outdated Show resolved Hide resolved
When navigating to another page, Turbo merges the `<head>` contents from
the current and new pages, which results in a `<head>` containing the
superset of both.

For certain items, like scripts, this makes sense. We have no way to
remove a running script. But that's not the case for styles: styles can
be unloaded easily, and for the page to display properly, we need to do
so. Otherwise styles kept in scope from a previous page could cause a
page to render incorrectly.

The common way to avoid this has been to use `data-turbo-track="reload"`
to force a reload if styles change. This works, but it's a bit
heavy-handed, causing full page reloads that could have been avoided.

There are a couple of common cases where updating styles on the fly
would be useful:

- Deploying a CSS change. Clients should be able to pick up the change
  without having to reload.

- Allowing pages to include their own specific styles, rather than
  bundle them all together for the whole site. This can reduce the size
  of the loaded CSS, and make it easier to avoid style conflicts.
@kevinmcconnell kevinmcconnell merged commit a73f6f1 into main Jan 15, 2024
2 checks passed
@kevinmcconnell kevinmcconnell deleted the remove-unused-styles branch January 15, 2024 13:20
afcapel added a commit that referenced this pull request Jan 25, 2024
To track stylesheets and styles that we can dynamically remove when
navigating.

We introduced this behaviour in #1128
and thought it would be a good default to avoid full page reloads when
styles change.

However, it seems it's quite common for libraries to add stylesheets
and styles to the head that they want to keep around. For example, see

- #1133
- #1139

So let's make this behaviour opt-in by adding a `data-turbo-track="dynamic"`
attribute to stylesheets and styles that we want to dynamically remove when
they are no longer in a new page navigation.

This avoids any breaking changes for existing apps.
afcapel added a commit that referenced this pull request Jan 25, 2024
To track stylesheets and styles that we can dynamically remove when
navigating.

We introduced this behaviour in #1128
and thought it would be a good default to avoid full page reloads when
styles change.

However, it seems it's quite common for libraries to add stylesheets
and styles to the head that they want to keep around. For example, see

- #1133
- #1139

So let's make this behaviour opt-in by adding a `data-turbo-track="dynamic"`
attribute to stylesheets and styles that we want to dynamically remove when
they are no longer in a new page navigation.

This avoids any breaking changes for existing apps.
afcapel added a commit to pfeiffer/turbo that referenced this pull request Jan 29, 2024
* origin/main:
  Introduce `turbo:{before-,}morph-{element,attribute}` events
  Turbo 8.0.0-beta.4
  Introduce data-turbo-track="dynamic" (hotwired#1140)
  Ensure that the turbo-frame header is not sent when the turbo-frame has a target of _top (hotwired#1138)
  Turbo 8.0.0-beta.3
  Fix attribute name (hotwired#1134)
  Add InstantClick behavior (hotwired#1101)
  Revert hotwired#926. (hotwired#1126)
  Keep Trix dynamic styles in the head (hotwired#1133)
  Remove unused stylesheets when navigating (hotwired#1128)
  Upgrade idiomorph to 0.3.0 (hotwired#1122)
  Debounce page refreshes triggered via Turbo streams
  Update copyright year to 2024 (hotwired#1118)
  Turbo 8.0.0-beta.2
  Set aria-busy on the form element during a form submission (hotwired#1110)
  Dispatch `turbo:before-fetch-{request,response}` during preloading (hotwired#1034)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants