feat(astro): add observeDynamicLinks option for prefetch settings#16583
feat(astro): add observeDynamicLinks option for prefetch settings#16583rururux wants to merge 1 commit into
observeDynamicLinks option for prefetch settings#16583Conversation
🦋 Changeset detectedLatest 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 |
|
|
||
| // https://astro.build/config | ||
| export default defineConfig({ | ||
| adapter: node({ mode: 'standalone' }), |
There was a problem hiding this comment.
This adapter is required to run tests using components that utilize the server:defer property.
Is there a reason this is opt-in and not a default? Are the drawbacks to this that means we’d want to avoid it most of the time? |
|
Honestly, the main reason was that I expected most cases wouldn't require MutationObserver-based detection, so I went with opt-in first to limit the impact rather than changing the default behavior right away. Happy to change it to default behavior if that's what you'd prefer. |
|
We don't know what's the impact on real-world applications, so I think it's best to have it opt-in for now |
|
It’s true that a global I wonder if another option could be to expose And for this specific issue ( These are both areas I don’t know super well, so don’t take this as a “We should do this”, but just sharing some thoughts to see if they’d help. |
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:deferattribute uses top-level await, its links are rendered after the Promise resolves, meaning they are not captured by the initialdocument.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
observeDynamicLinksoption, which uses aMutationObserverto 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
server:deferto see if it used any event notifications.astro:page-loadevent].astro/packages/astro/src/prefetch/index.ts
Line 316 in 7711e47
astro:page-loadcould 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.astro/packages/astro/src/transitions/events.ts
Lines 12 to 13 in 7711e47
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 theserver:deferside.MutationObserveris 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
observeDynamicLinksoption works correctly in the following scenarios:server:defer, as reported in issue Prefetch not working in components with server:defer and top-level await #13297ToggleButton.jsx)Docs
/cc @withastro/maintainers-docs for feedback!