I have create a simple Nginx config file to server an Angular like so:
server {
listen 80;
listen [::]:80;
root /path/to/apps/myapp/current/dist;
access_log /path/to/apps/myapp/current/log/nginx.access.log;
error_log /path/to/apps/myapp/current/log/nginx.error.log info;
index index.html;
location ^~ /assets/ {
gzip_static on;
expires max;
add_header Cache-Control public;
}
location / {
try_files $uri $uri/ =404;
}
}
And all works fine as expected. because I'm using Angular UI Router, I'd like to forward all pages to index.html
so Angular will take over (so a request to example.com/users/new
will be redirect by Nginx to index.html
, for Angular UI to handle it) for pages reloads, links, etc.
How can I achieve this?
I've playing around with options like:
server {
#implemented by default, change if you need different ip or port
#listen *:80 | *:8000;
server_name test.com;
return 301 $scheme://www.test.com$request_uri;
}
As specified in this answer. But I couldn't anything similar to work based on all requests.
Suggestions will be much appreciated.
You need to add the router to the end of your try_files
directive, like this:
location / {
try_files $uri $uri/ /index.html;
}
See this document for more.
You've nearly got it. try_files is the correct one to use, as Richard shows, you just needed to add your index.html in the list. However, there is no need to remove the =404 from the end, in fact, its better not to.
location / {
try_files $uri $uri/ /index.html =404;
}
Once the above change is implemented, reload the config with sudo nginx -s reload
- $uri will try the request as a file, if this fails, it moves to the
next one.
- $uri/ will try the request as a folder /index.html will
then be tried, which sends all requests to your index.html where your
angular app will be able to route things (also make sure you use
html5mode to avoid the use of # in the url.
- =404 will be your final fallback, basically saying: I've tried this as a file, folder, and via index.html. If index.html fails/does not
exist for whatever reason, we will serve a 404 error.
Why =404?
If all goes well, the last one is never used, and routing will just try file, folder, angular app. And that would be it. But I see it as good practice to have the =404 on the end to cover all bases.
Important note about index.html catchall
Regardless of whether or not you use the =404 in try_files, by directing everything to index.html, you basically lose the ability to serve 404 errors from your webserver, unless index.html does not exist (which is where =404
comes in). This means that you will need to handle 'Not Found' urls and missing pages within Angular JS, and you need to be ok with the fact that the error page you use will return a HTTP 200 response, rather than 404. (This is because the moment you direct to the index.html, you've served a page to the user, thus 200).
For added reassurance on the above, google try_files angular js and you will find most examples incorporate =404.
References:
- http://nginx.org/en/docs/beginners_guide.html#control
- http://ajbogh.blogspot.ca/2015/05/setting-up-angularjs-html5-mode-in.html (just one example)