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.
1. By proxy (what happens by default)
Section titled “1. By proxy (what happens by default)”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.
3. By runtime configuration
Section titled “3. By runtime configuration”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.tsis preferred. The environment check warns you if the one you declared is versioned, or if it doesn’t exist.
Which one is yours
Section titled “Which one is yours”- Does your front-end start with
ng serveand 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.