...because separate files are painful.
- Merge our custom webpack config into the Ionic config, so upgrading Ionic won't cause future problems
- Rewrite config paths to include the environment-specific config
- Merge our app configurations together, so properties cascade
- Possible to autocomplete the app configuration in my IDE (Jetbrains WebStorm)
- Add shortcut commands for building e.g.
build:prod
,build:uat
etc - Validate our config so no required fields are missing/set to the default placeholder value
See the stand-alone installation guide.
# See the default configuration on screen
$ npm run ionic:serve
# See the dev configuration on screen
$ npm run ionic:serve:dev
# You get the pattern... two others defined are
$ npm run ionic:serve:uat
$ npm run ionic:serve:prod
For Cordova I've hardcoded commands in package.json
:
$ npm run cordova:build:dev
$ npm run cordova:build:uat
$ npm run cordova:build:prod
Aside: it appears to work with the ios
omitted from the package.json
scripts, which allows flexibility to build for Android and iOS from one command. Not yet tested!
In this example we'll create the environment myspecialone
.
- Create a file in
src/environments
calledenvironment.myspecialone.ts
. - Open
package.json
and add scripts for this environment to the scripts section:"cordova:build:myspecialone": "cross-env NODE_ENV=myspecialone ionic cordova build ios --prod", "ionic:serve:myspecialone": "cross-env NODE_ENV=myspecialone ionic serve",
- That's it :)
Sorry it's not more automatic, I can't think of a way to auto-generate these commands. If you know how, tell me!
TBC
Why does this matter? Why go to all this effort?
Having used Symfony for many years I've come to appreciate config files that inherit other config files. It reduces repetition, allows composition, and makes working with them more pleasant.
Merging configurations is not as straightforward as it first seems. When you encounter arrays, do you replace or append? Do you merge or overwrite?
For this project, I've taken the approach of merging where possible. This keeps the code size down, but if you want more control here's other merging libraries that can be used -- and a summary of my research.
I chose this to merge our Webpack changes into the main configuration file. Why this and not webpack-config? Because it's more popular.
I also liked the way you can choose and change how the merge happens. It's very nice - check out the documentation.
Does the same job as above, with fewer options available. However it also takes care of loading the base webpack file, which gives a cleaner API in usage.
While both are called webpack-*
, they can be used to merge our app configuration. There are also more single-purpose libraries we can use:
Allows control over how to merge arrays and array values. I chose this again because it's more widely used and I liked the idea of having control over the merging, if needed in the future.
An improved alternative to deepmerge (according to the developer) which handles shallow or deep copy or merging properly. For this setup, deep vs shallow doesn't matter.
I spent a while looking for an existing library to use. My requirements were:
- structure. .ini files have no structure beyond
KEY=VALUE
. I find groupings make config values easier to deal with - config inheritance. We have configuration variables that don't need to change between environments - they're in a file for easy editing.
.env
(dotenv) is great for setting current values, and there are work-arounds for storing different environments and cascading them (see this great post for how to with React)
- Investigate if combining with dotenv makes sense, so sensitive credentials are stored separately from the environment files (i.e. not in Git)
- Add
CHANGELOG.md
andUPGRADE.md
to the repository - Investigate packaging as a NPM package
- Switch to releases, and record breaking changes
- More documentation, notes, rationale etc