The oldest web apps - web email clients being probably the canonical and most familiar example - didn't do dynamic refresh at all, because there was no way to fetch data from the server, so you couldn't do it even with JS. Any user action that required any part of the page to be updated involved a (very visible) whole page refresh. You could limit the scope of refresh with frames to some extent, but it was still very noticeable.
Microsoft introduced XMLHttpRequest in 2000 for this exact reason - its original purpose was to allow the newly introduced Outlook web UI to fetch data from the server and use that to update the DOM as needed. This was then enthusiastically adopted by other web app authors (most notably Google, with GMail, Google Maps, and Google Talk), and other browsers jumped onto the bandwagon by providing their own largely compatible implementations. By 2006 it was a de facto standard, and by 2008 it was standardized by W3C.
The pattern was then known as AJAX, for "asynchronous JS and XML". At first web apps would use the browser API directly, but jQuery appeared right around that time to provide a consistent API across various browsers, and the first SPA frameworks showed up shortly after (I'm not sure if I remember correctly, but I think GWT was the first in 2006).
Oh, I'm familiar with the history. I was thinking maybe you had similar concerns (lack of dynamic content) with something modern like HTMX which is a modern take on Server Side Rendering -- but it does in fact include mechanisms for AJAX-like calls.
While this is mostly true, there were similar techniques even before XMLHttpRequest. iframes could communicate with parents, and also JSONP. I think JSONP was mostly pioneered as a technique after XMLHttpRequest, but the iframe trick did work (I even used it! just a tiny 16x16 iframe communicating with the parent element by calling functions on window.parent, worked great on IE5).