Angular with clean URL's using Apache's mod_rewrite
In Angular you have a really nice router which takes care of all the things you need. Prefetching data, guarding specific routes and it will even lazy load modules. That all works out of the box, which I think is really awesome.
When you are using Apache to serve your public/production environment you want to have beautiful clean URL’s, for example ‘whatwhat.app/page/3’. You need some additional configuration to make sure Angular’s routing also kicks in when people visit those pages directly and not coming through the index/homepage.
By default you will get a 404 page, because that file is not physically on the server. With mod_rewrite you can adjust this behavior in Apache, if that module is turned on (which is often the case). Configuration for Apache can be changed per folder using .htaccess
.
Apache’s mod_rewrite and .htaccess
Just copy the configuration below and drop it in a file named .htaccess
in the same folder containing your index.html
file. That’s it!
# Check if mod_rewrite module is available
<IfModule mod_rewrite.c>
# Turn the rewrite engine on and set URI base
RewriteEngine On
RewriteBase /
# Serve files when they are found
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f [OR]
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -d
RewriteRule ^ - [L]
# When file is not found, serve index.html instead
RewriteRule ^ /index.html
</IfModule>
Optional: Run your Angular app from a sub directory
You need some additional configuration for this, because Angular needs to know the path above it. The easiest way is to add a base tag in the <head>
tag of the index.html
like this: <base href="/app/path/">
. Where the path should be adjusted to match yours of course, make sure it is the path above your Angular app (which should be ignored).
Another way is to inject it, that can be easier if you have different configurations per environment (ex. dev/acc/prod). You can find more information in the Angular documentation: APP_BASE_HREF.
When using a sub directory also change that in your .htaccess
like this:
RewriteBase /
should change toRewriteBase /app/path/
.RewriteRule ^ /index.html
should beRewriteRule ^ /app/path/index.html
.- Make sure the
.htaccess
file is in the same directory as Angular’sindex.html
.
What mod_rewrite will do for Angular
For this of you who want a little background information about what is happening.
What Apache does is serving files to your visitors when they ask for it. In the case of a homepage like ‘whatwhat.app’ it will serve the index.html
. With the configuration from the .htaccess
it will change a bit:
- When a file is found Apache will serve that to your visitor, which will make sure assets like js, css and images can be loaded. That also includes your Angular project. That is done with the
RewriteCond
andRewriteRule
. Which will just use the URI from the request. - After that there is another
RewriteRule
as fallback and is only executed when a file is not found. It changes any URI to/index.html
. Which makes Apache look for theindex.html
file and serve that instead. In that case your Angular app is served to your visitor. - That is exactly what you want because when you move from ‘whatwhat.app/’ to ‘whatwhat.app/page/3’ Angular will do the work, but if you visit ‘whatwhat.app/page/3’ right away Apache will try to find it. Which it can’t. By serving your app instead, the Angular router will get loaded and take over and resolve it afterwards.
- Any 404 page is a route that can’t by found by the Angular router, which should also show an error page. That is up to you.
Even more possibilities
You can use hashtags routing too, which won’t be send to the server. That is an alternative in some cases and it can be good for security too (if you have params you don’t want to send to the server). I will probably write about this in a separate article as well.
Also using Angular’s i18n and want some clean URL’s? I have written an article called Serve Angular i18n with clean URL’s using Apache’s mod_rewrite.
I am working on articles for other webservers and CDN’s too, follow me on Dev.to or Medium to keep an eye out on those. Any tips or questions? Reach out to me on Twitter. Thanks for reading!