New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support multiple environments in the same build #3855
Comments
|
This adds a large amount of complexity and for the listed use cases would require building multiple apps to support all desired locales/etc. Whereas it would most likely be preferred to have one built app that can support all desired locales/etc. Why not just import all the locales your app supports? |
|
Also AOT + I18n using the CLI is not really a complete solution at this point. |
Well, that's the approach that the angular team seems to have chosen for i18n: one separate bundle per locale, with the translations first extracted into a messages file, then translated, then reinjected in the templates at build time by the AOT compiler. Here's a quote from the angular.io i18n cookbook:
What am I missing here?
Because that would increase the bundle size, especially if many languages need to be supported, and because it's in contradiction with the design principle that I quoted above, which consists in creating one bundle per locale, and thus not to provide all the translations into a single application. |
|
My point on multiple apps was mainly geared towards the quantity of output builds via the use of the environment concept in this way. (i.e., x locales * y browsers * dev/prod = a large amount of builds to manage) If only a handful of locales are required bundling them all can be viable. They would be packaged in the vendor bundle and cached locally. This may be required either way as a translation may support multiple locales. The CLI is geared towards generating a production deployable app. The cookbook recipe provides a set of application "packages". For now with AOT, unfortunately, there is not much more that. The hope is the CLI will have first-class support for i18n and build an app containing the "packages" for all available translations. Another option, if you're plan is to use server-side code to provide the relevant app bundles, is to provide momentjs the same way. |
|
@clydin this is the current way of doing it for Angular (x locales * dev/prod). With Universal it would become much more easy to do what you're suggesting, but this is not the world we're living it right now. @jnizet what you're asking for makes sense, and I'd rather have another solution instead; being able to import an environment file from another environment, which is not currently possible. But if we were to support it, this would work: import {environment as devEnv} from './environment';
export const environment = Object.assign({}, devEnv, {
lang: 'fr'
}); |
|
@hansl, what i meant was that a developer shouldn't have to run |
|
Could, but we don't. Better support for i18n is not planned before the 1.0 final. For now the recommended way is to make a build for each locale you want to support. |
|
Thanks for your input, @hansl. For the record, I deal with the multiple bundles generation at a higher level: I have a gradle build that builds everything (backend + frontend), by delegating to angular-cli for the frontend. So my current, successful, strategy is to
I then have a server-side handler that detects the locale from the HTTP request, and serves the appropriate index-xx.html file. This suits my needs fine. The only, admittedly minor, inconvenience is that I can't statically import the appropriate moment locale JS file. I could hack a system where I would replace the environment.prod.ts file by the one containing the appropriate locale import, but I feel that this is something that angular-cli could be able to do by itself. |
|
@hansl I don't really understand the strategy you're suggesting, though. Where would I put the 4 lines of code that you posted, and how would I choose, from the command-line, that I want a prod build using the french locale-specific code? |
|
@jnizet let me expand upon that solution. Assuming the default: So the important bit is that the file in You can thus, not have Then you could do |
|
@filipesilva please correct me if I'm wrong, but that would still force me to write a prod-fr and a prod-en environment, in addition to the dev-fr and the dev-en, and thus would still lead to code duplication. |
|
@jnizet yes you would still need need to have The latter problem could be addressed by switching it up a bit though: together with these base files:
And then the 'combo' files: I understand that it might not be as clean as you would hope, but this solution is available today with no extra design or compromises. |
|
OK, I understand now. Thanks for your input @filipesilva . |
|
Was talking about this earlier in regards to Continuous Delivery and was given this issue to post my thoughts. Deployed an app to production via Heroku Pipelines (Review, Staging, Production) yesterday and have also done deployment pipeline via Bitbucket/Bamboo before. Bundling the environment config into a single package during build causes problems for deploying to a multitude of environments where only a config changes. Within Heroku and Bamboo, you build an environment agnostic package through a build process and then deploy that same package to different environments, only changing configuration as it goes through the pipeline. With the current bundling of environment config during build, it means we can't push an agnostic package and change config but we need to completely rebuild as the app makes it way through the pipeline. Keeping environment configs out of the build and simply copying them to |
|
@intellix I know that's a very popular approach and works great for the scenario you propose. Is there anything blocking you from using it from the CLI side though? The CLI does not have a specific facility for it but, architecturally, it shouldn't since that strategy is meant to be completely disconnected from the build step. I think you can have Although they are architecturally different, these strategies are not mutually exclusive and serve different purposes. For instance, using the separate config file you could never have different imports for each env, since that needs the build to be done differently. |
|
I think there's nothing blocking me from doing it today, i'll do as you said and then dynamically load in that config |
|
I would echo what @intellix posted, we use Bamboo for our CI and deployment pipeline with the added complexity that we have an Electron application which hosts an Angular 2 application bundled with Electron (i.e. through an MSI that the clients install). Because of this we find we are currently forced to build for each environment passing For information, we have several different environments including dev, int, test, stage, preprod, training and prod, and there are variants of some of these environments (e.g. for clustered servers), so this presents us a problem that we have to generate multiple builds and artifacts during the build. Has anyone else encountered this and found a solution? |
|
@StickNitro if you need drop-in config files, you can just put them in This way you don't have to rebuild your app, but you have to engineer your application to load config items at runtime. The CLI provides build-time configuration, runtime configuration is up to you to implement. |
|
This isn't necessarily a cli specific question, but what I'm curious about is, and maybe someone can clear this up for me, what if I need to provide different values at the NgModule metadata level. I'm assuming there' no way to do that with both aot & a build once deploy many pipeline? Like say I had As best as I can tell, you'd have to build for each env if you want to use aot, because I get the impression aot relies on the metadata provided in the NgModule to 'compile' the code, right? With JIT you could technically do something like, set up your server to attach a header specficying the env, have a config.js file where you xhr/ping the server to get the header, then in the NgModule file use that to provide the env in the browser while compiling. I'm pretty sure you can't do that with aot, and that's just fine, I just want to make sure I understand correctly, cause some of this stuff can get pretty confusing to me. |
|
TBH in our situation i'm about to run into this problem - we have 2 production servers - a staging and a live. Given Angulars predilection for build for an environment i have to build what is basically the same app twice. It takes about 4 minutes to build each one... and my entire build process is only 15 minutes in total.. so thats a pretty sizeable % i'm spending. I quite like Quang's option here. We're only deploying to an S3 bucket... so not really serving up right now to get clever with the server-side ideas.. and i want to be able to have this environment ready before the angular apps gets going.... by being a local file i replace during the deployment perhaps i can simply map it over the previous environment.... should work... saves me some time... Am i missing any down times, these files are so small a sync download really isn't going to be an issue. |
|
I wrote a solution for Angular Universal apps located at ng-env-transfer-state. It won't help directly with client only builds, but might help some others who are using Angular Universal. |
|
I am working on a project which is not yet live. The application has a quarterly release cycle and each quarter will have to do 10 different builds to ship it to customers. Unfortunately, the application is not deployed in cloud. Its a real challenge now. |
|
I made this a while back: Dockerfile FROM node:10 as build
WORKDIR /app
COPY package.json /app/package.json
COPY yarn.lock /app/yarn.lock
RUN yarn --frozen-lockfile
COPY . /app
RUN yarn build --prod --output-path=dist
FROM nginx:stable-alpine
WORKDIR /usr/share/nginx/html
RUN apk add gettext
COPY --from=build /app/dist .
EXPOSE 4200
CMD envsubst < index.html > index.html && nginx -g "daemon off;"index.html: |
jnizet commentedJan 4, 2017
OS?
Versions.
This is a feature request
I started internationalizing my application, and I met the following problem: when generating the bundle for the French locale (for example), I should include the locale-specific fr.js script of moment.js. Other libraries could also provide locale-specific JS files, or could need code that is specific to that locale (to internationalize a datepicker, for example).
I think the best way to do that would be to create an 'fr' environment file, simply containing
and to use
--env fr. Unfortunately, there doesn't seem to be a way to specify two different environments. And I wouldn't like to create a dev-fr environment, a prod-fr environment, a dev-en environment, a prod-en environment, etc.Another use-case for that would be to create separate bundles for browsers, containing the polyfills that are needed for different browsers, and thus be able to generate a production bundle, for the French locale, and the chrome browser. I'm sure other use-cases could exist.
So I think it would be nice if angular-cli allowed specifying several environments. This is BTW a feature that exists in other build tools (like Maven profiles, or gradle properties, for example)
What do you think? Is there another nice way to achieve that?
The text was updated successfully, but these errors were encountered: