Build separated development environments with direnv
TL;DR
Working with Ionic sometimes means to handle different versions of Ionic/Cordova and Ionic/Cordova Plugins. My goal was, to setup an Ionic environment specify for each project. And I want do activate the environments automatically.
I started with autoenv, but unfortunately there is no unload/deactivate mechanism. So, finally, i switched to direnv. But i also tried different solutions with Vagrant or Docker.
Requirements
You will need a package manager to install the different software packages. There are a variety of package manager for the different platforms.
For macOS, i will use Homebrew.
Things about my directory structure
Mostly, i try to group files in different directories, depending on their functionality.
Environment files goes to a directory .env. But, wait: there could be more environments (node.js, ruby, python), which all could be used in my project.
So, i decide to use subfolders for each possible environment. Here it looks like:
$ tree myproject myproject └── .env ├── nvm ├── pyenv └── ruby
Some small example
Suppose, you have this directory structure
. ├── home │ ├── .envrc │ └── bath │ └── .envrc └── office └── .envrc
If you walk between this different rooms, you will see how direnv follow you
~/tmp$ cd home direnv: loading .envrc You are at home ~/tmp/home$ cd bath direnv: loading .envrc You are in the bath ~/tmp/home/bath$ cd .. direnv: loading .envrc You are at home ~/tmp/home$ cd .. direnv: unloading ~/tmp$ cd office direnv: loading .envrc You are at work ~/tmp/office$ cd ../home/bath direnv: loading .envrc You are in the bath ~/tmp/home/bath$
Installation
There is a detailed installation instruction here, but for macOS, here is the simple step
$ brew install direnv ==> Downloading https://homebrew.bintray.com/bottles/direnv-2.14.0.high_sierra.bottle.tar.gz Already downloaded: /home/user/Library/Caches/Homebrew/direnv-2.14.0.high_sierra.bottle.tar.gz ==> Pouring direnv-2.14.0.high_sierra.bottle.tar.gz /usr/local/Cellar/direnv/2.14.0: 8 files, 3.7MB
Finally, check if installation has succeed
$ direnv version 2.14.0
Configuration
Directory specific configuration is made through the file .envrc. It’s like a normal Shell profile script, so mostly all commands are allowed and possible.
Entering the directory triggers this configuration file, so a normal cd into the directory does the environment setup.. pretty cool!
In my simple example, i used this configuration files
~/tmp$ find . -name .envrc ./home/.envrc ./home/bath/.envrc ./office/.envrc ~/tmp$ find . -name .envrc -exec cat {} \; echo "You are at home" echo "You are in the bath" echo "You are at work"
Setting up a sample project
Ionic heavily depends on node.js So, the challenge is to setup different node.js environments. Luckily, there is already a solution for that: Node Version Manager nvm.
Install nvm
For macOS, this is quit simple (details could be found here)
$ brew install nvm
Or, manually
$ wget -qO- https://raw.githubusercontent.com/creationix/nvm/v0.33.8/install.sh | bash
Setup directory structure
Create the desired directory structure
$ cd $HOME/tmp $ mkdir -p myproject2/.env/nvm
Configure direnv
Add the following lines (with some additional lines) into your direnv configuration file .envrc
#!/bin/bash export NVM_DIR=$HOME/tmp/.env/nvm echo setup nvm with NVM_DIR=$NVM_DIR . /usr/local/opt/nvm/nvm.sh nvm --version
Hint: When you created the file (for example with vi), you get the error message, that the .envrc file is blocked
$ vi .envrc direnv: error .envrc is blocked. Run `direnv allow` to approve its content.
Follow the suggested solution: run direnv allow
$ direnv allow direnv: loading .envrc setup nvm with NVM_DIR=/home/user/tmp/myproject/.env/nvm 0.33.8 direnv: export +NVM_CD_FLAGS +NVM_DIR +NVM_RC_VERSION
Now, test the configuration: Leave the directory and enter it again
$ cd .. direnv: unloading $ cd myproject direnv: loading .envrc setup nvm with NVM_DIR=/home/user/tmp/myproject/.env/nvm 0.33.8 direnv: export +NVM_CD_FLAGS +NVM_DIR +NVM_RC_VERSION
Hint: If this does not work, try to start the configuration file manually for the first time,
$ cd $HOME/tmp/myproject $ . .envrc setup nvm with NVM_DIR=/home/user/tmp/myproject/.env/nvm 0.33.8
Fix possibile warnings and errors
If you get this error message
nvm is not compatible with the npm config "prefix" option: currently set to ...
Then, issue this command
$ npm config delete prefix
Install node
Now, the real task: install node.js
$ cd $HOME/tmp/myproject $ nvm --version 0.33.8 $ node --version -bash: node: command not found $ nvm install 9.4.0 Downloading and installing node v9.4.0... Downloading https://nodejs.org/dist/v9.4.0/node-v9.4.0-darwin-x64.tar.xz... ######################################################################## 100,0% Computing checksum with shasum -a 256 Checksums matched! Now using node v9.4.0 (npm v5.6.0) Creating default alias: default -> 9.4.0 (-> v9.4.0)
Test the installation
$ which node /home/user/tmp/myproject/.env/nvm/versions/node/v9.4.0/bin/node $ node --version v9.4.0
If you want to use an additional node version (maybe the latest LTS version), just install it
$ nvm install lts/carbon Downloading and installing node v8.9.4... Downloading https://nodejs.org/dist/v8.9.4/node-v8.9.4-darwin-x64.tar.xz... ######################################################################## 100,0% Computing checksum with shasum -a 256 Checksums matched! Now using node v8.9.4 (npm v5.6.0)
You can switch between the different versions with nvm use
$ nvm use lts/carbon Now using node v8.9.4 (npm v5.6.0) $ node --version; npm --version v8.9.4 5.6.0 $ nvm use default Now using node v9.4.0 (npm v5.6.0) $ node --version; npm --version v9.4.0 5.6.0
Setting up Ionic Environment
After this required preparation, we can start setting up our Ionic Environment
For this example, I choose the following start path: ~/Workspace/Ionic3
Setup directory structure
$ mkdir -p $HOME/Workspace/Ionic3/.env/nvm $ cd $HOME/Workspace/Ionic3 $ vi .envrc
Create the direnv configuration file
Configuration file
#!/bin/bash #------------------------------------------------------------------------------- # #------------------------------------------------------------------------------- HERE="$PWD" #------------------------------------------------------------------------------- # #------------------------------------------------------------------------------- _USE_NODE_VERSION=9.4.0 #------------------------------------------------------------------------------- # #------------------------------------------------------------------------------- export NVM_DIR="$HERE/.env/nvm" echo "setup nvm: $NVM_DIR" . /usr/local/opt/nvm/nvm.sh nvm use $_USE_NODE_VERSION --silent echo "enabled nvm : $(nvm --version) $(which nvm | sed 's#'$NVM_DIR'/##')" echo "enabled node: $(node --version) $(which node | sed 's#'$NVM_DIR'/##')" echo "enabled npm : $(npm --version) $(which npm | sed 's#'$NVM_DIR'/##')"
Allow the configuration file for use
$ direnv allow direnv: loading .envrc setup nvm: /home/user/Workspace/Ionic3/.env/nvm enabled nvm : 0.33.8 enabled node: v9.4.0 versions/node/v9.4.0/bin/node enabled npm : 5.6.0 versions/node/v9.4.0/bin/npm direnv: export +NVM_CD_FLAGS +NVM_DIR
Test the configuration
~$ cd ~$ cd Workspace/Ionic3 direnv: loading .envrc setup nvm: /home/user/Workspace/Ionic3/.env/nvm enabled nvm : 0.33.8 enabled node: v9.4.0 versions/node/v9.4.0/bin/node enabled npm : 5.6.0 versions/node/v9.4.0/bin/npm direnv: export +NVM_CD_FLAGS +NVM_DIR
Well done!
Setup Ionic
Install required parts
$ npm -g install ionic@latest cordova@latest
Test your installation
~/Workspace/Ionic3$ ionic --version 3.19.1 ~/Workspace/Ionic3$ cordova --version 8.0.0 ~/Workspace/Ionic3$ $ which ionic /home/user/Workspace/Ionic3/.env/nvm/versions/node/v9.4.0/bin/ionic
And, finally, work with Ionic
$ ionic start super super --cordova --no-link $ cd super $ ionic serve
Next steps
Happy with this, maybe you want to try other things.