Environment.json vs environment.ts

I have just installed latest aurelia-cli 1.1.0 and the environment files (dev.js, prod.js) are no longer in aurelia_project folder but in config folder and they are .json files rather than .ts. Is this inentional? From which version, I cannot find any mention of this in release notes. Thank you!

1 Like

Yes, v1.1 refactored webpack setup. Please upgrade to latest v1.1.1 for better compatibility with old commands.

If you look at run and build task files, they are merely alias to npm start and npm run build. Basically, webpack runs directly by webpack without aurelia-cli magic (or should I say trouble).

The package.json listed those scripts.

The env files are now handled by a webpack plugin app-settings-loader by @Sayan751, instead of handled by aurelia-cli gulp task previously.

We will update doc for this change. You can still use au run, but you can directly use npm start.

1 Like

correct. and the new way to import environment is

import * as environment from '../config/environment.json';

Thank you!

1 Like

Also trying to update my code with this refactoring…

I am used to create more environments than just the old “dev.ts” and “prod.ts”. For exemple I used to have “stage.ts” file with values fitting our staging environment. Now with the new /config/environment.json structure I haven’t found how to start the application with staging values.

What I’ve tried is to create a file called /config/environment.staging.json and then run the app with

npm start --env staging

But it didn’t work :frowning:

What’s the correct way to do this ?

1 Like

The webpack setup has changed. We need to bring back customisable new env file. But right now, you need to update webpack.config.js to make that work.

The old au run --env prod still works because we had some code for the backward compatibility in aurelia_project/tasks/run.

But by default the webpack setup only checks production env, you can update two lines in webpack.config.js to support environment.staging.json.

module.exports = ({ production, staging } = {}, {extractCss ...

env files are handled by a webpack plugin now.

      { test: /environment\.json$/i, use: [
        {loader: "app-settings-loader", options: {env: production ? 'production' : (staging ? 'staging' : 'development') }},
      ]},

Update: forgot to mention

npx webpack-dev-server --env.staging
# or
npm start --  --env.staging`
1 Like

@Sayan751 we probably should use string version of env instead of the object version. We didn’t actually need the flexibility from the object version, the string version is easier for app-settings-loader to compose. But this is a semi breaking change if we switch the env syntax.

54%20am

2 Likes

Sounds good to me. We should do that. Probably release this with the next major version.

1 Like

This environment variable config stuff is a mess in aurelia-cli 1.2.3…

I tried doing what you said environment.stage1.json or stage2.json, and added the correct code to webpack.config.js and package.json scripts…

npm run build:stage1

and still compiles environment.json instead of environment.stage1.json

Nothing aside from “environment.production.json” or default environment.json

Documentation also doesn’t explain this. Not sure why we can’t just do something like au build --env platform1 or at least the webpack in package.json scripts section: "build:plat1": "webpack --env.platform1 --extractCss", or "build:plat1": "webpack --env.production=platform1 --extractCss",

1 Like

Sorry, our doc is definitely not up to date for it.
Can you show me your webpack.config.js and package.json?

1 Like

package.json

        "scripts": {
        "build": "webpack --env.production --extractCss",
        "build:stage1": "webpack --env.stage1 --extractCss",
        "build:stage2": "webpack --env.stage2 --extractCss",

environment.stage1.json

    {
      "debug": false,
      "testing": false,
      "f": false,
      "z": 5523
    }

webpack.config.js

    module.exports = ({ production, stage1, stage2} = {}, {extractCss, analyze, tests, hmr, port, host }
..

     { test: /environment\.json$/i, use: [
        {loader: "app-settings-loader", options: {env: production ? 'production' :  (stage1 ? 'stage1' : (stage2? 'stage2': 'development')) }},
      ]},

Command to run:

npm run build:stage1

au build doesn’t quite work at all.

aurelia logs say “config/environment.json” is the only one ever transpiled.

1 Like

If you want to have a 1 to 1 mapping between your config file and the environment, then you can do something like this.

package.json

    "build": "webpack --env.environment=production --extractCss",
    "build:stage1": "webpack --env.environment=stage1 --extractCss",

webpack.config.js

module.exports = ({ environment } = {}, {extractCss, analyze, tests, hmr, port, host } = {}) => ({
  mode: environment === 'production' ? 'production' : 'development', // this is for example; do the mapping as you see fit
  // also change other prod-specific instances 
  module: {
    rules: [
      { test: /environment\.json$/i, use: [
        {loader: "app-settings-loader", options: {env: environment }},
      ]}
    ]
  }
});
1 Like

I replaced everywhere in webpack config where it says “production” to “environment” and so that I get the benefits of both “production + stage1”

But when you run it:


module.exports = ({ environment } = {}, {extractCss, 

mode: (environment === 'production' || environment === 'stage1productionserver ') ? 'production' : 'development',

devtool: (environment === 'production' || environment === 'stage1productionserver ') ? 'nosources-source-map' : 'cheap-module-eval-source-map',

it still gets:

[BEPO] ./config/environment.json 31 bytes {0} [built]

I see in the chunk file loaded on 4:18 pm:

BEPO:function(n){n.exports=JSON.parse('{"a":false,"b":false}')}

Not correct I don’t think (I have no other way of checking if it loaded).

Also wish there was error checking "you entered environment=importantservernumber10 but we could not find environment.importantservernumber10.json to combine with environment.json"

Also wish we could do a const somewhere to define our array of environments that are meant to be used as production vs development:

environments: {'production': ['prod1', 'prod2', 'prod3'], 'staging': ['stage1'], 'development': ['development'] } pulls in env.prod1.json, env.prod2.json etc.

1 Like

With your original setup --env.stage1, if you print console.log('environment', environment); in main.js/ts.

It says {debug: false, testing: false}, this is the environment.stage1.json you provided, the default environment.json was {debug: true, testing: true}. However {f: false, z: 5523} is ignored by app-settings-loader. What app-settings-loader did is loading environment.json and using environment.stage1.json to override some values. The surprise is app-settings-loader ignored keys not defined in environment.json.

I think @Sayan751 can update app-settings-loader to allow keys that not defined in default environment.json.

2 Likes

@huochunpeng Now I see the actual problem. Thank you for pointing that out.

I would like to point out that this is intentional. From the loader documentation:

Merging configurations : The merge operation keeps the schema of the base file intact. That is, no unknown properties or property value of different type, from the customization files can be applied on the base file. This makes sense because during development you expect a certain set of keys and values of certain datatype to be present in your config and you program against this known schema. Therefore any new keys present in the customization file cannot and should not play any part in the source code.

I would like to ask @ArchEnemy how you are going to use these (temporarily non-existent) config parameters in code?

1 Like

I agree with you (I must have missed that part of the documentation, if it was more prominent I might have read it with more attention). Though I wish an error was displayed when keys were added by accident, if I ran into this, there will be several other devs who will run into the same issue. There’s just no easy way to debug what has gone wrong. Things like webpack and environment don’t make things easy to test so they should be better logged.

But again, I just created it npm run build:stage1…

app[…].chunk.js:

BEPO:function(n){n.exports=JSON.parse('{"a":false,"b":false}')

I even changed environment.production.json. nothing is registered. Nothing seems to change the chunk file in dist folder no matter what you change.

If I run as “production” it still doesn’t do it. At some point it started doing it, not sure why but only for production. The logs always say: [BEPO] ./config/environment.json 50 bytes {0} [built]

However, if I add a new “npm run start:stage1” vs “npm run start” … everything is working as expected successfully. The two environments print out correctly.

I can’t run dist/index.html locally as there are pathing errors. But I’m checking app[chunk].bundle.js and it has the old data. Is it cached?

1 Like

Would it be possible for you to push your reproduce-able code to a GitHub repo?

1 Like

I couldn’t really reproduce the error, but after some different compiles eventually the change propagated to that JSON.parse. I had to use a small static webserver to test the dist/ folder as well to see if it worked with a console.log(environment).

I added project.build.options.environments.includes() to create an array of production environments that need minification while dev environments could be set without webpack minifications.

Also the last issue that remains is that au build --env.environment=s1 seems to transmit that to webpack as webpack --extractCss "--env.environment=s1" <— see the double quotes? I have to use npm run build:prod or npm run start:s2 instead of au build or au run.

Not sure why it puts it in double quotes and so it doesn’t seem to register the variable.

1 Like

I got it to work when i added

    "build:int": "webpack --env.integration --extractCss",
    "build:prod": "webpack --env.production --extractCss",

to the package.json scripts section and then call it with npm run build:int.
But i had to adjust webpack.config.js like suggested above by adding integration next to production variable.