Click here to share this article on LinkedIn »

Does your Angular frontend talk to many backend services? Are you also using a reverse proxy like nginx or a Kubernetes Ingress to route requests to these services from different paths on the same domain? If so, then you should be aware of the proxy configuration options that Angular CLI provides to make local development a really great experience.

These configuration options are best illustrated through an example. If you are interested in the changes required, then see this commit on GitHub which shows the differences needed to setup proxying. This blog post will talk through that example in more detail.

Let’s take a frontend that is served at a path /catalog/ . The ‘Catalog Server’ is responsible for serving the static files (.js, .css, .html) and also provides an API that the frontend can use for retrieving environment specific config.

There are another two REST API servers that the frontend will make requests to: the ‘Video API’ and the ‘Library API’ available at the paths /video/ and /library/ on the same domain. These will yield book and film information that the catalog page will display.

By default, Angular CLI assumes that the frontend is served at a base path / i.e. it inserts <base href="/"> in the index.html . Hence, for example when https://mydomain.com/catalog/index.html loads, the browser will then request main.bundle.js from https://mydomain.com/main.bundle.js . But this will not be found at that location. The browser should request it from https://mydomain.com/catalog/main.bundle.js . This can be fixed by specifying the actual base HREF (in this case, /catalog/ ) and deploy URL in your package.json file:

"start": "ng serve --base-href /catalog/ --deploy-url /catalog/",

"build": "ng build --prod --base-href /catalog/ --deploy-url /catalog/"

If you run npm run start you should now see that it generates an index.html file with <base href="/catalog/"> and you should be able to access the page at http://localhost:4200/catalog/ . I’ve glossed over what exactly the deploy-url setting does. It has a similar effect on url(...) references in CSS to perform a rewrite (so check that this setting is correct if you are having trouble with CSS referencing assets such as fonts or images).

So it is already more closely resembling the structure with which we expect the services and frontend to be deployed in production. However, the local server that the Angular CLI has started to serve the static files knows nothing about what to do with the requests to GET /video/films or GET /library/books or even GET /catalog/config .

To handle those extra requests we must configure Angular CLI to proxy those requests to other servers that can understand and respond appropriately to them. To do this, create a a file proxy.conf.json in the root of your Angular CLI project, alongside the package.json file. In this example, the contents look like the following

{

"/library/*": {

"target": "http://localhost:10000",

"secure": false,

"logLevel": "debug",

"changeOrigin": true,

"pathRewrite": {

"^/library": ""

}

},

"/video/*": {

"target": "http://localhost:10001",

"secure": false,

"logLevel": "debug",

"changeOrigin": true,

"pathRewrite": {

"^/video": ""

}

},

"/catalog/api/*": {

"target": "http://localhost:5000",

"secure": false,

"logLevel": "debug",

"changeOrigin": true,

"pathRewrite": {

"^/catalog": ""

}

}

}

You also need to update your package.json to reference this file when running locally, like so:

"start": "ng serve --base-href /catalog/ --deploy-url /catalog/ --proxy-config proxy.conf.json",

Now when we run npm run start you can see in the command line that it sets up these proxy settings:

Proxies being setup on start

Now when you go to http://localhost:4200/catalog/ in the browser you can see in the command line that the server is making several proxied requests to other servers:

Requests received from the browser that are proxied to the relevant servers

The request to http://localhost:4200/library/books has resulted in a request being sent to http://localhost:10000/books and the response is then passed back to the frontend from the Angular CLI server. This happened because the configuration says for any path that matches /library/* then target the http://localhost:10000 server. It has an additional pathRewrite setting that says if the path matches ^/library (i.e. if it starts with /library ) then rewrite that portion with the empty string (i.e. remove it from the path), so /library/books is rewritten to /books in the request that is made to http://localhost:10000 .

The config is retrieved from http://localhost:4200/catalog/api/config which matches the proxy setting "^/catalog/api/*" . The pathRewrite setting indicates that /catalog at the start of the path should be replaced with the empty string before forming the proxied request, which becomes http://localhost:5000/api/config .

Obviously, these other servers must be running locally for the requests to work. Instead of targeting servers running locally, you could target a ‘Dev’ environment if you are not working on any changes to the REST APIs.

I think the new Angular CLI tooling is great and has made local development so much easier than it was in AngularJS. This is especially true when working with complicated deployment scenarios and this example shows that it is flexible enough to accommodate a lot of this complexity. Thanks for reading and I hope you found the above details useful for your own setups.

References

The full code for this example can be found at https://github.com/rars/demo-angularcli-proxy/

If you just want to see the changes that add this proxying to a fresh Angular CLI project, just look at commit 6008230 in that repository.

More documentation can be found at https://github.com/angular/angular-cli/blob/master/docs/documentation/stories/proxy.md