Skip to content

Commit 4ffbe62

Browse files
[TASK] Update hot reloading javascript to remember scroll position
The hot reloading currently only reloads the full page. However, it would be desirable when doing "live documentation" to reload the page and keeping the current scroll position in sync. The JavaScript is now adapted to locally store the current position, and restore it after page reload. The temporary sessionStorage is utilized for this, which is tab-specific. A small timeout ensures that if a page with locationHash is reloaded can properly jump to the stored position. Debug output is added while this feature is experimental. Also, the 'ws' URI is auto-detected so it can work on HTTPS and HTTP connections - this is queried via JavaScript and thus can work on reverse proxy setups.
1 parent dd4d374 commit 4ffbe62

File tree

1 file changed

+27
-4
lines changed

1 file changed

+27
-4
lines changed

packages/dev-server/src/Internal/HttpHandler.php

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -104,15 +104,38 @@ private function injectWebSocketClient(string $html): string
104104
//Read html and inject script before closing body tag
105105
$injection = <<<'EOT'
106106
<script>
107-
const socket = new WebSocket('ws://' + window.location.host + '/ws');
107+
const socket = new WebSocket((window.location.protocol === 'https:' ? 'wss://' : 'ws://') + window.location.host + '/ws');
108108
socket.addEventListener('message', function (event) {
109109
if (event.data === 'update') {
110-
console.log('Reloading page due to server change...');
110+
console.log('Reloading page due to server change... Stored scrollPosition: ' + window.scrollY);
111+
sessionStorage.setItem('scrollPosition', window.scrollY);
112+
sessionStorage.setItem('scrollURL', window.location.href);
111113
window.location.reload();
112114
}
113115
});
114-
</script>
115-
EOT;
116+
117+
// Restore scroll position after page loads. Note that sessionStorage is
118+
// browser-tab specific, so multiple instances should not affect each other.
119+
window.addEventListener('load', function() {
120+
const scrollPosition = sessionStorage.getItem('scrollPosition');
121+
const scrollURL = sessionStorage.getItem('scrollURL');
122+
123+
// Only restore if we're on the same URL (hot reload, not navigation)
124+
if (scrollPosition !== null && scrollURL === window.location.href) {
125+
console.log('Prepare to restore scrollPosition to: ' + scrollPosition);
126+
127+
// Use setTimeout to override hash scrolling that happens after load
128+
setTimeout(function() {
129+
console.log('Restoring scrollPosition to: ' + scrollPosition);
130+
window.scrollTo(0, parseInt(scrollPosition));
131+
}, 10);
132+
}
133+
134+
// Ensure local scroll position is reset, so other reloads to not carry state.
135+
sessionStorage.removeItem('scrollPosition');
136+
sessionStorage.removeItem('scrollURL');
137+
});
138+
</script>EOT;
116139
117140
return str_replace('</body>', $injection . '</body>', $html);
118141
}

0 commit comments

Comments
 (0)