Implementing the Astro ClientRouter caused several issues, including D3.js visualizations stopping after initial load, React components losing their sizing, and custom elements throwing re-registration errors during SPA-like navigation. Event listeners also failed to fire after the initial page load.
Issue
After implementing <ClientRouter />, several critical components failed during client-side navigation:
- D3.js TidyTree rendered only on initial load and showed blank SVG on subsequent navigations.
- Web Workers used for Voronoi canvas failed to initialize when returning to the homepage.
- React MeshGradient WebGL canvas resized incorrectly after the first navigation.
- Custom Elements threw re-registration errors during navigation.
- Event listeners registered via
DOMContentLoadedstopped working after navigation.
Culprit
The issues arose from:
- Event Listener Architecture: Components relied on
DOMContentLoaded, which does not fire during ClientRouter’s AJAX-based navigation. - Missing Cleanup: Event listeners accumulated across navigations without removal, causing duplicate handlers and memory leaks.
- Custom Element Re-registration: Custom elements were redefined during navigation, causing re-registration errors.
- WebGL Context Loss: WebGL contexts were not preserved correctly during DOM swaps, leading to incorrect sizing and rendering issues.
- View Transitions API Limitations: CSS animations and WebGL contexts were affected by DOM swaps during view transitions.
Solution
Dual Event Listener Pattern
A dual event listener pattern was implemented to handle both initial page loads and client-side navigation, ensuring components are reinitialized correctly.
Lifecycle-Aware Cleanup
Lifecycle-aware cleanup was added to remove event listeners and prevent memory leaks and conflicts during navigation.
Custom Element Registration Guards
Custom element definitions were wrapped with existence checks to prevent re-registration errors during navigation.
React Component Container Fix
A dedicated wrapper component was created for React-based WebGL canvases to ensure they maintain correct dimensions and functionality during navigation.
Critical CSS Overrides
CSS overrides were applied to prevent incorrect sizing and ensure consistent behavior across different routes.
Outcome: The implementation successfully resolved the issues with D3.js visualizations, React components, custom elements, and event listeners, ensuring smooth SPA-like navigation while maintaining component functionality.