Environment flags --prod or --env


#1

Hi there guys!

I’m migrating my Web App into NativeScript and I’m facing a problem that I don’t know how to solve.

I have tried to add the nativescript-hook-debug-production plugin and it wasn’t working for me or I didn’t set it up correctly.

Currently I have my environments folder with environment.ts and environment.prod.ts. In the service I am importing enviroment.ts and I would like to import the environment.prod.ts once I set up the production flag.

Does anybody know how could I achieve that feature?

Thank you in advance!


#2

If you are using Angular, I would suggest to use Webpack only to pass in environment variables.

https://docs.nativescript.org/best-practices/bundling-with-webpack#nativescript-cli-commands

You can also use the same method to provide environmental variables to the Webpack build:

$ tns build android --bundle --env.development --env.property=value

They can be accessed through the env object in the Webpack configuration:

// webpack.config.js
module.exports = env => {
    console.dir(env); // { development: true, property: 'value' }
}

#3

First of all, thank you for your reply :wink:

With this approach would I achieve the result I’m expecting? Importing only one variable “environment” from “environment.ts” without flag and use the same variable but in the moment of building and bundling I want that variable to point to “environment.prod.ts” when --prod flag released. I could provide a fragment of code if necessary


#4

Here is what I can imagine of,

Define configs

export class AppConfig {
 static ServerUrl:string = "http://dev.server.com/...";
 ...
// more configurations I might want to add
}

export class ProdConfig extends AppConfig {
 static ServerUrl:string = "http://prod.server.com/...";
 ...
// more configurations I might want to update
}

Update Webpack

...
       new webpack.DefinePlugin({
            "global.TNS_WEBPACK": "true",
            "global.ENV_NAME": JSON.stringify(process.env.npm_config_env_name || "development")
        }),
...

Write a utility method that returns current config:

export function getAppConfig(): typeof AppConfig {
    switch (global.ENV_NAME) {
        case "production":
            return ProdConfig;
        case "development":
        default:
            return AppConfig;
    }
}

So now calling getAppConfig() by default returns development configuration. When the environment name is passed in as production, it can activate the production configuration set.

$ tns build android --bundle --env.name=production

Hope this gets improved when after 4.x, seamless integration with Angular CLI and should not take much to migrate then.


#5

I think it’s a very good approach, but I’m still struggling with the webpack.config.js, that DefinePlugin seems not to be working and it isn’t accessible from the config file (‘process.env.npm_config_env_name’ only throws ‘development’) and the global.ENV_NAME doesn’t exist. Should I configure anything else? Thank you for help


#6

If you are using Webpack, by default it enables one environment variable for it’s internal use.

So should not be a problem in adding one more, You can directly use JSON.stringify(env.name || "development") instead of accessing process. process was some old code I used to follow.

Regarding global.ENV_NAME, we have to let TypeScript understand that. Add this to your references.d.ts (If you don’t have one already in your project root, create one).

declare namespace NodeJS {
    interface Global {
        ENV_NAME: string;
    }
}

If you are using VS Code you might want to restart after this step.


#7

When you try to access that env.name passed through --bundle --env.name=production for instance, the result you get is a boolean and not the string you should see, how is it possible?

  • tns run android --bundle --env.name=production
  • console.log(global.ENV_NAME); // true or undefined if you don’t define env.name

#8

global.ENV_NAME never can be undefined if you follow

"global.ENV_NAME": JSON.stringify(process.env.npm_config_env_name || "development")

It must be development instead as default value. Can you please reconfirm you applied exact same code in define plugin.


#9

I have applied the same, and I got that ‘undefined’.

I have adapted the webpack.config.js to work with booleans for --env.prod instead of getting the --env.name=production. I was having the same issue so I decided to go with the boolean approach :wink:


#10

Glad you figured out a solution, yet not sure why you couldn’t get that as string. In my case I use more than 2 environments so pass in a name and it works for me.


#11

I will try to provide that solution later on.

Thank you very much for your help :wink:


#12

Hello, everyone, I know this topic may be kind of dead now, but has anyone found a way to inject ENVs without bundling the project with webpack? Adding a --bundle flag renders the app unable to display .ts files in debugger as it compiles everything, and that isn’t helping with debugging


#13

Hi, sorry for the late reply.
Right now, due to NativeScript limitations and my way of working (I separate the compiled files and scss in different folder changing the outDir in the tsconfig.json), the only way I have found to deal with the tests for the environments is to re-run the application each time I make some changes.
For the next NativeScript release 4.0 in April ( ?? ) they will include the autoWatch flag although they haven’t mentioned anything about the testing topic