Configuring Client Side Routing on Apache (.htaccess)
Use rewrite rules to properly host your React, Angular, or Vue client side routing applications on Apache.
In the world of Single Page Applications (SPAs) it's important to understand that our application's routes are all served from the same HTTP route, which is generally an index.html
file hosted at the root of our domain (https://some-domain.com/
) that's generated from whatever build command you've used to generate the SPA application, such as create-react-app, Angular, or Vue build commands.
In a single-page application, we might have a route for user login at /login
, but this can lead to some complications once the application has been deployed to a web host.
This issue often occurs in the following situation.
Whenever I click a link from within my application to go to my route, the application loads the page fine. However, if I try to navigate directly from my browser, I receive an HTTP 404 response error.
So what's happening here?
The application loads correctly when you click a link or button because modern client-side routing libraries can intercept the navigation event before the browser moves away from the page. They also update the browser's URL to maintain the appearance of navigating to a different page, ensuring that the forward and back functions of the browser work as expected.
The application doesn't load correctly when you navigate to a route in the browser because the server isn't set up to handle requests for that route. This means:
There isn't a static file directory on the server for the route (like
/login
).- Note that most shared hosting providers treat all hosted content as static file directories.
There isn't a server-side process in place to direct the incoming path to server-side logic that sends HTML back to the browser.
.htaccess Rewrite Configuration
In Apache, commonly used by most shared hosting providers, there's a special file named .htaccess
that lets us change how incoming HTTP requests are handled. This file enables us to set up our single-page applications to be correctly managed by our single page (index.html
).
The .htaccess
file syntax can be a bit tedious to understand.
In order to use client side routing on Apache, we need to modify our .htaccess file to rewrite (this is different than redirect) all incoming traffic into our site to the index.html
page.
A redirect informs the client about a change in the resource's location, causing the browser to make a new request to the updated URL, while a rewrite, on the other hand, serves content from a different source internally while keeping the original request URL unchanged in the client's browser.
The .htaccess rules that we need to apply in order to support client side routing is as follows.
RewriteEngine On
# Skip rewriting if the request is for a real file or directory
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# Rewrite everything else to index.html
RewriteRule ^ index.html [L]
Here's a breakdown of what this does:
RewriteEngine On
enables the rewrite capabilities of Apache.The first two
RewriteCond
lines are conditions that check if the requested filename does not exist as a file (!-f
) and does not exist as a directory (!-d
). These conditions ensure that direct requests for real files or directories on the server (like images, CSS, or JavaScript files) are served normally, bypassing the rewrite rule.RewriteRule ^ index.html [L]
is the rule that rewrites all other requests (those that do not correspond to actual files or directories) toindex.html
, allowing your client-side routing to take over. The^
pattern matches any request, and[L]
signifies that this should be the last rule applied if the condition matches.
This setup is common in single-page applications (SPAs) that use frameworks like React, Angular, or Vue.js, where client-side JavaScript handles most routing.
Supporting HTTPS
It's also important to call out that many times you'll need to rewrite HTTP requests over to HTTPS. Let's add those rules to our .htaccess config also.
RewriteEngine On
# Enforce SSL by redirecting HTTP to HTTPS
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
# Skip rewriting if the request is for a real file or directory
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# Rewrite everything else to index.html
RewriteRule ^ index.html [L]
This new rule checks if HTTPS is "off" (meaning the request is made over HTTP) and redirects to the HTTPS version of the URL, effectively enforcing SSL for all incoming requests.
This redirection is done using a 301 HTTP status code, which indicates a permanent redirect. This tells the browser (and search engines) that the page should only be accessed via HTTPS in the future, enhancing the security of the user's connection to the website and contributing to better SEO for the site.