ionic-team / ionic-app-scripts

App Build Scripts for Ionic Projects
http://ionicframework.com/
MIT License
608 stars 304 forks source link

Environment proposal #762

Closed danbucholtz closed 6 years ago

danbucholtz commented 7 years ago

I am thinking we could do this:

  1. Introduce a new flag that gets passed in like this:

ionic serve --env qa or ionic run android --env prod

My first thought was that it's value would default to dev for non-prod builds, and prod for prod builds. Developer's can pass in whatever they want, though.

  1. Based on the value that is passed in (or inferred), the config section of the package.json is read. It could look something like this:
...

"config": {
   "ionic_env" : {
       "dev" : {
          "keyToReplace" : "devValueToReplaceWith",
          "keyTwoToReplace" : "devValueTwoToReplaceWith"
       },
       "qa" : {
          "keyToReplace" : "qaValueToReplaceWith",
          "keyTwoToReplace" : "qaValueTwoToReplaceWith"
       }
   }
},
...

If the ionic_env data is not there, we would just move on in the build process. If it is present, we would then perform the text replacement.

  1. Any computed values, sync or async, could be replaced after the build is done. We could either leave this up to the user to add on to the npm script section, or we could provide a hook into the postprocess step. I prefer the latter as it's easier to document and and we can probably make it a 1/2 second faster or so if we do it in app-scripts.

Feedback is appreciated.

Thanks, Dan

fiznool commented 7 years ago

Looks interesting! I have a few questions.

Any computed values, sync or async, could be replaced after the build is done.

Could you expand on this? I didn't quite understand what you mean.

How would the app use these variables, what would the code look like?

One of the comments in another thread mentioned keeping sensitive values out of source control. Could there be a way of reading in a value from a process.env variable to satisfy this requirement?

rolandjitsu commented 7 years ago

@danbucholtz this looks great. Angular CLI has a similar implementation.

They have a --target which you can use to tell the CLI to either do a production build (AOT, minification, gzip, etc.) or a dev build. Then there's the --environment flag which we can use to choose the appropriate environment.

I'd disagree with the ionic_env working as proposed though. As you also pointed out, there might be a case when we need to compute some values, and that'd be difficult for some users to figure out. How about the following ionic_env:

"ionic_env": {
    "prod": "config/env.prod.js",
    "staging": "config/env.staging.js",
    "dev": "config/env.dev.js"
}

And each file would export the following:

const somePackage = require('somePackage');

module.exports = {
    SOME_VAR: somePackage.getSomeValueSync(),
    SOME_ASYNC_VAL: async function getSomeValueAsync() => {
        await asyncValue = somePackage.computeSomeValueAsync();
        return asyncValue;
    },
    VALUE_FROM_PROCESS: process.env.SOME_ENV_VAR_VAL
};

Then @ionic/app-scripts would require the appropriate env based on the config from ionic_env and for each key it will:

Perhaps there could be a better approach, but I thing this would work in most scenarios.

fiznool commented 7 years ago

Perhaps I'm missing something, but what sort of use cases would benefit from async computation of values?

rolandjitsu commented 7 years ago

Reading a file for instance (that's also possible to do sync). Or perhaps you store some keys in an AWS bucket and you'd like to pull those keys when you compile the app. I could think of plenty of use cases.

fiznool commented 7 years ago

Right, I'm with you now. :+1:

One approach I've seen in other places is to allow exporting a function as well as an object inside the configuration file. This could simplify the logic from the app-scripts end and allow you to build the config object dynamically, and only return once you are ready.

Something along these lines:

// sync example
const somePackage = require('somePackage');

module.exports = {
  SOME_VAR: somePackage.getSomeValueSync();
  VALUE_FROM_PROCESS: process.env.SOME_ENV_VAR_VAL;
};
// async example
const somePackage = require('somePackage');

module.exports = function() {
  const config = {
    SOME_VAR: somePackage.getSomeValueSync();
    VALUE_FROM_PROCESS: process.env.SOME_ENV_VAR_VAL;
  };

  return somePackage.computeSomeValueAsync().then(val => {
    config.SOME_ASYNC_VAL = val;
    return config;
  });
};

app-scripts would then perform the following

This has the benefit that app-scripts doesn't need to enumerate all the keys in the config object (what about nested keys?) and provides the most flexibility in your config script (what if the fetching of a second async value depends upon another one being resolved first?)

rolandjitsu commented 7 years ago

@fiznool true, that'd be much simpler and it would help if a value depends on another one. But the app scripts would still need to enum keys in order to replace, but that's just implementation detail.

rolandjitsu commented 7 years ago

Though I'd actually argue that if we export an object, app scripts could potentially run async tasks in parallel so if we'd have more than one property that evaluates to a promise/observable, it could run all of them at once and complete when all are done (something like a Promise.all([ ... ])/Observable.merge(...)).

Yet, the user could do this as well, but if app scripts would do it, it would spare the user of adding extra implementation.

I guess there are many ways this can be tackled, but the simpler the better.

fiznool commented 7 years ago

The difficulty there though, is that if one async value depended on another, you wouldn't be able to resolve the configuration correctly if app-scripts ran everything in parallel.

Better to put the logic in the hands of the user, IMHO.

ehorodyski commented 7 years ago

I like where @rolandjitsu is going, but instead of tying it down to a specific implementation, is there a way you can take the environment path being used from package.json in the ionic_env object, and then alias it, so it's import { <T> } from @ionic/config or import { <T> } from @ionic/env?

I don't know how the Angular library does aliasing so you can do import { HTTP } from '@angular/http', instead of import { HTTP } from 'angular/modules/wherever/it/lives/http', but that's how I'd implement it.

Give the users the ultimate control of building what they want to export from their environment/config files, but provide a way for those paths to be swapped out during building, and I think properly creating a module alias, which I don't know how to do, is the best approach.

danbucholtz commented 7 years ago

If we were to expose a hook and allow the user to load in async values, perhaps we could do something like this:

"config" : {
   "ionic_env" : {
      "dev" : "./scripts/dev.config.js",
      "qa" : "./scripts/qa.config.js",
      "prod" : "./scripts/prod.config.js"
      ... etc ...
   }
}

Those modules could then export a function that returns a Promise. That way it will always be async.

It could work like this:

module.exports = function(ionicEnvironment: string) {
   return readSomeAsyncValue().then((result: string) => {
      return {
         'keyOneToReplace' : 'valueOne',
         'keyTwoToReplace' : result
      }
   });
}

Something like this would work in the vast majority of use cases.

In an application's code, let's say you need to hit a different HTTP service for development and production.

You could write a service like this:

export class MyService {
   construtor(public http: Http){
   }

   makeServiceCall() {
      return this.http.makeRequest('$BACKEND_SERVICE_URL');
   }
}

Your implementation to replace it could look like this:

module.exports = function() {
   return Promise.resolve({
      '$BACKEND_SERVICE_URL' : 'localhost:8080/myService'
   });
}
ehorodyski commented 7 years ago

@danbucholtz - I think that is really over-complicated.

Take a look at Webpack's resolve aliasing. This could be done dynamically when starting ionic serve or the other scripts, depending on the env variable:

alias: { Utilities: path.resolve(__dirname, 'src/utilities/'), Templates: path.resolve(__dirname, 'src/templates/') } Now, instead of using relative paths when importing like so:

import Utility from '../../utilities/utility';

you can use the alias:

import Utility from 'Utilities/utility';

The only implication to the user is that they'd need to store their config files outside the folder with their source code, as to not include all the files defined. Or maybe not, you can run a glob that excludes the other environment files not being used. Plus, there's no resolution during application running.

josh-m-sharpe commented 7 years ago

For us this isn't necessarily just about env=dev/staging/prod. For some context, we're coming to ionic(v2) from a vanilla cordova app and we use the same codebase to generate multiple different apps primarily distinguished by an 'org_id'. (The app passes this value in server calls to receive different content, amongst a bunch of other differences). We also currently inject the internal and external version numbers since they vary (inconsistently) by org_id.

So, in a nutshell, just passing in "environment" wouldn't solve this problem for us. Why not make this feature align better with unix best practices and simply make all of the current env available inside the application somehow?

for example:

ORG_ID=123 ENVIRONMENT=staging ionic serve

For what it's worth, cordova (or node?) is doing this already automatically. That is, you can access 'process' inside a cordova hook without having to require anything. From that, it's just process.env.ORG_ID == '123'

rolandjitsu commented 7 years ago

@danbucholtz I agree, that'd be a reasonable solution. And I'm sure that it would cover most use cases.

@ehorodyski I think it's already possible to use aliasing if you use your own webpack config file (I cannot confirm it, never tried it). But I do see what you mean, though that would not work if you have async operations that need to run in order to compute the env values you want to have available in the app. It would also not work for the use case @josh-m-sharpe describes where you need some env vars that are not exposed by app scripts.

@josh-m-sharpe using the solution proposed would also solve what you're referring to. You'd just need to expose from process.env:

module.exports = function() {
    // process.env is an object and has all the env vars
    return Promise.resolve(process.env);
}

I think it's essential to have a more generic and universal solution, such as the one proposed by @danbucholtz in https://github.com/driftyco/ionic-app-scripts/issues/762#issuecomment-280666058, that can cover most of the uses cases since the dev needs vary as we can see from the posts on this topic.

biesbjerg commented 7 years ago

Am I the only one that really wants hinting of config keys, e.g. by defining a ConfigInterface? I have not seen it mentioned and I'm not sure how to do it elegantly, though...

ehorodyski commented 7 years ago

@biesbjerg - Right, this is what I'd like accomplished as well. I need to brush up on how to do Typescript module aliasing, so that the paths can be dynamically generated when you run ionic serve.

If ionic-app-scripts doesn't want to implement something like this, I think it would be great to use for yourself. It's really not hard, I've done it before.

coldAlphaMan commented 7 years ago

@danbucholtz all of the other stuff people are mentioning are great nice to haves. That said, i think your first comment is awesome enough and will suit most needs.

fiznool commented 7 years ago

@danbucholtz

You could write a service like this:

export class MyService {
   construtor(public http: Http){
   }

   makeServiceCall() {
      return this.http.makeRequest('$BACKEND_SERVICE_URL');
   }
}

Your implementation to replace it could look like this:

module.exports = function() {
   return Promise.resolve({
      '$BACKEND_SERVICE_URL' : 'localhost:8080/myService'
   });
}

Are you suggesting that '$BACKEND_SERVICE_URL' becomes a sort of 'magic string' that is replaced during compile time by the contents defined in the environment config file?

If so, I think this might be a bit confusing and difficult to maintain.

As others have suggested, an ideal solution would be something along the lines of the following, which could be achieved in webpack using resolve aliasing:

import { BACKEND_SERVICE_URL } from 'config';

export class MyService {
   construtor(public http: Http){
   }

   makeServiceCall() {
      return this.http.makeRequest(BACKEND_SERVICE_URL);
   }
}

I'm not sure how the above could be achieved with rollup. If this is a concern, a slightly lesser (but still very workable) version would be to add all config parameters to a global variable, e.g. ENV. With webpack, this could be achieved using the define plugin, and with rollup you could use the rollup replace plugin.

declare const ENV;

export class MyService {
   construtor(public http: Http){
   }

   makeServiceCall() {
      return this.http.makeRequest(ENV.BACKEND_SERVICE_URL);
   }
}

For those wishing for TypeScript autocomplete, ENV could instead be declared in src/declarations.d.ts as follows:

declare namespace ENV {
  const BACKEND_SERVER_URL: string;
  // Any other properties go here
}
danbucholtz commented 7 years ago

The resolve aliasing is interesting and wouldn't really require Webpack or Rollup to do it. From our perspective, a bundler is just a bundler, not a build tool. We don't dive into the world of plugins unless absolutely necessary, because they tighten our coupling to the tool. In our ideal world, we're going to swap out Webpack for a better bundler someday without 90% of our developers even noticing.

I think the aliasing leaves many use-cases unfulfilled where you need to load asynchronous data prior to a build. I guess you could do it ahead of time in a separate workflow/process and put it in an environment variable? I'm not sure, this seems a bit complicated to me.

I'll chat with some other team members this week and we'll figure out what we want to do. Any of these solutions will cover the vast majority of use cases.

Thanks, Dan

Ross-Rawlins commented 7 years ago

+1

ehorodyski commented 7 years ago

I think the aliasing leaves many use-cases unfulfilled where you need to load asynchronous data prior to a build. I guess you could do it ahead of time in a separate workflow/process and put it in an environment variable? I'm not sure, this seems a bit complicated to me.

Could you provide some use-cases for where you'd load async data prior to a build -- that would be environmental configurations?

Maybe there's a disconnect in what certain people are talking about. In my view, and many others, this is analogous to having .properties files in a Java project. They'd stay in the repo and only the specific file would get included in the build. Would the Promise resolutions happen during run-time?

riltsken commented 7 years ago

Just my perspective as a user, but I pretty much use environment variables for any configuration changes required among different environments or deploys. This means I can change a configuration value for prod, staging, dev, individual branch builds ... any N+ environments. Supporting N+ environments is easy with environment variables. Just use one template. When talking about property files though it becomes harder because now you need a property file per environment or to generate a property file per environment.

I'll post my specific project use cases that we have currently:

maxCacheAgeInDays
ionicCloudChannel
apiUrl
oauthClientId
logLevel
logentriesToken
googleMapsJavascriptApiUrl

In the individual threads I see this asked more than once for environment variable support. I could generate a property file I guess at buildtime, but that would basically be me duplicating what I am today in a different form. Below are some references to what I would consider are analogous solutions for the same problem.

references:

Anyway just some thoughts. I would really love environment variable support :).

vovikdrg commented 7 years ago

Angular-cli has implemented and its easy to configure it in angular-cli file why not to do the same?

https://github.com/angular/angular-cli/blob/3c3f74c060cc79f3872230a18eb0c1dd8371065f/packages/%40angular/cli/blueprints/ng2/files/angular-cli.json#L24

wethinkagile commented 7 years ago

We want this too!

juarezpaf commented 7 years ago

We're currently using a script that runs before ionic serve and generate the correct file for us. Let me explain it in more details here:

  1. We created an env folder in the root of the Ionic project and added this folder to our .gitignore
  2. Inside of the env folder we have different files:
    ./env
    production.json
    sandbox.json
    staging.json
  3. Each file has the variables we need, for example, our staging.json file looks like:
    {
    "api_url": "'https://staging.api.url'",
    "client_id_login": "'566d41f...'",
    "client_secret_login": "'511480878...'",
    "google_maps_key": "'tEkoJK...'"
    }
  4. We changed the scripts section inside of the package.json file to have a preionic phase and also an independent command:
    "scripts": {
    "ionic:build": "ionic-app-scripts build",
    "ionic:serve": "ionic-app-scripts serve",
    "preionic:build": "node ./scripts/replace.env",
    "preionic:serve": "node ./scripts/replace.env",
    "generate-env": "node ./scripts/replace.env",
    "test": "ng test"
    }
  5. Our replace.env.js file handles the generations of our config.ts file https://gist.github.com/juarezpaf/7a9007dfcef25ec24f7de900df8fe04e
  6. The config.ts.sample is very simple and it'll just expose these variables to use use across our app

    export class AppConfig {
    static get API() {
    return ENV.api_url;
    }
    
    static get GOOGLE_MAPS_KEY() {
    return ENV.google_maps_key;
    }
    
    static get CREDENTIALS() {
    const credentials = {
      'login': {
        'client_id': ENV.login.client_id,
        'client_secret': ENV.login.client_secret
      }
    }
    return credentials;
    }
    }
  7. We use the AppConfig in our AuthService:
    
    import { AppConfig } from '../config/config';

@Injectable() export class Auth { credentials: any; private apiUrl = AppConfig.API;

constructor(public http: Http) { credentials.client_id = AppConfig.CREDENTIALS.login.client_id; credentials.client_secret = AppConfig.CREDENTIALS.login.client_secret; } }


8. With everything in place we can use it in 3 different ways:
  * `npm run generate-env --sandbox`
  * `ionic serve --staging`
  * `ionic build:ios --production`

I found some *cons* with this `replace.env.js` approach:
 * Local files with tokens and other sensitive info
 * If we need other environments we need to change this file;
 * Write the variables into a the `config.ts` file every time;
jpbrown250 commented 7 years ago

Hey guys, I have been working all day on a temporary solution to this thread that should work for most of the use cases I have read in this and a few other threads of the same topic. The main concerns I noticed form suggestions include:

  1. Fear of an update that could break a solution
  2. Unable to use environment variables
  3. Required changing the text in a file to switch environments
  4. Required cardinal knowledge of the script and how it functions (personally)

My project should solve all of those issues. If there are any others I am happy to work on it. Git Repository

I have it fairly well spelled out in the README.md.

pbowyer commented 7 years ago

There is a very clean implementation at https://github.com/driftyco/ionic-app-scripts/pull/683#issuecomment-287401855 which I'm using successfully.

vkniazeu commented 7 years ago

@pbowyer , does it work for you with ionic build browser --prod? I've commented on #683 as it fails for me when the AoT Compiler kicks in.

vkniazeu commented 7 years ago

Solution in #683 fails with [17:52:03] Error: Error encountered resolving symbol values statically. Could not resolve @app/config relative to XXX/src/app/app.module.ts., resolving symbol AppModule in...

pbowyer commented 7 years ago

@vkniazeu That exact command works for me - but I can't see anything in the output saying AoT is running, so can't definitively confirm.

vkniazeu commented 7 years ago

@pbowyer , thanks! It's the ngc started ... line which indicates that angular-cli AoT compiler is being used. It should be default if the --prod flag is used. Are you using latest Ionic and Angular packages in your project?

pbowyer commented 7 years ago

@vkniazeu That line's present in the output, so it's being used. It's not present if I omit --prod.

As to versions, I'm on:

Cordova CLI: 6.5.0
Ionic Framework Version: 2.2.0
Ionic CLI Version: 2.2.1
Ionic App Lib Version: 2.2.0
Ionic App Scripts Version: 1.1.4
ios-deploy version: 1.9.1
ios-sim version: 5.0.13
OS: OS X El Capitan
Node Version: v6.10.0
Xcode version: Xcode 8.2.1 Build version 8C1002
vkniazeu commented 7 years ago

@pbowyer , thank you for your time. Strangely, it fails for another person as well with the same error and same setup. My package versions are newer, but I don't think this is the reason for the resolving symbol values statically error. I'll keep digging.

rolandjitsu commented 7 years ago

@pbowyer The solution described in https://github.com/driftyco/ionic-app-scripts/pull/683 does not work with AOT. And ngc should fail for import ... from '@app/config' as it will not be able to resolve it since it's never declared.

vkniazeu commented 7 years ago

@rolandjitsu , thanks for bringing this up again. Do you have an idea of how to overcome this lack of declaration for AoT to work? Or, perhaps, you have an alternative solution that would be similar in simplicity?

rolandjitsu commented 7 years ago

@vkniazeu I currently use Rollup instead of Webpack and rollup-plugin-replace.

rollup.config.js:

// For reference, check the following:
// https://github.com/driftyco/ionic-app-scripts/blob/master/config/rollup.config.js
// Config borrowed from: https://github.com/driftyco/ionic-cli/issues/1205#issuecomment-255744604
const nodeResolve = require('rollup-plugin-node-resolve');
const commonjs = require('rollup-plugin-commonjs');
const globals = require('rollup-plugin-node-globals');
const builtins = require('rollup-plugin-node-builtins');
const json = require('rollup-plugin-json');

// We use the replace plugin to provide the correct env variables
const replace = require('rollup-plugin-replace');

// We will use the machine ip to make HTTP requests to the local machine from an external device while in dev mode.
const ip = require('ip');
// We need to expose the app id to the app.
const ionicConfig = require('../ionic.config.json');

// NOTE: If IONIC_ENV is not set, we check if the CLI args contain the '--prod' flag.
function isProd() {
    return process.env.NODE_ENV === 'production' || process.env.IONIC_ENV === 'prod' || process.argv.slice(2)
            .some((arg) => arg.indexOf('--prod') !== -1)
}

// https://github.com/rollup/rollup/wiki/JavaScript-API
const config = {
    /**
     * entry: The bundle's starting point. This file will
     * be included, along with the minimum necessary code
     * from its dependencies
     */
    entry: process.env.IONIC_APP_ENTRY_POINT,

    /**
     * sourceMap: If true, a separate sourcemap file will
     * be created.
     */
    sourceMap: true,

    /**
     * format: The format of the generated bundle
     */
    format: 'iife',

    /**
     * dest: the output filename for the bundle in the buildDir
     */
    dest: process.env.IONIC_OUTPUT_JS_FILE_NAME,

    /**
     * plugins: Array of plugin objects, or a single plugin object.
     * See https://github.com/rollup/rollup/wiki/Plugins for more info.
     */
    plugins: [
        builtins(),
        commonjs(),
        nodeResolve({
            module: true,
            jsnext: true,
            main: true,
            browser: true,
            extensions: ['.js']
        }),
        globals(),
        json(),
        replace({
            values: {
                '{{API_HOST}}': isProd() ? 'https://api.domain.com' : `http://${ip.address()}:8888`,
                '{{IONIC_ENV}}': isProd() ? 'prod' : 'dev',
                '{{APP_ID}}': ionicConfig.app_id
            },
            // Config
            exclude: 'node_modules/**'
        })
    ]
};

module.exports = config;

env.ts (I placed it under src/app/):

export const env: any = '{{IONIC_ENV}}';
export const apiHost = '{{API_HOST}}';
export const appId = '{{APP_ID}}';

export function isProd(): boolean {
    return env === 'prod';
}

And you just import from env wherever you need. It should work with AOT as well. Though I'm encountering other issues with Rollup that are unrelated.

I'm not sure about a fix for @app/config, I imagine making a declaration file should suffice, but I'm not sure how ngc will work with it since it needs to resolve the values statically.

vkniazeu commented 7 years ago

@rolandjitsu , thank you for sharing your setup. I will consider it as my project grows if an Ionic own solution is not available by then.

mumairofficial commented 7 years ago

After reading above and googling, I got too many ideas for env variable setup and now fully confused about what is best for scale-able enterprise application? should I wait for ionic team implementation for ionic-3

jburghardt commented 7 years ago

Too many solutions are out there right now, most of them are not fully functional with prod development. We need a official solution and support from the ionic team for this.

rossholdway commented 7 years ago

Hello. Based off the great work by @juarezpaf in his previous comment, we're using something very similar.

Advantages for us with this approach are that it's relatively simple, does not involve changing webpack or Rollup config, works with prod / AOT and uses --env=[environment] flag.

We are able to use the standard ionic serve command, and default to a development env, or use the --env flag when we require a different environment e.g. ionic build ios --prod --env=production

Our setup is as follows (very similar to juarezpaf with a few modifications!).

  1. We have a .env folder containing json files for each environment (added to .gitignore)
    ./env
    production.json
    staging.json
    development.json

Example of .env/development.json

{
  "environment": "development",
  "endpoints": {
    "server1": "https://....",
    "server2": "https://...."
  }
}
  1. Add the script ./scripts/environment.js and reference it in package.json available at https://gist.github.com/rossholdway/16724496806b66a162ee6cbf8bfc5def
"scripts": {
    ...
    "ionic:watch:before": "node ./scripts/environment",
    "ionic:build:before": "node ./scripts/environment",
    ...
  }

NOTE: If you're using a version of ionic-cli < 3.4.0 use preionic:build and preionic:serve

This will generate ./src/app/app.config.ts.

  1. In your module import the config with import { APP_CONFIG, AppConfig } from './app.config'; and add as a provider

    providers: [
    ...
    {
      provide: APP_CONFIG,
      useValue: AppConfig
    }
    ]
  2. Now you can import your environment specific app config where needed via Angular DI. e.g.

import { Component, Inject } from '@angular/core';
import { APP_CONFIG } from './app.config';

@Component({
  selector: 'example-page',
  templateUrl: 'example-page.html'
})
export class ExamplePage {

  constructor(@Inject(APP_CONFIG) private config) {
    console.log(config.environment);
    console.log(config.endpoints.server1);
  }

}

There are some disadvantages, mainly that we can't use TypeScript in app.config.ts easily, but apart from that we are yet to run into any issues.

Usage examples ionic serve (Not specifying the --env flag will default to using .env/development.json) ionic build ios --prod --env=production (Will use .env/production.json to build app.config.ts)

danbucholtz commented 7 years ago

app-scripts is a never ending project. I'll hopefully have some time to tackle this in the coming weeks.

Thank you for being patient. 💯

Thanks, Dan

ekoome commented 7 years ago

+1

the-ult commented 7 years ago

@danbucholtz any news on your process? Or what would be a proper solution? Would the solution @rossholdway provided, be the best solution for now?

danbucholtz commented 7 years ago

Soon. Very soon! So here's what on my road map:

  1. Migrate to a "fesm" build of ionic-angular. It did not make it for this weeks release, but should be in in two weeks in the next release. This is basically bundling code with rollup before bundling it again with webpack. The reason for this is to avoid unnecessary closures. Our testing shows this should knock off around ~1 second of app start-up time on mobile devices. (I estimate this will take 2 more days)

  2. Make some fixes to navigation & deep linking in ionic-angular (I estimate this will take two weeks).

I think that's all I have that is higher priority than the environment stuff. We'll get this in soon.

Thanks, Dan

trumbitta commented 7 years ago

I personally reckon this issue should be higher priority than most, because having different configs for different environments is just something a good framework should have from the start if you want it to be used in professional settings.

This is also the reason why I'm so puzzled by Angular not having an official logging provider / solution.

But of course I'm glad you'll be finally working on it 🎉

yuricamara commented 7 years ago

Folks,

Look at: Ionic 2 Environment Variables: The Best Way

This solution works like a charm. I implemented it in my project. I even think that it removes this issue from so high priority.

trumbitta commented 7 years ago

@rossholdway you solution works for me only if I use npm run ionic:serve instead of ionic serve. Any hints?

trumbitta commented 7 years ago

Nevermind, it's working. It just doesn't log anything when run via ionic serve.

rossholdway commented 7 years ago

@trumbitta Sorry, I'm not sure why it wouldn't be working correctly with ionic serve for your setup. I'd just stick with using npm run ionic:serve for now as it sounds like it won't be long until we have support for environments built directly into app scripts 🎉

trumbitta commented 7 years ago

Hi @danbucholtz, sorry to bother you and thanks for your work!
Any news?

RoopeHakulinen commented 7 years ago

This would be really essential for me also. Anything that can be done to help you guys?