Single-page applications (SPA) are a popular approach to building modern websites. And it is not just a passing trend: SPAs have a number of advantages over traditional applications.
The disadvantages of this approach are also known. For example, SPAs may experience search engine optimization (SEO) issues, applications may take a long time to open on the first launch, and can burden users' devices.
But there are less obvious problems that can arise when developing a SPA. One such problem is broken anchor links.
Anchor links are used to navigate within a single page. They also allow you to link to a specific section of an external page. For instance, you can share a link to your landing page and immediately scroll the user to the section with information about the company.
If you try to implement anchor links in a simple SPA, they simply will not work. When following such a link, the browser will display the very beginning of the page and will not scroll to the target section.
Why is this happening?
When directly following an anchor link from external resources, the browser scrolls the page to the desired section immediately after the
DOMContentLoaded event occurs. This means that the document has been analyzed, the DOM is ready, and the synchronous and deferred scripts have been loaded and have just started executing. This is how anchor links work in Chrome and Safari, at least. At this moment, it is possible that the required element is simply not present in the document because not all resources have been loaded yet and not all scripts have had a chance to execute.
And during transitions between pages within a single application (that is, when using, for example, react-router in a single-page application), the browser attempts to navigate to the section by changing the URI before the new page has time to render.
If you follow the anchor link within the same page, then most likely there will be no difficulties, since in this case all page elements have already been drawn.
To solve this problem, you can write a script that will scroll the page to the intended element after the DOM has undergone all changes.
You can also take a ready-made package, for instance, react-router-hash-link for react-router. It fixes a number of problems related to the work of anchors in SPA on React. There are similar implementations for other popular frameworks.
However, the best option would be to render a full HTML page from the server using server-side rendering (SSR) or a static site generator (SSG). This can be done using Next.js, Gatsby, etc. In this case, when the browser tries to navigate to the desired section, the DOM will already be ready and the target element will be available.
This way looks more natural. We are not inventing anything new, but using existing mechanisms implemented in browsers long before single-page applications. With the help of modern solutions, we can 'restore' the original working principle of our websites, while maintaining the benefits of the SPA.