Skip to content
This repository was archived by the owner on May 1, 2020. It is now read-only.

Feature request: Ionic 2 (dev/prod) environment variables configuration #760

Closed
jthoms1 opened this issue Feb 16, 2017 · 46 comments
Closed
Assignees

Comments

@jthoms1
Copy link
Contributor

jthoms1 commented Feb 16, 2017

From @jgw96 on July 25, 2016 20:42

From @amreladawy on July 24, 2016 6:58

Short description of the problem:

It is a feature request.
Just like Angular2, I hope that Ionic can provide 2 files (environment.dev.ts and environment.prod.ts) that would contain variables with different values corresponding to production and development environment.
During the build, the appropriate file to be copied and bundled within the app artifact.

Which Ionic Version? 2.x

https://forum.ionicframework.com/t/ionic-2-environment-variables-config-setup/58147/1

https://stackoverflow.com/questions/36004810/how-to-config-different-development-environment-in-angular-2-app

Copied from original issue: ionic-team/ionic-framework#7413

Copied from original issue: ionic-team/ionic-cli#1205

@jthoms1
Copy link
Contributor Author

jthoms1 commented Feb 16, 2017

From @itrethan on October 22, 2016 8:48

Can we raise the priority for this issue? This is actually very important. Our app has different configs for prod and devel. Without this, it requires ugly hand rolled variable updates... Just make the release really cumbersome.

@jthoms1
Copy link
Contributor Author

jthoms1 commented Feb 16, 2017

From @dnmd on October 24, 2016 13:46

Currently our implementation uses the rollup-plugin-replace, and a slightly modified rollup config.

Basically what happens is that the import paths are replaced based on the process.env.IONIC_ENV variable during compile time. This will use the environment.dev.ts during development and environment.prod.ts when in production.

Implementation steps

  1. install the rollup-plugin-replace
    npm install --save-dev rollup-plugin-replace

  2. create two files; environment.dev.ts and environment.prod.ts within e.g. the src/config directory.

├── src/config/environment.dev.ts

export const ENV = {  
  PRODUCTION : false,
  API_URL    : 'dev.local'
};
├── src/config/environment.prod.ts

export const ENV = {  
  PRODUCTION : true,
  API_URL    : 'prod.local'
};
  1. import the environment-dev as the default within your pages / services etc.
// use the 'environment-dev' as the default import(!)
import { ENV } from '../../config/environment-dev';

@Component({
  templateUrl: 'hello-ionic.html'
})
export class HelloIonicPage {
   console.log( ENV.API_URL );
}
  1. update your /package.json
├── /package.json

"config": {
    "ionic_rollup": "./config/rollup.config.js"
}
  1. create your rollup.config.js within the /config directory. Require the plugin, and add the replace snippet below to your plugins section. One can use node_modules\@ionic\app-scripts\config\rollup.config.js as a template.
├── /config/rollup.config.js

var replace = require('rollup-plugin-replace');
var isProd  = (process.env.IONIC_ENV === 'prod');
...
plugins: [
    replace({
      exclude: 'node_modules/**',
      // use the /config/environment-dev as the default import(!), no stub needed.
      // note we only replace the "last" part of the import statement so relative paths are maintained
      '/config/environment-dev' : ( isProd ? '/config/environment-prod' : '/config/environment-dev'),
    })
   ...
]

Hope this helps someone! Of course in an ideal situation a file replacement would take place, similar to the Angular CLI

@jthoms1
Copy link
Contributor Author

jthoms1 commented Feb 16, 2017

From @Maziar-Fotouhi on October 26, 2016 14:55

Is there any plans to actually implement this?

@jthoms1
Copy link
Contributor Author

jthoms1 commented Feb 16, 2017

From @tabirkeland on November 1, 2016 17:36

With "@ionic/app-scripts": "0.0.39" now defaulting to webpack for bundling, I am doing something like this.

Steps to implement:

  1. Make sure you have installed the latest app-scripts npm install @ionic/app-scripts@latest and have the latest tsconfig.json.

  2. Install dotenv.

  3. Create .env file with env variables defined in the root directory of your app. Recommended:
    add .env to .gitignore.

  4. Create and modify webpack.config.js from original found here:

├── /config/webpack.config.js

require('dotenv').config();

...
function getPlugins() {
  var plugins = [
    new webpack.DefinePlugin({
      'API_URL': JSON.stringify(process.env.API_URL)
      // Add any more variables here that you wish to define
    })
  ];

  if (process.env.IONIC_ENV === 'prod') {
      // This helps ensure the builds are consistent if source hasn't changed:
    plugins.push(new webpack.optimize.OccurrenceOrderPlugin());
  }
  return plugins;
}
...
  1. Define custom webpack config file in package.json.
├── /package.json

"config": {
    "ionic_webpack": "./config/webpack.config.js"
}
  1. Create custom typings file defining the constants that are in your .env file so that webpack can populate them and you are able to reference them in your application.
├── /src/customTypings/customTypings.d.ts

declare var API_URL: string;
// Add any more variables here that you wish to define

You should now be able to reference the global variable(s) in your app.

Furthermore, you can create multiple .env files for different environments and require them in webpack.config.js like so:

require('dotenv').config({path: '/custom/path/to/your/env/vars'})

@jthoms1
Copy link
Contributor Author

jthoms1 commented Feb 16, 2017

From @slinto on November 8, 2016 9:41

This solution is working, but I think, rewriting all webpack.config is not good, becase updates... Is there any idea from ionic team?

@jthoms1
Copy link
Contributor Author

jthoms1 commented Feb 16, 2017

From @rossholdway on November 11, 2016 11:13

@jgw96 Can we get this added to a milestone? We should be able to specify different environment configuration e.g. different API endpoints for dev and production. As @slinto mentioned creating a modified webpack.config is not ideal as updates will cause issues :/

@jthoms1
Copy link
Contributor Author

jthoms1 commented Feb 16, 2017

From @locnguyen on November 11, 2016 15:54

I'd really like to see this functionality supported. Is a custom webpack config the only way?

@jthoms1
Copy link
Contributor Author

jthoms1 commented Feb 16, 2017

From @Maziar-Fotouhi on November 11, 2016 16:10

Okay... After a lot of coffee and head bumping, I've realized that the best way (at least for me) is to change the environments manually and not rely on ionic to change it. That was mainly because ionic-cli does not let you runionic serve with production environment.
I have set an environment.ts in the root folder of the app that contains all the variables.

environment.ts

export class ENV {

    public static currentEnvironment: string = "development";
    // public static currentEnvironment: string = "production";

    public static development: any = {
         key1: "value1",
         key2: "value2",
        ......
        ......
    };
    public static production: any = {
        key1: "value1",
        key2: "value2",
        ......
        ......
    };
}

Then I added an environment.service among my services.

environment.service.ts

import {Injectable} from '@angular/core';
import {ENV} from '../../environments/environment';

@Injectable()
export class EnvironmentService {


    public getKey1() : string{
        if(ENV.currentEnvironment === "development"){
            return ENV.development.key1;
        } else if(ENV.currentEnvironment === "production") {
            return ENV.production.key1;
        }
    }

    public getKey2() : string{
        if(ENV.currentEnvironment === "development"){
            return ENV.development.key2;
        } else if(ENV.currentEnvironment === "production") {
            return ENV.production.key2;
        }
    }

     ......
     ......

}

Then I added the service to the providers of the app.module and used it like any other service.
E.g. in any component you can access the values like this:

any.component.ts

...
...
...

import {EnvironmentService} from '../../services/environment.service';

...
...
...

constructor(
                      ...
                      ...
                      ...
                      private environmentService: EnvironmentService
                      ...
                      ...
                      ...) {
    }

...
...
...

let baseUrl = this.environmentService.getKey1();

...
...
...

And finally, in order to change the environment, you have to toggle (comment and uncomment) the first two line of environment.ts.

This is a good workaround for now, if you need different values (URLs, API keys, etc.) to be used in development and production. But, I think eventually, ionic and ionic-cli teams will have to work together to integrate something like this internally, that lets us use different sets of environment variables based on a flag that we pass to the command that is running the app.
E.g. :
ionic (serve/run) (--prod/--dev)

@jthoms1
Copy link
Contributor Author

jthoms1 commented Feb 16, 2017

From @slinto on November 11, 2016 17:13

hmm, the manual comment/uncomment of right ENV is dangerous, because is there a big risk with publishing application with development environment to store, especially if your team is about 1+ people :) I think about right way as:

ionic serve / DEVELOPMENT ENV (DEFAULT):
$ ionic serve

ionic serve / PRODUCTION or CUSTOM ENV:
$ ionic serve --env=prod,
$ ionic serve --env=test,
$ ionic serve --prod

ionic build / PRODUCTION ENV (DEFAULT):
$ ionic build

ionic build / DEVELOPMENT or CUSTOM ENV:
$ ionic build --dev
$ ionic build --env=test
$ ionic build --env=dev

eg. http://jonnyreeves.co.uk/2016/simple-webpack-prod-and-dev-config/

@jthoms1
Copy link
Contributor Author

jthoms1 commented Feb 16, 2017

From @Maziar-Fotouhi on November 11, 2016 17:31

@slinto You are absolutely correct, there is the possibility of publishing the app with dev variables. But, it is only as dangerous as any other solution. You may build the prod app with the wrong command as well.
I'm actually using this in a corporate project with a big number of people on the team. I think nowadays every team uses version control systems like git or svn. So, this would be just a matter of team functionality and team members being coordinated with each other. And furthermore, there is usually only one person in team who is in charge of deploying the app.
But, again, you're right. With manual toggle of environments, there is a slightly higher chance of making the mistake. So, as I said, this is only a temporary fix. Ideally, this should be internal to ionic, using the commands you mentioned.

@jthoms1
Copy link
Contributor Author

jthoms1 commented Feb 16, 2017

From @allaanz on November 14, 2016 19:57

+1

@jthoms1
Copy link
Contributor Author

jthoms1 commented Feb 16, 2017

From @zjhiphop on November 20, 2016 11:16

Hey, guys, any progress of official implements?

@jthoms1
Copy link
Contributor Author

jthoms1 commented Feb 16, 2017

From @rolandjitsu on November 21, 2016 15:2

@dnmd can you confirm that your solution works with a production build?

@jthoms1
Copy link
Contributor Author

jthoms1 commented Feb 16, 2017

From @Yimiprod on November 25, 2016 18:4

with 0.0.46 adding anything at config in package.json trigger rollup warnings (and the script freeze after that)

[18:58:40]  rollup: Conflicting namespaces: /space/www/applications/wav/node_modules/@angular/compiler/index.js
            re-exports 'NgContentAst' from both
            /space/www/applications/wav/node_modules/@angular/compiler/src/template_parser/template_ast.js (will be
            ignored) and /space/www/applications/wav/node_modules/@angular/compiler/src/template_parser/template_ast.js.
[18:58:40]  rollup: Conflicting namespaces: /space/www/applications/wav/node_modules/@angular/compiler/index.js
            re-exports 'PropertyBindingType' from both
            /space/www/applications/wav/node_modules/@angular/compiler/src/template_parser/template_ast.js (will be
            ignored) and /space/www/applications/wav/node_modules/@angular/compiler/src/template_parser/template_ast.js.
[18:58:40]  rollup: Conflicting namespaces: /space/www/applications/wav/node_modules/@angular/compiler/index.js
            re-exports 'templateVisitAll' from both
            /space/www/applications/wav/node_modules/@angular/compiler/src/template_parser/template_ast.js (will be
            ignored) and /space/www/applications/wav/node_modules/@angular/compiler/src/template_parser/template_ast.js.

By the way, isn't it better to listen for the argument --release ?
Another thing, why with 0.0.46 it's rollup and not webpack by default?

@jthoms1
Copy link
Contributor Author

jthoms1 commented Feb 16, 2017

From @movrack on November 26, 2016 15:17

I like the idea of @slinto
In our case, we have actually 5 environments...

  • dev
  • test (unit test)
  • iat (human first line test => developer tester)
  • uat (human second line test => business client tester)
  • prod

And we have to copy config file at build time to choose the environment.
To chose the environment at build time, we run it like :
TARGET=xxx ionic run yyy for mac or set TARGET=xxx&& ionic run yyy for windows developer.

This is managed by a hook based on this post : http://www.kdmooreconsulting.com/blogs/build-a-cordova-hook-to-setup-environment-specific-constants/

But since we do that, we lost the live reload feature! (ionic-app-script watch doesn't copy our right config.js file and we don't know how to do that).

If we can set a parameter like @slinto told -- to choose the environment with something like "--env=xxx", and make it available for live reload ... -- it will be really cool!

@jthoms1
Copy link
Contributor Author

jthoms1 commented Feb 16, 2017

From @schaergeek on November 28, 2016 8:44

Definitely a must. So +1

@jthoms1
Copy link
Contributor Author

jthoms1 commented Feb 16, 2017

From @iacomus on November 30, 2016 18:56

So how would this tie in with the Live Deploy to channel feature currently available https://docs.ionic.io/services/deploy/ ?

@jthoms1
Copy link
Contributor Author

jthoms1 commented Feb 16, 2017

From @mvidailhet on December 21, 2016 14:16

OK, so I needed this kind of feature to be able to have different parameters (api endpoints, google analytics ID etc...) with different environments (dev, preprod, prod...).

So I made my first module (feedbacks more than welcome, and please be gentle :p) to be able to do that: gl-ionic2-env-configuration

Basically, it loads a env-configuration.json located in the www folder before anything else (so that your api url will be set even in your apiService constructor, for example).

In the package documentation, I linked a simple node executable to easily copy the configuration file for a specific environment.

Advantages

  • You don't need to override the Ionic webpack.config (which could break things when Ionic updates).
  • You can have as much environments as you want and name it as you like.
  • You can dynamically change the configuration file without having to recompile the app (which will be very useful for continous integration systems).

Hope this will help.

@jthoms1
Copy link
Contributor Author

jthoms1 commented Feb 16, 2017

From @sean-hill on January 2, 2017 17:49

Any updates to this Ionic team? I would love to see this baked into the ionic-app-scripts repo.

@jthoms1
Copy link
Contributor Author

jthoms1 commented Feb 16, 2017

From @fiznool on February 2, 2017 11:39

Inspired by the solution from @tabirkeland I thought I'd post my own version of this. The differences with the script below vs the original solution:

  • The Ionic webpack.config script is built upon, not replaced, meaning that any updates to @ionic/app-scripts should be merged in.
  • The script is aware of Ionic's --prod flag, allowing you to provide separate configuration for dev and prod builds.
  • There is no dependency on dotenv.

Here's the steps to get it all working:

  1. Create a file at config/webpack.config.js and paste the following content:
// Set the `ENV` global variable to be used in the app.
var path = require('path');
var webpack = require('webpack');

var projectRootDir = process.env.IONIC_ROOT_DIR;
var appScriptsDir = process.env.IONIC_APP_SCRIPTS_DIR;

var config = require(path.join(appScriptsDir, 'config', 'webpack.config.js'));

var env = process.env.IONIC_ENV || 'dev';
var envVars;
try {
  envVars = require(path.join(projectRootDir, 'env', env + '.json'));
} catch(e) {
  envVars = {};
}

config.plugins = config.plugins || [];
config.plugins.push(
  new webpack.DefinePlugin({
    ENV: Object.assign(envVars, {
      environment: JSON.stringify(env)
    })
  })
);

if(env === 'prod') {
  // This helps ensure the builds are consistent if source hasn't changed:
  config.plugins.push(new webpack.optimize.OccurrenceOrderPlugin());
}

module.exports = config;
  1. Add the following entry to your package.json:
  "config": {
    "ionic_webpack": "./config/webpack.config.js"
  }
  1. If you need additional configuration, create two files env/dev.json and env/prod.json. In here, put any configuration you need for that environment. Your json should be an object of key-value pairs, which will be made available for use in your application.
{
  "enableLogging": true,
  "apiServerUrl": "\"http://example.com/api\""
}

Now, you can use the ENV global constant anywhere in your .ts files:

declare const ENV;

if(ENV.environment === 'dev') {
  // Run without the `--prod` flag.
  // Any keys defined in `dev.json` will be available on the `ENV` object.
} else if (ENV.environment === 'prod') {
  // Run with the `--prod` flag.
  // Any keys defined in `prod.json` will be available on the `ENV` object.
}

The script creates an ENV object with a single key, environment, which is set to prod if you run your ionic command with the --prod flag. Otherwise, this will be dev.

The env/dev.json and env/prod.json files are optional. If present, the script will merge the appropriate object into ENV. The script above uses webpack's DefinePlugin, so remember to 'stringify' any string values, otherwise webpack will assume you want to insert a code fragment. For example:

{
  "apiServerUrl": "\"http://example.com/api\""
}

It would be great to see this baked into the core webpack.config.js file in the app-scripts repo.

@jthoms1
Copy link
Contributor Author

jthoms1 commented Feb 16, 2017

From @NightOnFire on February 2, 2017 18:6

I implemented the solution from @fiznool the webpack script does not look for env/dev.json but env/dev and when it does have .json it auto converts to an object so no need for the JSON.parse. I changed envVars = JSON.parse(require(path.join(projectRootDir, 'env', env))); to envVars = require(path.join(projectRootDir, 'env', env + '.json'));.

My very limited knowlege of webpack stumped me for a bit and I had to add extra quotes in my json so I ended up with {"foo": "\"bar\""}. There is probably a better way to deal with this though.

@jthoms1
Copy link
Contributor Author

jthoms1 commented Feb 16, 2017

From @swaheed2 on February 2, 2017 19:39

Since Ionic 2.0 final is out, I'm guessing there will be many more production level apps starting out.

If we can get an update from the Ionic team about this feature, we can at least know if we need to implement a temporary solution or go all in using one of the various suggestions from the comments.

@jthoms1
Copy link
Contributor Author

jthoms1 commented Feb 16, 2017

From @coldAlphaMan on February 3, 2017 23:14

so fyi i was able to implement @fiznool suggestion along with @NightOnFire changes and it worked for me. That said, pay attention to @NightOnFire comments on how to set up entries in your json file.

{"foo": "bar"} WILL NOT WORK and will generate exceptions.
you HAVE to format your json entries the same way @NightOnFire did his.

Hope this helps.

@jthoms1
Copy link
Contributor Author

jthoms1 commented Feb 16, 2017

From @fiznool on February 4, 2017 7:47

@NightOnFire @coldAlphaMan thanks for your comments, I've updated my comment to reflect these needed changes. 👍

@jthoms1
Copy link
Contributor Author

jthoms1 commented Feb 16, 2017

From @geraneum on February 11, 2017 11:18

You cannot useENV in app.module.ts in production using @fiznool method. Any solution for this?

@jthoms1
Copy link
Contributor Author

jthoms1 commented Feb 16, 2017

From @rolandjitsu on February 11, 2017 11:32

@geraneum Use Rollup with rollup-plugin-replace and replace strings instead of variables:

replace({
    values: {
        '{{IONIC_ENV}}': process.env.IONIC_ENV,
    },
    exclude: 'node_modules/**'
}),

And somewhere in your app:

const env = '{{IONIC_ENV}}';

@jthoms1
Copy link
Contributor Author

jthoms1 commented Feb 16, 2017

From @fiznool on February 11, 2017 12:14

@geraneum could you share a code snippet that shows this issue? It might be possible to split the references to ENV out into separate exported functions or constants to allow for aot builds.

@jthoms1
Copy link
Contributor Author

jthoms1 commented Feb 16, 2017

From @geraneum on February 11, 2017 12:58

@fiznool

I have put declare const ENV; in /src/declarations.d.ts

Then in /env/prod.json I have something like this:

{
  "ionicCloudAppId": "'<APP ID>'",
}

in /src/app/app.module.ts I have:

const cloudSettings: CloudSettings = {
  'core': {
    'app_id': ENV.ionicCloudAppId
  }
}

Everything else is the same as what you've suggested.
I have other variables declared in prod.json and they work everywhere except app.module.ts.
Also using ENV.ionicCloudAppId in other places works.
This only happens with --prod flag.

@jthoms1
Copy link
Contributor Author

jthoms1 commented Feb 16, 2017

From @fiznool on February 11, 2017 13:37

AOT can be fiddly. What exactly is the error message?

I've previously had luck exporting constants so that AOT works correctly, you could try this.

export const cloudSettings: CloudSettings = {
  'core': {
    'app_id': ENV.ionicCloudAppId
  }
}

@jthoms1
Copy link
Contributor Author

jthoms1 commented Feb 16, 2017

From @geraneum on February 11, 2017 13:54

@fiznool added export still getting the same error:
Cannot read property 'ionicCloudAppId' of undefined

Also how can I use this feature with ionic package build --release? when I do that, dev settings gets picked up in the generated APK, I also provided release.json, but still no luck.

@jthoms1
Copy link
Contributor Author

jthoms1 commented Feb 16, 2017

From @fiznool on February 11, 2017 14:21

@geraneum I just created a sample repo and building for production works as expected. In app.module.ts, there is a console log which prints the variable ENV.api_server to the console. This is defined differently in dev.json and prod.json.

When running ionic run android --prod I see the following in logcat:

02-11 14:16:26.883 16383 16383 I chromium: [INFO:CONSOLE(32)] "http://prod.example.com", source: file:///android_asset/www/build/main.js (32)

which is what I would expect.

Perhaps you can use this repo and see what the differences are in your own app? Here is my ionic info:

Cordova CLI: 6.5.0 
Ionic Framework Version: 2.0.1
Ionic CLI Version: 2.2.1
Ionic App Lib Version: 2.2.0
Ionic App Scripts Version: 1.0.0
ios-deploy version: Not installed
ios-sim version: Not installed
OS: Linux 4.8
Node Version: v6.9.4
Xcode version: Not installed

Regarding the release build, you still need the --prod flag, AFAIK --release is purely concerned with generating release keys to sign your app with.

ionic package build --prod --release

@jthoms1
Copy link
Contributor Author

jthoms1 commented Feb 16, 2017

From @geraneum on February 11, 2017 14:50

@fiznool Thank you very much for your help.
I got the correct output from console log... but for test I changed the app.module.ts like this:

imports: [
    IonicModule.forRoot(MyApp, {
      tabsHideOnSubPages: ENV.tabsHideOnSubPages
    })
  ],

and prod.json to this:

{
  "api_server": "'http://prod.example.com'",
  "tabsHideOnSubPages": true
}

And as soon as I did it, I got the following error on app launch:

Uncaught TypeError: Cannot read property 'tabsHideOnSubPages' of undefined
    at e.createInternal (main.js:26)
    at e.create (main.js:11)
    at t.create (main.js:11)
    at main.js:7
    at t.invoke (polyfills.js:3)
    at Object.onInvoke (main.js:4)
    at t.invoke (polyfills.js:3)
    at e.run (polyfills.js:3)
    at t.run (main.js:4)
    at e._bootstrapModuleFactoryWithZone (main.js:7)

@jthoms1
Copy link
Contributor Author

jthoms1 commented Feb 16, 2017

From @fiznool on February 11, 2017 16:19

Yes, I see now. Seeing the same issue. Maybe someone with more aot knowledge can help as I'm a bit stumped too 😄

@jthoms1
Copy link
Contributor Author

jthoms1 commented Feb 16, 2017

From @domlogic on February 14, 2017 9:2

I was seeing the problem of undefined things after creating config files like rollup.config.js and updating package.json. It is important to copy the files from app-scripts on git hub and edit them rather than create new files because you are overriding the defaults, which breaks if things are missing.

For the initial problem, I wanted to contribute my problem and solution:

I think the support is already there. I wanted to avoid storing the api keys and other identities from source control. I did the following:

  1. Create a "config" folder and an "environment" folder under the app root.

  2. Copy the default ionic app-script for the copy config from https://github.com/driftyco/ionic-app-scripts/blob/master/config/copy.config.js to /config

  3. Edit the copy.config.js (for me it was a firebase config, which I placed before polyfills):
    ... copyFonts: { src: ['{{ROOT}}/node_modules/ionicons/dist/fonts/**/*', '{{ROOT}}/node_modules/ionic-angular/fonts/**/*'], dest: '{{WWW}}/assets/fonts' }, copyFirebaseConfig: { src: ['{{ROOT}}/environment/firebase-config.js'], dest: '{{BUILD}}' } , copyPolyfills: { src: ['{{ROOT}}/node_modules/ionic-angular/polyfills/polyfills.js'], dest: '{{BUILD}}' }, ...

  4. Add the config to package.json so that ionic build knows that the default is overridden:
    ... "config": { "ionic_copy:": "config/copy.config.js" }, ...

  5. Add a file which exports the desired config as a const at the location specified in the modified copy.config.js

  6. Import the config where it is needed (for me it's a single import in app.module.ts):
    import {FirebaseConfig} from '../../environment/firebase-config';

  7. Tell git to ignore everything under "environment"

  8. Tell your build server to add the config file to its working dir under subdir "environment" (I haven't done this yet)

Now only your build server and dev environment know what your api keys are. I hope this helps somebody else.

@jthoms1
Copy link
Contributor Author

jthoms1 commented Feb 16, 2017

From @jhonathas on February 15, 2017 19:16

@domlogic But doing so I can not get a configuration file for environments, right? Example, firebase.dev.ts, firebase.prod.ts etc ...

@danbucholtz
Copy link
Contributor

What does everyone think of something like this?

#762

Thanks,
Dan

@Ross-Rawlins
Copy link

+1

@RodolfoSilva
Copy link

RodolfoSilva commented Feb 27, 2017

Inspired by the @dnmd and Angular 2 solution, I've only made minor changes, and it works fine.

Implementation steps

Install the rollup-plugin-replace

npm install --save-dev rollup-plugin-replace

Create this files in the src/environments directory:

  • environment.dev.ts
  • environment.prod.ts
  • index.ts(optional)

Add these examples to files:

├── src/environments/environment.dev.ts

export const ENV = {  
  PRODUCTION : false,
  API_URL    : 'dev.local'
};
├── src/environments/environment.prod.ts

export const ENV = {  
  PRODUCTION : false,
  API_URL    : 'prod.local'
};
├── src/environments/index.ts

// use the '/environments/environment.dev' as the default import(!)
export * from '../environments/environment.dev';

Import the environments/environment.dev as the default within your pages/services etc.

// use the '/environments/environment.dev' as the default import(!)
import { ENV } from '../../environments/environment.dev';

@Component({
  templateUrl: 'hello-ionic.html'
})
export class HelloIonicPage {
   console.log( ENV.API_URL );
}

Update your /package.json

├── /package.json

"config": {
    "ionic_rollup": "./config/rollup.config.js"
}

Create your rollup.config.js within the /config directory and add this code:

const rollupConfig = require('@ionic/app-scripts/config/rollup.config');
const replace = require('rollup-plugin-replace');

const isProd = (process.env.IONIC_ENV === 'prod');

const rollupConfigReplaceEnviroment = replace({
  exclude: 'node_modules/**',
  // use the /environments/environment.dev as the default import(!), no stub needed.
  // note we only replace the "last" part of the import statement so relative paths are maintained
  '/environments/environment.dev' : ( isProd ? '/environments/environment.prod' : '/environments/environment.dev'),
});

rollupConfig.plugins = rollupConfig.plugins || [];
rollupConfig.plugins.splice(0, 0, rollupConfigReplaceEnviroment);

module.exports = rollupConfig;

About rollup.config i think we dont need copy all source of @ionic/app-scripts/config/rollup.config.js, only extend it...

@gianpaj
Copy link

gianpaj commented Feb 28, 2017

thanks @RodolfoSilva for that example!

This is my version without the need of environment.*.ts files or folder. Also, IONIC_ENV wasn't getting picked up my ionic CLI command.

rollup.config.js

const rollupConfig = require('@ionic/app-scripts/config/rollup.config');
const replace = require('rollup-plugin-replace');

const isProd = (process.env.NODE_ENV === 'prod');

if (isProd) {
    console.log('Building with Prod enviroment');
} else {
    console.log('Building with Dev enviroment. Set NODE_ENV=prod for production API URL, etc.');
}

const rollupConfigReplaceEnviroment = replace({
  exclude: 'node_modules/**',
  ENVIRONMENT: isProd ? 'prod': 'dev'
});

rollupConfig.plugins = rollupConfig.plugins || [];
rollupConfig.plugins.splice(0, 0, rollupConfigReplaceEnviroment);

module.exports = rollupConfig;

Then you just need to add this in .ts file which exports the variable you want to change depending on the ENV variable (NODE_ENV):

api.ts

let ENV = 'ENVIRONMENT'; // <-- this text will be replaced by the 'rollup-plugin-replace' module

const isProd = (ENV == 'prod');

let PROTOCOL;
let API_URL;

if (isProd) {
    PROTOCOL = 'https:';
    API_URL = 'api.example.com';
} else {
    PROTOCOL = 'http:';
    API_URL = 'dev.example.com'; // maybe pointing to localhost
}

And now you run it like this 🎉 :

$ ionic serve --nobrowser

> ionic-hello-world@ ionic:serve MyMobileApp
> ionic-app-scripts serve "--v2" "--nobrowser" "--address" "0.0.0.0" "--port" "8100" "--livereload-port" "35729"

[00:07:25]  ionic-app-scripts 1.1.3
[00:07:25]  watch started ...
[00:07:25]  build dev started ...
[00:07:25]  clean started ...
[00:07:25]  clean finished in 5 ms
[00:07:25]  copy started ...
[00:07:25]  transpile started ...
Building with Dev environment. Set NODE_ENV=prod for production API URL, etc.

or for prod:

$ NODE_ENV=prod ionic serve --nobrowser

> ionic-hello-world@ ionic:serve MyMobileApp
> ionic-app-scripts serve "--v2" "--nobrowser" "--address" "0.0.0.0" "--port" "8100" "--livereload-port" "35729"

[00:01:31]  ionic-app-scripts 1.1.3
[00:01:31]  watch started ...
[00:01:31]  build dev started ...
[00:01:31]  clean started ...
[00:01:31]  clean finished in 2 ms
[00:01:31]  copy started ...
[00:01:31]  transpile started ...
Building with Prod environment
...

@vovikdrg
Copy link

vovikdrg commented Mar 2, 2017

@RodolfoSilva @gianpaj I am getting error "rollup failed: Unexpected token" any ideas what it could be?

@rolandjitsu
Copy link
Contributor

@vovikdrg do you by chance use @ionic/cloud-angular? If you do, the error occurs in @ionic/db. I removed @ionic/cloud-angular and it works without it.

I'm not sure why though.

@vovikdrg
Copy link

vovikdrg commented Mar 2, 2017

@rolandjitsu yes i am...

@vovikdrg
Copy link

vovikdrg commented Mar 6, 2017

@rolandjitsu thanks for pointing out, I have found issue. It was dependency to old rxjs.

@maxpaj
Copy link

maxpaj commented Mar 31, 2017

What's the official solution for this?

@danbucholtz
Copy link
Contributor

@maxpaj,

No official solution right now, coming soon...

Let's track this issue here since it's a duplicate.

Thanks,
Dan

@ionic-team ionic-team locked and limited conversation to collaborators Mar 31, 2017
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

9 participants