x)- [ ] bug report -> please search issues before submitting
- [x] feature request
@angular/cli: 1.3.2
node: 7.8.0
os: darwin x64
Not a failure.
Not a failure
With modern DevOps and infrastructure automation, it is easy to create a new environment on the fly. To better support this new world, it would be preferred to have one build package and provide the configuration at the point of deployment. This is a more flexible model, which fits a more dynamic environment.
Imagine you are trying to reproduce an issue, but you need to have a copy of production to duplicate the issue, as it only shows up in production. With modern infrastructure tools, it is easy to create a replica of production in the cloud and all the other services on the Internet. With the current design the following steps are required to create a new environment:
evironment.{env}.ts file from the new settings of step 1 In the process above, you risk creating a build that differs from the one in production, which could cause issues and loss of time. The new environment services are first, since you may get tokens and other settings from these services, which need to go into the environment file. This design requires knowledge of all your environments to be known and static, which is fine in a small project, but it is inflexible in this modern era.
By using a runtime environment settings, we reduce the need to create a new environment file and build, which may lead to issues. Here is an example flow for runtime environment settings:
In this example, the new environment has an exact copy of the build package, not a new build. Runtime environment settings, allow for easy creation of new environments to meet current project needs.
Nothing else to add.
This can be achieved currently without any modifications to the CLI. One method would be to create an _application configuration_ service (e.g., AppConfig) that can be injected throughout the application as necessary. It would use the built-in CLI environment functionality for build time settings. But it would also, upon application startup, fetch a configuration file (JSON or otherwise) that can be deployed with your application by adding the file as an asset. This configuration file would contain any settings which would need to be run-time configurable. The aforementioned service can abstract away the underlying mechanics of retrieving and normalizing the settings; and in addition, can optionally use the build time settings as defaults and defer to the run-time settings only if present. This allows for simplified deployment if desired and also run-time flexibility if needed.
An additional CLI feature that could be useful in this scenario (and potentially others), would be to expand the environment option to allow the addition of assets per environment. Allowing, for instance, a production environment to add a different set of files to the output than a development or staging environment. However, with the defaulting concept as explained above, this not necessarily a requirement but simply opens up an additional implementation option for the desired use case.
my 2c, I swear by 12factors Config in my apps, and I totally like having run-time control from environment variables. With a client side app you don't actually have control of the runtime environments. In practice, I've found run time setting definition difficult in for ng apps, specifically the startup delay when your app has to go look up configuration. Usually, I set environment at build time and package unique dev, qa, and prod assets. As a developer I try to ensure the only things that charge are configuration settings and include/exclude dev instrumentation.
Agree with this 1000%. In AngularJS apps, I've usually deployed them on PHP/Python/ASP.net MVC server with just one "backend" controller that served up a JS file populating a global environmentSettings constant (those actual settings would be stored in a JSON/XML file read by the controller). I'm still trying to figure out the exact steps I'd take to do this in an Angular CLI project (as it's more complex than just including <script> tags). Also, it'd be nice to find a way to set environment variables at runtime without having any sort of back-end (just edit a JSON file), so SPA's could be deployed on an extremely lightweight HTTP server.
@jongunter
(as it's more complex than just including
Great stuff, @devoto13 and @tytskyi . I'll give it a try. Thanks for the suggestions!
My answer above allows for runtime settings without the need for a backend service, modifying index.html, or using webpack specific features. The key is to use an angular service to request the JSON file either on startup or on first use via the angular http service. In my projects I also add additional logic to the service to incorporate the CLI environment options, provide option defaults and helper functions, etc.
@clydin Would you mind giving more details on how you implement that? I'm coming fresh from an AngularJS world and I don't know Angular 4 specifics as well as I probably should.
I understand how you would request a JSON file via Http. However, there seems to be an annoying race condition that I need to have these settings available before I can use them (for example, before I make an HTTP request to our API, or redirect to a specific URL for authentication). I can make the settings an Observable and chain it into every service method (via switchMap) that returns an observable, but that seems awfully repetitive and possibly error-prone. If I were to use a route resolve at my root route for fetching this data, would that solve this problem?
Google for examples of using APP_INITIALIZER. It allows to execute some logic and return Promise. Angular application will not be initialized before this Promise is resolved. Like this one.
@devoto13 I got this working on my app and it worked great until I brought in ngrx/effects. Seems as though all of my effects classes (and their dependencies) are eagerly instantiated before the APP_INITIALIZER promise resolves, meaning that the environment settings are not available to some of my services and effects.
I'll play around some more...maybe this an issue I should file with the ngrx team.
Regarding ngrx/effects running before APP_INITIALIZER, there's an issue open here (I don't think it's solved in v4 yet): https://github.com/ngrx/effects/issues/152
I think the workaround sounds quite reasonable/usable, closing this issue/feature request.
Heya all, just want to mention that this issue was essentially a duplicate of https://github.com/angular/angular-cli/issues/3855, and there's some more discussion there.
This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.
Read more about our automatic conversation locking policy.
_This action has been performed automatically by a bot._
Most helpful comment
Google for examples of using
APP_INITIALIZER. It allows to execute some logic and return Promise. Angular application will not be initialized before this Promise is resolved. Like this one.