Ember with external config file?


#1

Hello,

We have 3 environment (qa, dev and prod) and we wish to only build our app once and during deployment we would instruct the ember app to load the right config file.

Alternatively instead of loading an hardcoded file is there a way for the app to remotely fetch the config file ? Like this we could remotely modify some config without the need to build and redeploy ?

Thank you


#2

In our team we keep environments urls in environment.js. eq.

{
  dev: {
    urls: ['localhost:4200', '127.0.0.1:4200'],
    api: 'http://dev.api.url'
  },
  test: {
    urls: ['test.app.url'],
    api: 'http://test.api.url'
  } 
}

Then in runtime we parse that object and save it in service. that way you always know all details about environment. Other config properties are shared across environments.


#3

Could you give me an example of how you parse an external js from within an ember app ?


#4

it’s not external, that config is part of config/environment.js


#6

But how do you still have an config/environment.js after “ember build” ? When I do ember build everything gets mashed up in a meta tag in index.html.

Could you provide me with a small snipped of how you achieve dynamic config loading ?

Thank you!


#7

@John are you saying you only want ember build to be run once to build 3 different versions of the app? As far as I’m aware this is not possible. Ember CLI does significantly different things to a prod build, for example, vs a dev build. The built assets will turn out completely different between the two environments so it’s not as simple as just changing the environment config.


#8

@dknutsen Yes, we only wish to ‘ember build’ once since the code does no change, only the properties (api url etc…) do. So the idea would be to have a kind of pipeline

  1. build the app
  2. ZIP it and store it somewhere
  3. deploy to DEV
  4. deploy to QA
  5. deploy to PRE-PROD
  6. deploy to PROD

the only difference from 3) to 6) is the config file that changes that we would place it ‘somewhere’ in the app and that is loaded at runtime.

We didn’t know ember does something different when using ember build -prod vs ember build -dev. If indeed it does something completely different I guess in that case we can drop our idea of a one time build


#9

Yeah I see what you’re saying, definitely don’t think it’s possible. For starters I know a prod build will fingerprint everything, minify it, and do some other fancy smashing and munging. That doesn’t happen with dev builds, and doesn’t happen with custom environments (our company has “whitelabeled” builds so even our “other” production builds aren’t the same as our main “production” build). And then if you throw in addons that use hooks for prod builds only (ember test selectors, for example) there are even more differences.

Not sure what your use cases are beyond what you’ve described above but I would highly recommend checking out ember-cli-deploy if you’re not already using it. Very extensible deploy pipeline which can do all kinds of neat stuff out of the box with existing plugins, or you can write custom plugins.


#10

As I mentioned before it’s possible and we use one build across different environments.

As @dknutsen mentioned dev and prod builds are different but code base is the same. In prod build your code gets minified, images could be squashed, etc. you certainly don’t wont either deploy dev build to prod nor do all prod build jobs during development.

So how it looks like, is for development we of course use dev build done during ember serve or ember build. We use serve, as no need to start other local server.

For all other environments ( test, uat, prod) we use prod build and only deploy zipped package. That’s handled by bamboo (but jenkins could be used as well).

To use config in your app you simply have to import it as mentioned here https://guides.emberjs.com/v2.16.0/configuring-ember/configuring-your-app/

to distinguish between environments you have to use url for it. In your config set

envs: {
  dev: {
    urls: ['localhost:4200', '127.0.0.1:4200'],
    api: 'http://dev.api.url'
  },
  test: {
    urls: ['test.app.url'],
    api: 'http://test.api.url'
  } 
}

then you check every urls property against window.location.host, if match then you have your environment.

Minus of that solution is that all environments url will be available inside prod app code, so potentially that’s a security issue.


#11

You need to build for every env. I use the envfile and a CD with envs vars sets to what kind of env it’s building.

https://github.com/fivetanley/ember-cli-dotenv this addon that use dotenv library is a good one to try.


#12

It’s easy to confuse two separate topics here.

ember-cli has three kinds of builds (dev, test, and prod). Dev is for running locally, test is for running test suites, and prod is for running on an actual website.

That is separate from the question of which website you want to run on.

If you have dev, QA, and production websites, those are still all production builds from ember-cli’s perspective. How you manage separate configuration for each of them is somewhat up to you. My recommendation is to use ember-cli-deploy and create separate deploy targets for each one, so you can run ember deploy qa vs ember deploy production.

It’s not strictly true that you need to rebuild for every environment. It’s enough to do one production build and then make your own <meta> configuration for multiple environments (it’s just url-encoded JSON). That’s why we put configuration in <meta> by default instead of compiling it into the Javascript – it makes it easier to swap it out if you want to.


#13

I did this (modifying the tag, among other things) for an ember sample app, which uses FastBoot.

There are a bunch of things configurable through environment variables - i.e. fastboot’s hostWhitelist, and the backend URL. Everything is done by this “app reconfiguration” script, which modifies the index.html and the package.json files on the dist/ folder, right before launching the fastboot app server.

I hope this helps anyone!