Skip to content

feat(astro): add observeDynamicLinks option for prefetch settings#16583

Open
rururux wants to merge 1 commit intowithastro:mainfrom
rururux:prefetch-mutation-observer
Open

feat(astro): add observeDynamicLinks option for prefetch settings#16583
rururux wants to merge 1 commit intowithastro:mainfrom
rururux:prefetch-mutation-observer

Conversation

@rururux
Copy link
Copy Markdown
Member

@rururux rururux commented May 4, 2026

fixes #13297

Changes

In the current implementation, enabling prefetch settings causes links to be collected via document.getElementsByTagName('a') on the initial page load.
While this approach works for most cases, it fails to cover certain scenarios, such as the one reported in issue #13297.

The root cause of issue #13297 is that when a component with the server:defer attribute uses top-level await, its links are rendered after the Promise resolves, meaning they are not captured by the initial document.getElementsByTagName('a') call.
More broadly, the same issue occurs whenever links are dynamically added to the DOM after the initial page load.

To address this, this pull request adds the observeDynamicLinks option, which uses a MutationObserver to watch for dynamically added link elements.
This ensures that links added after the initial render are properly captured.

This feature is opt-in.

Why MutationObserver?

Investigation process
  • First, I checked the code around server:defer to see if it used any event notifications.
  • It did not, but I found that the prefetch code [uses the astro:page-load event].
    document.addEventListener('astro:page-load', () => {
  • When I looked into whether astro:page-load could be used here, I found that the constant defining this event name is marked as @deprecated, so I decided to look for a different approach.
    /** @deprecated This will be removed in Astro 7 */
    export const TRANSITION_PAGE_LOAD = 'astro:page-load';
  • I also considered that the root cause of issue Prefetch not working in components with server:defer and top-level await #13297 is not specific to server:defer, the same problem can occur in other situations where links are added to the DOM dynamically. For this reason, I wanted an approach that resolves the issue within the prefetch code itself, rather than adding prefetch-dependent logic to the server:defer side.
  • As a result, I concluded that MutationObserver is the best approach, as it is well-suited for observing DOM changes and allows the fix to be fully self-contained within the prefetch implementation.

Testing

Added tests to verify that the observeDynamicLinks option works correctly in the following scenarios:

Docs

/cc @withastro/maintainers-docs for feedback!

@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented May 4, 2026

🦋 Changeset detected

Latest commit: 717a9d9

The changes in this PR will be included in the next version bump.

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions github-actions Bot added pkg: astro Related to the core `astro` package (scope) docs pr semver: minor Change triggers a `minor` release labels May 4, 2026
Copy link
Copy Markdown
Contributor

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

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

This PR is blocked because it contains a minor changeset. A reviewer will merge this at the next release if approved.


// https://astro.build/config
export default defineConfig({
adapter: node({ mode: 'standalone' }),
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

This adapter is required to run tests using components that utilize the server:defer property.

@codspeed-hq
Copy link
Copy Markdown

codspeed-hq Bot commented May 4, 2026

Merging this PR will not alter performance

✅ 18 untouched benchmarks


Comparing rururux:prefetch-mutation-observer (717a9d9) with main (17f1867)1

Open in CodSpeed

Footnotes

  1. No successful run was found on main (7711e47) during the generation of this report, so 17f1867 was used instead as the comparison base. There might be some changes unrelated to this pull request in this report.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

docs pr pkg: astro Related to the core `astro` package (scope) semver: minor Change triggers a `minor` release

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Prefetch not working in components with server:defer and top-level await

1 participant