On Importance Of HTTP Redirect In Single-Page Applications

Web development

The Important Part

Single-Page Applications (SPA) are by design operating within the scope of one entry point (URL). Though they usually do have pages (or screens or other ways to structure interfaces and information), and they do have a way of navigating through them via various routing libraries (e.g https://reactrouter.com/en/main or https://router.vuejs.org/) that also manages (and reacts to changes in) browser's history API.

The problem with that is the entry point: as long as the app is loaded, changes in URL in browser's history do not require page reload, and the application's code reacts to them and displays the page accordingly. But when the URL is loaded anew (or the whole page is reloaded in browser), the HTTP request goes to the new entry point which is just not there.

An example

Let's say I have an SPA on my website, which is served from index.html - meaning there's an index.html that launches JS code for the app. So because web servers interpret index.html as a default content for the directory, requests to https://mysite.net/ would serve index.html and everything would work.

Now if I have a "Contacts" tab in my SPA that uses /contacts path for routing, while SPA is open and manages the browser history its router will handle https://mysite.net/contacts and it will work. But when URL is (re)loaded by browser, it will ask the webserver for /contacts - and there's no such file on the webserver, so it will result in 404.

Things to remember

So unless there's a server-side rendering involved, SPA need rewrite rules on server to serve index.html on every URL, so the SPA could launch and its router could take care or URL parsing and displaying the desired page/tab.

Vue docs have a good selection of recipes for various web-servers: https://router.vuejs.org/guide/essentials/history-mode.html#example-server-configurations - for instance, for Apache it'd be adding following to .htaccess:

    <IfModule mod_rewrite.c>
        RewriteEngine On
        RewriteBase /
        RewriteRule ^index\.html$ - [L]
        RewriteCond %{REQUEST_FILENAME} !-f
        RewriteCond %{REQUEST_FILENAME} !-d
        RewriteRule . /index.html [L]

for Nginx

    location / {
        try_files $uri $uri/ /index.html;

For Node with Express could be a middleware and so on.

In Netlify case, there's also a dedicated documentation page for rewrites: https://docs.netlify.com/routing/redirects/rewrites-proxies/ - but in short, you need following in _redirects file in SPA root (make sure it's copied to target directory on build):

    /*    /index.html   200


Good thing would be to know about it before it hits you, though being able to quickly solve it after the fact (like what made me write this) is OK too 😄