'Nginx config to serve an Angular app under an URI prefix where files are generated in the same folder as "index.html"

There are a lot of Angular/Nginx examples on the web but I'm still unable to make my config work. I use Angular 13.

In angular.json:

  • outputPath is "www"
  • baseHref is "/my-project/"

and for the assets:

"assets": [
  {
    "glob": "**/*",
    "input": "src/assets",
    "output": "assets"
  },
}

I run ng build. Files are generated under www, amongs them:

  • index.html
  • runtime.js
  • polyfills.js
  • main.js
  • styles.css
  • assets/...

My app has many routes. For example:

  • /my-project/page1
  • /my-project/page2
  • /my-project/page3

My question:

How can I configure nginx.conf so the dynamic routes of the application are all handled by index.html, but the regular files inside the same www folder are served directly?

The nginx.conf example you often see online is similar to:

server {
    // ...
    root /usr/src/app/www;

    location /my-project {
        try_files $uri /index.html;
    }

    location /my-project/assets {
        alias /usr/src/app/www/assets;
    }
}

But when I try that, it seems that even the regular files are redirected to index.html and HTML is returned!

For example: http://localhost/my-project/runtime.js will return the full HTML of www/index.html not the javascript from www/runtime.js.

What is missing?



Solution 1:[1]

That's because you do not understand how nginx root, alias and try_files directives actually works. Check the difference between root and alias yourself, and take into attention that the last parameter of the try_files directive in contradiction of all the previous treated as a new URI to re-evaluate. What you should do instead is to use my_project as your outputPath too. After that, assuming the full path to your application is /usr/src/app/my_project, you can use the following configuration:

location /my_project/ {
    root /usr/src/app;
    try_files $uri /my_project/index.html;
}

This way your app will be available under http://localhost/my-project/ URL (note the trailing slash). Your global root can be set to any other directory, it won't affect your application. If you want it to be available even if the trailing slash is missing, you can add an additional redirect:

location = /my_project {
    return 301 /my_project/;
}

If your files structure allows you to place the my_project directory under your global web root, things can be even more simple, the above block isn't necessary (as well as the additional root directive) since nginx will made the redirect automatically.

If for some reason you can't place your app into the folder named my_project, you can use an alias directive. However this is better to be avoided because of several side effects when you are using alias and try_files directives together. Nevertheless configuration required for an angular app should not face any of those side effects so assuming your project path is /usr/src/app/www the following configuration should work:

location /my_project/ {
    alias /usr/src/app/www/;
    try_files $uri /my_project/index.html;
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1