Skip to content

How to route the calls of an Angular front-end

With a backend micro, pointing a dependency at local, cloud or a mock is straightforward: Aseptic injects the resolved URL when it starts it, as a system property (-D) or as an environment variable. An Angular front-end has nowhere to receive it: its calls leave from the browser, and the URL they point at was decided at build time or lives in a file the app itself serves.

That’s why Aseptic routes it differently. There are three ways, chosen in this order, which goes from least to most intrusive. The first two don’t touch your repository.

Aseptic writes a proxy.conf.json into .aseptic/.runtime/ —outside your repo— and passes it to ng serve with --proxy-config. That file maps each dependency’s API prefix to whatever destination the scenario resolved for it: the local micro, the cloud or the mock server.

For it to work, each of the front-end’s dependencies must declare as its local path the prefix the app calls with (for example /api/orders). It’s the one thing to review after adding the front-end: autodetection can’t guess it from the code, so it leaves it for you to confirm.

There’s nothing to switch on. If the scenario resolves the dependency to mock, the front-end talks to the mock without the front-end —or you— noticing.

2. When ng serve doesn’t accept the flag

Section titled “2. When ng serve doesn’t accept the flag”

Some front-ends don’t start with Angular’s dev server but with a builder of their own —Module Federation being the typical case—, and that builder doesn’t know --proxy-config. Passing it doesn’t degrade routing: it stops the micro from starting, with an Error: Unknown argument: proxy-config. And since one that doesn’t come up drags along whatever depended on it, the scenario ends up pointing somewhere else.

Aseptic looks at the builder declared in angular.json (or workspace.json, on Nx) and only stops passing the flag when it has proof that it isn’t accepted. If there’s no file, it can’t be read, or the project can’t be identified, it passes it as always: dropping it “just in case” would leave front-ends that work today unrouted, and that silent failure is worse than the noisy one it avoids.

When it doesn’t pass it, the scenario still starts and the log says so: that front-end is left unrouted, and right there it points you at the way out.

In Micros → Local startup configuration you can force it with Routing via ng serve proxy:

  • Automatic — deduced from the builder. This is the normal one.
  • Yes, pass the flag — for a builder that does accept it and isn’t on the list.
  • Never pass it — for one that doesn’t.

If your app asks for its configuration at startup —the APP_INITIALIZER pattern that does a fetch to a path and gets the URLs from there—, say so in Runtime configuration path. Aseptic serves a JSON with the already-resolved URLs there and routes that path through the same proxy.

It’s a virtual path, not a file in your repository: that’s precisely why it can be intercepted. And there are two ways of serving it:

  • Dependency JSON (the default): an object of dependency id → resolved URL. It’s a contract between your app and the manifest: the app has to know those keys.
  • Gateway-relative: for apps that already carry their configuration in an asset of their own (assets/config/environment.js) with the URLs hanging off an API gateway. Aseptic serves that same asset, verbatim, plus a trim that at runtime turns the gateway’s origin into a relative path, so the proxy catches it by prefix. If the repo ships that file, it’s autodetected when you add the micro and there’s nothing to set up.

4. Rewriting the environment (last resort)

Section titled “4. Rewriting the environment (last resort)”

One case is left that none of the above reaches: front-ends that do not accept the proxy flag, do not ask for configuration at runtime, and resolve the backend with URLs compiled at build time, inside the active profile’s environment. There the only way is to touch that file.

Aseptic does it in a bounded and reversible way, and only if you ask for it: you declare it in the manifest with stack.environmentRewrite, saying which file and which fields point at which dependency. On start it replaces the value of those fields with the resolved URL; on stop, it leaves it as it was. There’s no control in the interface on purpose: it’s opt-in and declared by hand.

Two safeguards worth knowing:

  • It survives abrupt shutdowns. The original is backed up outside the repository (.aseptic/.runtime/env-backups/) and restored both on stop and on the next start: if the app was killed with the file modified, the first thing it does is put it back.
  • Better a profile that isn’t versioned. The file stays modified while the scenario runs, so a git-ignored environment.local.ts is preferred. The environment check warns you if the one you declared is versioned, or if it doesn’t exist.
  • Does your front-end start with ng serve and call through a prefix? Number 1, with nothing to do.
  • Does it start but not route, and the log mentions --proxy-config? Number 2, and if your builder does accept it, force it.
  • Does your app ask for its configuration at startup? Number 3.
  • None of the above and the URLs are compiled inside? Number 4.