I am wanting to access the env config from next.config.js in order to surface some env vars set in .env.local and set some server runtime config based on them.
Is it reasonable in next.config.js to do...
const { loadEnvConfig } = require("#next/env");
const env = loadEnvConfig(".").combinedEnv;
It works, but I can't find any docs that explain how to do this, or if it's a supported package/api.
As documented here: https://nextjs.org/docs/basic-features/environment-variables#test-environment-variables
When you run loadEnvConfig it actually updates process.env to include config that next js uses, so this should work...
const { loadEnvConfig } = require("#next/env");
loadEnvConfig(".")
// process.env.SOMETHING <~~ includes value of SOMETHING set in .env.local
Related
Looking for elegant and simple solution to have "local configuration override" files.
The idea is to be able to have local configuration that will not ask to be added to git repository every time.
For that I need to include local.config.js if it exists.
I have global app configuration in config.js with configuration like
export const config = {
API_URL="https://some.host",
}
and config.local.js
export const config = {
API_URL="https://other.address",
}
there's .gitignore:
config.local.js
Difficulty:
I do not want to add a node module to project just for this one thing. I believe there should be an elegant way to do this in one or few lines, but have not found any so far.
Things that I tried:
1.
try {
const {
apiUrl: API_URL,
} = require('./config.local.js');
config. API_URL =apiUrl;
} catch (e) {
}
require does not work inside try{} block.
2.
const requireCustomFile = require.context('./', false, /config.local.js$/);
requireCustomFile.keys().forEach(fileName => {
requireCustomFile(fileName);
});
does not work.
3.
export const config = require('./config.local.js') || {default:'config = {...}'}
does not work.
4.
Using .env and settings environment variable: I need to override whole array of configuration values. Not one by one.
This solution uses process.argv. It is native to node as documented here and does not use .env
It inspects the command values used to start the app. Since these should be different between your local and production environments, it's an easy way to switch with no additional modules required.
command prompt to start your node app:
(this might also be in package.json and incurred via npm start if you're using that approach.)
$ node index.js local
index.js of your node app:
var express = require('express');
var config = require('./config');
if (process.argv[2] === 'local') {
// the 3rd argument provided at startup (2nd index) was 'local', so here we are!
config = require('./config_local');
}
var app = express();
// rest of owl…
I have a node.js application built using graphql. I need to check an 'environment variable' to see what environment I'm on (development, testing, production). Based on that environment, I need to set a url. I think I have a vague idea of what I need but don't know how to accomplish it.
Currently my config.js file looks something like this:
const configuration = convict({
env: {
format: ['development', 'testing', 'production'],
default: 'development',
arg: 'nodeEnv',
env: 'NODE_ENV'
}
const env = configuration.get('env');
configuration.loadFile(`./config/${env}.json`);
configuration.validate({allowed: 'strict'});
module.exports = configuration.getProperties();
)};
And then in a separate file where I actually need to set the url based on the environment, I need to do so based on the kind of environment (development, test or production) that I'm on. The code in that file would be:
If(env=='development'){
const url = 'abc.def.com/xxx/yyy/zzz/graphql';
}
Else If (env == 'testing'){
const url = 'xxx.yyyy.com/abc/def/ghi/graphql';
}
Else{
const url = '123.abc.com/cdc/def/hhh/graphql';
}
I tried to console.log the env value but when I try the following:
console.log( env );
I get an error: Reference error: env is not defined.
Can someone point me to what I'm missing/doing wrong to access the env variable?
You can access them like this:
process.env.VARIABLE_NAME
The documentation for Vue CLI 3 says here https://cli.vuejs.org/guide/mode-and-env.html#using-env-variables-in-client-side-code:
You can have computed env vars in your vue.config.js file. They still need to be prefixed with VUE_APP_. This is useful for version info process.env.VUE_APP_VERSION = require('./package.json').version
This is exactly what I want to do. But I couldn't find out how to actually define the env var there in vue.config.js. I tried:
module.exports = {
process.env.VUE_APP_VERSION: require("../package.json").version,
...
}
But it just produces an error:
ERROR SyntaxError: Unexpected token .
/Users/lhermann/htdocs/langify/frontend/vue.config.js:2
process.env.VUE_APP_VERSION: require("../package.json").version,
^
Does anyone know?
The environment variables are not part of the config export, you just set them in the vue.config.js file, eg
process.env.VUE_APP_VERSION = require('./package.json').version
module.exports = {
// other config, eg configureWebpack
}
I've raised a feature-request to get an example added to the docs ~ https://github.com/vuejs/vue-cli/issues/2864
Common Environment Variables:
According to Environment Variables and Modes documentation, you can specify env variables by placing .env files in your project root.
The variables will automatically be accessible under process.env.variableName in your project. Loaded variables are also available to all vue-cli-service commands, plugins and dependencies.
.env # loaded in all cases
.env.local # loaded in all cases, ignored by git
.env.[mode] # only loaded in specified mode
.env.[mode].local # only loaded in specified mode, ignored by git
Your .env file(s) should look like this:
VUE_APP_MY_ENV_VARIABLE=value
VUE_APP_ANOTHER_VARIABLE=value
Note that only variables that start with VUE_APP_ will be statically embedded into the client bundle with webpack.DefinePlugin.
Computed Environment Variables:
If you want variables that need pre-processing, you can use chainWebpack property of vue.config.js to inject anything you want:
// vue.config.js
module.exports = {
// ...,
chainWebpack: config => {
config.plugin('define').tap(args => {
args[0]['process.env'].APP_VERSION = `"${require("../package.json").version}"`
return args
})
}
// ...
}
Using this method, you can inject anything, with any names you want; you are not bound by the VUE_APP_ limitation.
I'm trying to mutate the value of my config in memory for testing, I've tried adding process.env.ALLOW_CONFIG_MUTATIONS=true in several spots in the application, as well as through the command line and my .env file.
The config.util.getEnv('ALLOW_CONFIG_MUTATION') method always returns undefined.
I've also tried using importFresh and MockRequest as per examples I've seen online, neither of which allow me to mutate the config in memory, and then reset the value later.
Does anyone have any idea about this?
Update: here's an example of what I'm trying to accomplish
const config = require (config);
const app = new App(config)
it(`does a thing with base config`, () => { ... }
it('does a thing with modified config, () => {
// here i would need to modify my config value and
// have it change the original config that's currently in
// application memory
config = newConfig
expect(config.get('newValues')).to.equal(true)
}
Thanks!
If it is the same config module that I have used (I think I is) then add a custom-environment-variables.js OR test.js with you test config.
test.js will need an ENV=test to work and the custom-environment-variables need something like (for Mac's and NPM) $ npm run funcTest -> yarn serverRunning && NODE_ENV=test wdio wdio.conf.js.
the JSON will look something like
{
test: 'Value'
}
I have the following in one of my project files:
const baas = process.env.DBID;
console.log('baas', baas);
If I run:
cross-env PORT=4000 NODE_ENV=production WEBPACK_CONFIG=browser_prod,server_prod webpack --colors
My server.js file looks like:
const baas = undefined;
console.log('baas', baas);
As expected. However, I want to be able to set the ID when I run the built app not when I build the app, ie:
DBID=someotherid node dist/server.js
So I need webpack to not convert const baas = process.env.DBID to it's value at build time, but rather leave it as is, so the server.js uses it's value at runtime.
How do I do this?
Note: if I manually edit the built server.js and change undefined to process.env.DBID then the run script works and the app uses the env var from run time, but I don't want to edit files after building.
You are using the wrong target.
By default, webpack builds the application to be run in the browser. This means it will mock native node functions like path fs and process
Your target is node, so there is no need to mock these.
Add this to your webpack.config.js
module.exports = {
target: 'node'
};
https://webpack.js.org/concepts/targets/#usage
What you need is process.argv not process.env:
// server.js
const baas = process.argv[0];
console.log('baas', baas);
Then:
node dist/server.js baas_value
For convenience, you can use this module https://www.npmjs.com/package/yargs
I was able to prevent Webpack from converting process.env by accessing it indirectly like this:
const processText = "process";
const _process = global[processText];
app.listen(_process.env.PORT || 2000);
You need to get process indirectly instead of env because the process variable is defined by webpack to be something like /* provided dependency */ var process = __webpack_require__(/*! process/browser */ "process/browser");