10

Let's say we have a .env file with some variables specified:

AWS_PROFILE=hsz
ENVIRONMENT=development

There is also a simple npm task defined:

{
  "name": "project",
  "version": "0.0.1",
  "scripts": {
    "deploy": "sls deploy"
  }
}

But runnning npm run deploy ignores our .env definition.

It can be resolved with better-npm-run like:

{
  "name": "project",
  "version": "0.0.2",
  "scripts": {
    "deploy": "bnr deploy"
  },
  "betterScripts": {
    "deploy": "sls deploy"
  },
  "devDependencies": {
    "better-npm-run": "^0.1.1",
  }
}

but this looks like an overhead - especially when we have 10+ tasks.

Is there a better way to always load .env without proxying all tasks via better-npm-run?

hsz
  • 148,279
  • 62
  • 259
  • 315

4 Answers4

15

A bit ugly, but you could try something like this:

"scripts": {
  "deploy": "export $(cat .env | xargs) && sls deploy"
}

This will export all environment variables from the .env file before running sls deploy.

There are some variations to this tehnique in this answer.

Not very clean but it avoids usage of an extra module.

mihai
  • 37,072
  • 9
  • 60
  • 86
  • 1
    This will crash when having commented lines in your .env file but you can fix it by replacing `cat .env | xargs` with `grep '^#' .env -v | xargs` – Flinth Sep 19 '22 at 10:04
9

You can use env-cmd npm package to set environment variables loaded from .env file before executing a npm script.

  1. Add package to your package.json devDependencies:
npm i env-cmd -D
  1. Prefix your npm script with env-cmd program in package.json:
{
  "scripts": {
    "deploy": "env-cmd sls deploy"
  }
}
Faisal Hasnain
  • 475
  • 6
  • 8
1

Maintain and load all your environment specific configuration in project itself.

dev.js

module.exports = {
    "host":"dev.com"
}

prod.js

module.exports = {
    "host":"prod.com"
}

config.js - main file that will resolve configuration based on process.env.ENV variable.

const dev = require('./dev');
const prod = require('./prod');
let envObject = {};
const env = process.env.ENV || "dev";
switch(env) {
    case 'prod':
        envObject = prod;
        break;
    default:
        envObject = dev;
}
envObject['ENV'] = env;
process.env = Object.assign(process.env,envObject); // Optional if you prefer to add them into process environment otherwise `require('./config')` where you need configuration. 
module.exports = envObject;

index.js - node project root file call every time when project start

const config = require('./config');
console.log('config object => ',config.host);

package.json

{
  "name": "project",
  "version": "0.0.2",
  "scripts": {
    "deploy": "sls deploy"
  }
}

Running you node.js code Prod environment ENV=prod npm run deploy; Development environment - npm run deploy;

Default environment is set to dev in ./config.js

Using this simple practice you don't need any npm module to manage your environment configurations.

front_end_dev
  • 1,998
  • 1
  • 9
  • 14
  • Thanks, but the point is to avoid prefixing `npm run` with any env variables; also in case of running `sls deploy` - external tool - no `index.js` is loaded at all. – hsz Nov 09 '18 at 08:31
  • Or create a .npmrc file inside the project root folder and set variable there. https://docs.npmjs.com/files/npmrc#files – front_end_dev Nov 09 '18 at 08:46
1

I was having the same issue while trying to syncing the DB using an external command and fixed the issue by requiring dotenv package which will load the variables

"scripts": {
"db-sync": "node --require dotenv/config ./src/sequelize/sync.js"}

then just call npm run db-sync

Mhd Wael Jazmati
  • 636
  • 9
  • 18