Obviously, there are a lot of mod rewrite discussions and answers all across the web. However, I am having a hard time grasping them. So I thought I would ask here.
The problem with this answer is that you still want 404s for file-not-found. Depending on how a person is building their front-end application, its very common for people to have css or other files return 404, especially if they are building larger dynamic applications, or are outsourcing the front-end work. Also, angular routes are usually not related to anything on the file system. The above may work if you narrow it down to a single directory. For instance, I will often use a common prefix for all angular routes that is not related to the file-system layout (/ajs/). If you can do
<Directory /ajs>
FallbackResource /app/index.html
</Directory>
Then it would make more sense, but that doesn't seem to work for me. Using a common prefix also makes the backend rules much simpler no matter the backend. For instance, you can setup a simple server forward controller if you aren't using a reverse proxy. And it makes modeling your apache rewrite rules simple. For instance:
RewriteEngine On
RewriteRule ^/ajs/(.+)$ /index.html
That said, I haven't seen the directory/fallback method before, so am interested to explore it for when the only rewrite I need is for the angular forward. Thanks!
From my production server:
<VirtualHost *:80>
ServerName XXX.com
DocumentRoot /home/www/XXX.com/www
# Local Tomcat server
<Location /api/>
ProxyPass http://localhost:8080/api/
ProxyPassReverse http://localhost:8080/api/
</Location>
RewriteEngine On
# If an existing asset or directory or API is requested go to it as it is
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f [OR]
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -d [OR]
RewriteCond %{REQUEST_URI} /api
RewriteRule ^ - [L]
# If the requested resource doesn't exist (and is not API), use index.html
RewriteRule ^ /index.html
ErrorLog logs/XXX.com-error.log
CustomLog logs/XXX.com-access.log common
</VirtualHost>
Please note, that "!" before "/api" in the accepted answer is incorrect.
The accepted answer to this question is outdated. You can now use the FallbackResource directive in your conf file with Apache 2.2.16+.
FallbackResource /app/index.html
If you want the FallbackResource directive to ignore the "/api" routes:
<Directory /api>
FallbackResource disabled
</Directory>
This is a slight variation and elaboration of Scott Ferguson's excellent answer. I find it easier to use the <Location>
directive than <Directory>
. The <Directory>
directive takes an absolute path name which can be different in different machines.
So, let's say that your Angular app's index.html
is in my-app/index.html
under the document root of your web server. And you wish to access the app using http://localhost/my-app
.
First of all make sure that your base href is "/my-app/". Next, in your httpd.conf
file add:
<Location "/my-app">
FallbackResource /my-app/index.html
</Location>
This will cause Apache to load index.html if any resource under /my-app/
can not be found.
If you are making API calls under the same path, such as say /my-app/api
then you should probably not apply the FallbackResource
rule for these calls. So add:
<Location "/my-app/api">
FallbackResource disabled
</Location>
Here's something to get you going (put this inside your /.htaccess file):
Options +FollowSymLinks
IndexIgnore */*
RewriteEngine on
# if a directory or a file exists, use it directly
RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteCond %{REQUEST_URI} !/api
# otherwise forward it to index.html
RewriteRule ^.*$ - [NC,L]
RewriteRule ^app/. /app/index.html [NC,L]
NOTE: For newer Apache versions see also the next answer, which uses the much easier FallbackResource