Angular-cli: Mixing configurations

Created on 3 May 2018  路  21Comments  路  Source: angular/angular-cli

Versions

v6

Observed behavior

You cannot use --prod with a custom configuration since --prod is an alias for --configuration=production. This means that if I make a custom configuration for my project, I need to duplicate it for the prod build to include everything from the production configuration.

Desired behavior

I'd like to be able to mix configurations, where each one overwrites the precedent. For example with -c=prod,xxx, where xxx overwrites production values if they both define the same property

For example if I'm doing i18n, I would like to have something like that:

          "configurations": {
            "production": {
              "fileReplacements": [
                {
                  "replace": "src/environments/environment.ts",
                  "with": "src/environments/environment.prod.ts"
                }
              ],
              "optimization": true,
              "outputHashing": "all",
              "sourceMap": false,
              "extractCss": true,
              "namedChunks": false,
              "aot": true,
              "extractLicenses": true,
              "vendorChunk": false,
              "buildOptimizer": true
            },
            "fr": {
              "aot": true,
              "outputPath": "dist/my-project-fr/",
              "i18nFile": "src/locale/messages.fr.xlf",
              "i18nFormat": "xlf",
              "i18nLocale": "fr",
              "i18nMissingTranslation": "error"
            }
          }
        },

And use -c=production,fr, or --prod -c=fr

angulacli devkiarchitect 2 (required) feature

Most helpful comment

I think this issue needs more attention.
Our angular.json file is currently 14048 lines and growing, not even counting the multitude of i18n configurations that are yet to be implemented.

All 21 comments

@buu700 was also interested in something similar in https://github.com/angular/angular-cli/issues/10559

That would be a great addition.
At the moment (in the 1.x.x config) I have a setup with many apps sharing a lot of the same (duplicate) configuration. I was hoping that 6.0 would provide a way to share common configuration between app flavors, but at this point, the config will just be even more bloated than before.
In my case it's not the i18n files (although potentially it will be in the future), but assets, styles and environment files that changes between customers (apps).

Alternative to using multiple configurations they could have a extend feature as mentioned here: https://github.com/angular/angular-cli/issues/11233 . Definitely need either one of them.

@hansl Personally i would set this issue to priority 2 (required). Instead of:

ng build -c=prod,theme1,en and ng serve -c=theme1,en

we have to make TONS configurations with TONS of duplicate code:

"build": {
   ...
    "configurations": {
        "theme1": {
            // Asset configuration theme 1
        },
        "theme1-en": {
            // Asset configuration theme 1
            // Load language files EN
        },
        "theme1-prod-en": {
            // Production settings
            // Asset configuration theme 1
            // Load language files EN
        },
        "theme1-de": {
            // Asset configuration theme 1
            // Load language files DE
        },
        "theme1-prod-de": {
            // Production settings
            // Asset configuration theme 1
            // Load language files DE
        },
         "theme2": {
            // Asset configuration theme 2
        },
        "theme2-en": {
            // Asset configuration theme 2
            // Load language files EN
        },
        "theme2-prod-en": {
            // Production settings
            // Asset configuration theme 2
            // Load language files EN
        },
        "theme2-de": {
            // Asset configuration theme 2
            // Load language files DE
        },
        "theme2-prod-de": {
            // Production settings
            // Asset configuration theme 2
            // Load language files DE
        },
    }
},
"serve": {
    "builder": "@angular-devkit/build-angular:dev-server",
    "options": {
        "browserTarget": "myapp:build"
    },
    "configurations": {
        "theme1": {
            "browserTarget": "myapp:build:theme1"
        },
        "theme1-en": {
            "browserTarget": "myapp:build:theme1-en"
        },
        "theme1-de": {
            "browserTarget": "myapp:build:theme1-de"
        },
        "theme1-prod-en": {
            "browserTarget": "myapp:build:theme1-prod-en"
        },
        "theme1-prod-de": {
            "browserTarget": "myapp:build:theme1-prod-de"
        },
        "theme2": {
            "browserTarget": "myapp:build:theme2"
        },
        "theme2-en": {
            "browserTarget": "myapp:build:theme2-en"
        },
        "theme2-de": {
            "browserTarget": "myapp:build:theme2-de"
        },
       "theme2-prod-en": {
            "browserTarget": "myapp:build:theme2-prod-en"
        },
        "theme2-prod-de": {
            "browserTarget": "myapp:build:theme2-prod-de"
        },
    }
}

And this was just 2 themes and 2 languages. It multiplies for each other theme or language...

Looks like our situation. 30+ configurations x 6 different environments = wall of config

Alternative to using multiple configurations they could have a extend feature as mentioned here: #11233 . Definitely need either one of them.

Unless I am misunderstanding, I don't think this will reduce the number of configurations, only duplication within the configurations.

I would prefer the proposed solution in this issue, which should allow for significantly less configurations.

+1

would definitely need such a feature!

I think that it should be mentioned in the documentation in Deployment because nowadays it is in i18n:

For production builds, you define a separate production-fr build configuration in the CLI configuration file, angular.json.

I also think this feature is essential to write maintainable, clean configurations, especially when you implement internationalization.

I wonder if this problem could also be solved by allowing angular.json to be written in YAML (angular.yaml), as YAML lets you declare anchors to duplicate properties.

I agree with @MickL that this is beyond a "nice to have". Even something as trivial as changing the default locale (for pipes) explodes into a barrage of cut'n'paste all over the already-not-too-friendly angular.json.

@mgechev it would be cool to be able to inherit

"build": {
  ...
  "configurations": {
    "production": {
      (...)
    },
    "pl": {
      "extends": "config/pl.angular.json",
      (...)
    },
    "en": {
      "extends": "config/en.angular.json",
      (...)
    }
  }
}

I think this issue needs more attention.
Our angular.json file is currently 14048 lines and growing, not even counting the multitude of i18n configurations that are yet to be implemented.

Any news on that? I have a workspace with many libraries and I have to duplicate test configs and other similar stuff for all of them.

we are facing the same problem. for the time being is there any workaround/best practice to avoid copy and paste a great amount of the same configuration parts that someone could share?

thank's a lot in advance

I'd like to throw my hat in support of the solution proposed in #11233 where we have the ability to extend configs/use base configs in angular.json (rather than on the command line as suggested here). Since that issue was closed in favor of this one, I'm commenting here.

This functionality would be so convenient for nx projects that may contain hundreds of libs all requiring the exact same configuration (e.g. for tests). @filipesilva, please let us make this happen.

As a workaround I store angular.json as javascript object in angular.ts script. It allow me to store production configuration in single constant and reuse it with typescript spread syntax, i.e.

configurations: {
    production: ...productionConfiguration(),
    anotherProductionConfiguration: {
        ...productionConfiguration(myParams),
        otherProperty: 'value'
    }
}

I compile it and run as node angular.js before build and serve commands (I use npm run build, npm run start which internally call this task).

This feature would also solve the current issue that you can't use a global assets definition in options together with a build-specific assets definition. I assumed the assets in options would always be loaded, however they are ignored in case there is an assets array in your build configuration

"options": {
    // will only load for production, not for integration
    "assets": [
        {
            "output": "assets",
            "glob": "**/*",
            "input": "src/assets"
        }
    ]
},
"configurations": {
    "integration": {
        "assets": [
            {
                "output": "json",
                "glob": "someFile.json",
                "input": "src/json"
            }
        ]
    },
    "production": {}
}

I personally think that angular.json should be a angular.js that exports an object. I noticed this was requested here: https://github.com/angular/angular-cli/issues/12943

This means we can do what @ashasvishnyakov described:

configurations: {
    production: ...productionConfiguration(),
    anotherProductionConfiguration: {
        ...productionConfiguration(myParams),
        otherProperty: 'value'
    }
}

I compile it and run as node angular.js before build and serve commands (I use npm run build, npm run start which internally call this task).

@asvishnyakov Would you have the awesomness of providing a running gist?

@abariatti I cannot show you full code because of my contract limitations, but the idea is simple.

Add angular.ts and put your current json to it as typescript object, i.e.

const angularJson = { ... };

Then add output to the angular.json:

const fs = require('fs');
const angularJson = { ... };
fs.writeFileSync('angular.json', JSON.stringify(angularJson, null, 4), 'utf8');

Now, in packages.json add tasks to compile and run it:

{
  "scripts": {
    "angular-json:build": "tsc --moduleResolution node --lib es2018 --outFile angular.js angular.ts",
    "angular-json:transform": "npm run angular-json:build && node angular.js",

Then run angular-json:transform task manually every time you change angular.ts or add it before every build or run task in packages.json:

{
  "scripts": {
    "build": "npm run angular-json:transform && ng build"

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._

Was this page helpful?
0 / 5 - 0 ratings

Related issues

MateenKadwaikar picture MateenKadwaikar  路  3Comments

rajjejosefsson picture rajjejosefsson  路  3Comments

gotschmarcel picture gotschmarcel  路  3Comments

jbeckton picture jbeckton  路  3Comments

daBishMan picture daBishMan  路  3Comments