To prevent building our Angular-App multiple times for different environments, we tried to forgo injecting environment-specific variables (e.g. service endpoints) into our app with regular fileReplacements
and instead load those environments from assets (/assets/environment.js
in our case).
The approach is outlined in posts like this or this.
The environment.js is very simple. It's included in a <script>
tag in our index.html to ensure it's loaded and executed before any angular-code and it simply sets a property of window (yay global variables!)
window.env = {
serviceUrl: 'https://production.example.com/api'
}
This works very well with one critical exception. There are modules in our application that require access to those environment variables when setting up:
@NgModule({
imports: [
ExampleModule.forExample({
serviceUrl: window.env.serviceUrl,
}),
],
...
})
export class AppModule { }
This will fail because window.env is not present/undefined
at AoT compilation.
Is there any way to work around this issue?
Most of our applications are heavy so we don't want to switch to JiT compilation and we'd also like to keep builds to a minimum because they can take up to 20 minutes for certain projects.
After basically giving up we found NGSSC (https://github.com/kyubisation/angular-server-side-configuration).
NGSSC is able to tokenize variables during the AoT-Build. When deploying the app to a specific environment, these tokens can be replaced with the actual variable values by calling ngssc insert
.