Skip to content

Pass values from command line, environment and CLI config to code when build\serve #10521

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

Closed
Flybbit opened this issue Apr 29, 2018 · 5 comments

Comments

@Flybbit
Copy link

Flybbit commented Apr 29, 2018

Requirement
I have three app in project. They use shared code. AppA uses part A from shared code, AppB uses part B and third AppC uses both A and B parts. So I need something like conditional compilation to reduce bundle size for AppA and AppB.
Another requirement is to pass some parameters like connection address or build number to code.
Third one feature which could be nice to have is ability to define environment variable on computer and use it when build\serve. So on dev machine you can get only dev build - "safety barrier".

Possible solution
Webpack has DefinePlugin and it can help to implement all three features. We should just change CLI config schema

"defines": {
  "type": "array",
  "description": "defines",
  "items": {                             
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "Name of the def"
          },
          "value": {
            "oneOf": [{"type": "string"}, {"type": "number"}, {"type": "boolean"}],
            "description": "Value of the def for all targets"
          },
           "targets": {
            "type": "object",
            "properties": {
              "development": {
                "oneOf": [{"type": "string"}, {"type": "number"}, {"type": "boolean"}],
                "description": "Value of the def for development target"
              },
              "production": {
                "oneOf": [{"type": "string"}, {"type": "number"}, {"type": "boolean"}],
                "description": "Value of the def for production target"
              }
            }
          }
        }
  },
  "default": []
}

and add plugin in common webpack config

new webpack.DefinePlugin(
  appConfig.defines.reduce(
    (defines, item) => {
      if (item && item.name){
        let name = item.name;
        let value = item.targets ? item.targets[buildOptions.target] : item.value;
        if (typeof value === 'string') {
          value = JSON.stringify(eval(value));                      
        }
        defines[name] = value;
      }                  
      return defines;
    }, {}
  )
)

How to use:

  1. config your app
  "defines": [
    {
      "name": "DEFINE_OPTION",
      "value": true
    },
    {
      "name": "ENV_OPTION",
      "value": "process.env.ENV_OPTION"
    },
    {
      "name": "COMMAND_LINE_OPTION",
      "value": "buildOptions.command_line_option"
    },
    {
      "name": "CALC_OPTION",
      "value": "2 + 2"
    }
  ]
  1. Run
ENV_OPTION="my value"
ng serve --command_line_option=42

somewhere in your code

declare var DEFINE_OPTION: boolean;
declare var ENV_OPTION: string;
declare var COMMAND_LINE_OPTION: string;
declare var CALC_OPTION: number;


if (DEFINE_OPTION){
  //this code will be excluded by optimizer if !DEFINE_OPTION  
}

As bonus (?) you can define some logic (see CALC_OPTION). Another thing - access to buildOptions. It allows to get command line args fast and easy, but looks a bit dirty

Flybbit added a commit to Flybbit/devkit that referenced this issue May 13, 2018
1) pass parameter known only at build stage to source code using command line argument
   or environment variable
2) define different values in code for different apps and architects
3) strip off some parts of code for some apps and architects
How to use
angular.json:
"defines": [
  {
    "name": "DEFINE_OPTION",
    "value": false
  },
  {
    "name": "ENV_OPTION",
    "value": "process.env.TEST_ENV_DEFINES"
  },
  {
    "name": "COMMAND_LINE_OPTION",
    "value": "buildOptions._customCommandLineOption"
  },
  {
    "name": "CALC_OPTION",
    "targets": {
      "production": "283745620252 + 1",
      "development": "2 + 2"
    }
  }
]
code:
declare var DEFINE_OPTION: boolean;
declare var ENV_OPTION: string;
declare var COMMAND_LINE_OPTION: string;
declare var CALC_OPTION: number;
if (DEFINE_OPTION){
  //stripped off
}
run:
set TEST_ENV_DEFINES=env_value
ng build --_customCommandLineOption=42

angular/angular-cli#10521
Flybbit added a commit to Flybbit/devkit that referenced this issue May 13, 2018
…ment parameters to code

Add more control on build process:
1) pass parameter known only at build stage to source code using command line argument
   or environment variable
2) define different values in code for different apps and architects
3) strip off some parts of code for some apps and architects
How to use
angular.json:
"defines": [
  {
    "name": "DEFINE_OPTION",
    "value": false
  },
  {
    "name": "ENV_OPTION",
    "value": "process.env.TEST_ENV_DEFINES"
  },
  {
    "name": "COMMAND_LINE_OPTION",
    "value": "buildOptions._customCommandLineOption"
  },
  {
    "name": "CALC_OPTION",
    "targets": {
      "production": "283745620252 + 1",
      "development": "2 + 2"
    }
  }
]
code:
declare var DEFINE_OPTION: boolean;
declare var ENV_OPTION: string;
declare var COMMAND_LINE_OPTION: string;
declare var CALC_OPTION: number;
if (DEFINE_OPTION){
  //stripped off
}
run:
set TEST_ENV_DEFINES=env_value
ng build --_customCommandLineOption=42

angular/angular-cli#10521
Flybbit added a commit to Flybbit/devkit that referenced this issue May 15, 2018
…ment parameters to code

Add more control on build process:
1) pass parameter known only at build stage to source code using command line argument
   or environment variable
2) define different values in code for different apps and architects
3) strip off some parts of code for some apps and architects
How to use
angular.json:
"defines": [
  {
    "name": "DEFINE_OPTION",
    "value": false
  },
  {
    "name": "ENV_OPTION",
    "value": "process.env.TEST_ENV_DEFINES"
  },
  {
    "name": "COMMAND_LINE_OPTION",
    "value": "buildOptions._customCommandLineOption"
  },
  {
    "name": "CALC_OPTION",
    "targets": {
      "production": "283745620252 + 1",
      "development": "2 + 2"
    }
  }
]
code:
declare var DEFINE_OPTION: boolean;
declare var ENV_OPTION: string;
declare var COMMAND_LINE_OPTION: string;
declare var CALC_OPTION: number;
if (DEFINE_OPTION){
  //stripped off
}
run:
set TEST_ENV_DEFINES=env_value
ng build --_customCommandLineOption=42

angular/angular-cli#10521
@filipesilva
Copy link
Contributor

Hi there, this functionality is something we have considered before and opted to not include in Angular CLI. I know doing what you propose is common in webpack projects but this isn't the approach we want to follow in Angular CLI.

Generally speaking, the use case you mentioned (different code in different builds), is addressed by our file replacement functionality (https://github.com/angular/angular-cli/wiki/stories-application-environments).

@Flybbit
Copy link
Author

Flybbit commented May 21, 2018

@filipesilva Thanks, replacement really solves half of problem. What could you advice for second half: pass environment\command line to code. I found Issue #4419. According to comments there solution is to generate ts code before build. Is it right approach at the moment?

@filipesilva
Copy link
Contributor

I don't see us passing generic values from the CLI to the files anytime soon. The approach we suggest is to have that code on disk and replace it according to needs.

@ghost
Copy link

ghost commented Jul 18, 2019

You can also use the
ng serve --args "var1=varValue1,var2=varValue2"

Then write a "command line arguments string parser" that just dumps all of those into
process.env

@angular-automatic-lock-bot
Copy link

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.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Sep 9, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants