Use env variable in VueJS SPA components at runtime? - vue.js

I'm building a simple SPA with VueJs and Webpack, and would like to use/access env variables from my VueJS components.
I know I will not be able to change those variables "on the fly" but instead I need to recompile-rebuild-redeploy the entire application to see the changes, but for now it's ok since the actual need is to show different info and/or sections base on the deploy environment (local, staging, production).
To be more specific, for now I'm trying to get the env var COMMIT_HASH just to display it as some applications already do just for development info.
This variable would primarily used by the pipeline for the staging deployment, as in local development would be not that useful and probably not used at all for production deployment.
The problem is that I cannot figure out how to access env variables values from my VueJS components scripts sections at runtime, as process.env is a Node method accessible only during webpack compilation and not at runtime.
I thought about using string replacement and found this question, but then I would need to update Webpack script for any new env variable I need to use, so it looks quite inelegant to me.
I also tought of loading all the env variables in a js object and somehow pass it down to the files being compiled by Webpack, but this also looks inelegant/inefficient to me.
So now I'm stuck as can't figure out how to access env vars from my VueJS components at runtime.

I ended up using string-replace-loader with regex matching and a callback for dynamic replacement.
Basically I'll use env.SOME_VARIABLE in my code and search/replace it with the variable value.
For some reason I couldn't make the regex work with the \w to match for word characters and used [a-zA-Z_] instead.
{
test: /resources.*\.js$/,
loader: 'string-replace-loader',
options: {
search: 'env\.([a-zA-Z_]+)',
replace(match, p1, offset, string) {
return process.env[p1];
},
flags: 'g'
}
}
Notes
Since it is text replacement I cannot simply assign env variable values to vue component data properties as it would be interpreted as a variable:
// E.g. given env `COMMIT_HASH=some_hash`
data() {
return {
/**
* WRONG:
* this would be parsed as
* hash: some_hash
* leading to an
* Uncaught ReferenceError: some_hash is not defined
*/
hash: env.COMMIT_HASH,
/**
* RIGHT:
* wrap string to be replaced in single/double quotes so after
* replacement it became a string literal assignment.
* hash: "some_hash"
*/
hash: "env.COMMIT_HASH",
};
},

Related

Vue. How to pass a variable I have on server (process.env.SERVER) to the browser

On the frontend server I have a file I can read with:
if(!!process.env.SERVER) {
require("dotenv").config( { path: '/hw/.env', debug: true } )
console.log(process.env.myvar)
}
But how can I pass the vlue of process.env.myvar to the browser?
Thanks.
If you want to get some variables for all cases you can create an enviroment file with just .env as the name next to package.json in your project.
To get variables from that file you need to declare them first in the .env like this:
VUE_APP_MYVAR = 'myvar'
In your app you can use it like this:
process.env.VUE_APP_MYVAR
If you need some variables depending on the process, respectively for your enviroment, your myvar can't be called with process.env.SERVER. If SERVER is the process, you need a .env.server file next to your package.json.
You can then, again, declare myvar in .env.server like this:
VUE_APP_MYVAR = 'myvar'
To get process.env.VUE_APP_MYVAR this time you have to ensure, that you build or serve your enviroment named server. Else, your app trying to get process.env.VUE_APP_MYVAR with the process you used.
For Example: If you have .env.development and .env.server, both can contain VUE_APP_MYVAR = 'myvar' with different assigned values. Which one is picked depends on the enviroment you build or serve.
For more information, see the docs: Modes and Environment Variables
#Modes

Recommended dynamic runtime configuration technique on nuxtjs (other than dotenv)

I have been trying to use publicRuntimeConfig / privateRuntimeConfig
On nuxt 2.4.1, I have defined my runtime config as follows on nuxt.config.js
publicRuntimeConfig: {
DATA_API_HOST_URL: process.env.VUE_APP_DATA_API_HOST_URL,
},
privateRuntimeConfig: {
AUTH_APP_CLIENT_SECRET: process.env.VUE_APP_AUTH_APP_CLIENT_SECRET,
},
and calling it as follows on my login.vue
asyncData( ctx ) {
console.log(ctx.$config.DATA_API_HOST_URL)
//some activity
}
The keys are showing up on $config inside asyncData. I debugged on chrome dev tools. But value is not read from process.env.VUE_APP_DATA_API_HOST_URL. The value is showing up as undefined. However, process.env.VUE_APP_DATA_API_HOST_URL is showing the value OK. The whole point is to move away from process.env.
this.$config.DATA_API_HOST_URL also does not access the values.
'${DATA_API_HOST_URL}' is shown in examples but I believe it is only for explicit param declarations at asyncData like asyncData( { $config : {DATA_API_HOST_URL}).
When I pass values as it is using DATA_API_HOST_URL: process.env.VUE_APP_DATA_API_HOST_URL || 'https://test.api.com', it seems to copy the value fine using ctx.$config.DATA_API_HOST_URL!
Looking to me like copying process.env to *RuntimeConfig has a problem!
What is the recommended way of importing and using runtime configurations?
As per documentation in the Nuxt blog post you marked, the feature your are trying to use is released in 2.13 (you´re using 2.4 if i not misunderstood). That could be the reason behind the behaviour you're seeing.
I'd recommend update your project dependencies or trying another approach.
I think you should use Docker to set dynamic runtime config like link below:
https://dev.to/frontendfoxes/dockerise-your-nuxt-ssr-app-like-a-boss-a-true-vue-vixens-story-4mm6

How to set Terraform workspace variables via CLI?

I'm using workspaces in terraform to separate environments at runtime, so that I can separate deployments using a different configs.
However, I'm trying to figure out how to set CLI variables.
my variables.tf:
locals {
environment = "${terraform.workspace}"
lambda_vars = {
deploy_version = "0.1"
deploy_name = "deployment"
deploy_secret_1 = "somesupersecretsecret"
}
}
These variables are used throughout my config.
I'm trying to set new variables using the CLI, but it doesnt work, and I can't seem to find any reference to how to achieve this. I've tried:
terraform apply -var 'local.lambda_vars={ deploy_secret_1 = "somesupersecretsecret1" }'
I feel like I'm going about this the wrong way.
Can anyone help?
If you want to be able to configure the variables then you should use actual variables instead of locals. Locals are a way of composing things so you avoid repeating yourself or can use interpolation. Variables don't allow for any interpolation at all.
So in your case you should declare separate variables for things you want to be able configure. If this is just the deploy_secret_1 then you can do this with something like the following:
variable "deploy_secret_1" {
default = "somesupersecretsecret"
}
locals {
environment = terraform.workspace
lambda_vars = {
deploy_version = "0.1"
deploy_name = "deployment"
deploy_secret_1 = var.deploy_secret_1
}
}
Now if you run the following command:
terraform apply -var 'deploy_secret_1=overriding-secret'
It should overwrite the deploy_secret_1 part but leave the rest as is. If you don't specify the deploy_secret_1 variable either by the command line, environment variables or a tfvars file then it will default to somesupersecretsecret. If you'd rather force it to be defined and error if you don't specify the variable then just omit the default argument to the variable declaration.
If you wanted to be able to override more things then you should declare more variables.

.env VUE_APP_ variable json?

Starting to use the vue cli 3 and ran into a use-case I can't seem to find an answer for.
How can I set an environment variable via a .env file (ie, .env.development, .env.production, etc) that exposes a JSON object? Additionally, is there a way to load an external files contents into an environment variable (i.e., require)?
Appreciate the assistance!
I came up with a solution to solve my own issue...
Although the previous answers are viable I didn't want to have to JSON.parse every time I wanted to use the JSON in the environment variable.
The approach I took was to store in each environment-specific file (i.e., .env-development, .env-production, .env-test) a file path to a file containing the JSON. For example...
VUE_APP_JSON_FILE=./.env.development.json-data
This file would contain the raw JSON...
Then in my vue.config.js I used the webpack DefinePlugin to load up the file and make it available via a global variable. For example...
new webpack.DefinePlugin({
VUE_APP_JSON: JSON.stringify(process.env.VUE_APP_JSON_FILE)
})
Defining the new variable will make the json available as an object where throughout my app I can simply reference VUE_APP_JSON.property. This saves me from having to JSON.parse the variable all throughout my app.
You can
stringObj = JSON.stringfy(YourJson),
Then save this string inside the VUE_APP_SOME_KEY_NAME.
but when you'll use it you'll have to JSON.parse () it first.
So, you cannot directly store a json object in a key value .dotEnv file.
Another option is to load these json files Base on process.env.NODE_ENV.
like: require (`config.${process.env.NODE_ENV}.js)
You should distinguish which profile using dot . (as .env.production or .env.development) and the format must be KEY=value, you can't put a json object here, only strings, but you can use JSON.parse in your code to unserialize any string in the file.
Vue cli will only allow access to environment variables that starts with VUE_APP_ and to access, process.env.VUE_APP_SECRET
You can find it and more in the docs

Gradle / Groovy properties

I would like to control 'global' config in Gradle build scripts using external property files on each build machine (dev, ci, uat,...) and specify the filename with a command line argument.
e.g. gradle -DbuildProperties=/example/config/build.properties
I specifically don't want to use gradle.properties as we have existing projects that already use this approach and (for example) we want to be able to amend database urls and jdbc drivers without having to change every project.
So far have tried:-
Properties props = new Properties()
props.load(new FileInputStream("$filename"))
project.setProperty('props', props)
which works but has a deprecated warning, but I can't figure out how to avoid this.
Have also tried using groovy style config files with ConfigSlurper:-
environments {
dev {
db.security {
driver=net.sourceforge.jtds.jdbc.Driver
url=jdbc:someserver://somehost:1234/some_db
username=userId
password=secret
}
}
}
but the colons and forward slashes are causing exceptions and we don't want to have to mess up config with escape characters.
There must be a non-deprecated way to do this - can anyone suggest the 'right' way to do it?
Thanks
You can get rid of the deprecated warning quite easily. The message you got probably looks something like this:
Creating properties on demand (a.k.a. dynamic properties) has been deprecated and is scheduled to be removed in Gradle 2.0. Please read http://gradle.org/docs/current/dsl/org.gradle.api.plugins.ExtraPropertiesExtension.html for information on the replacement for dynamic properties.
Deprecated dynamic property: "props" on "root project 'private'", value: "true".
It can be fixed by replacing:
project.setProperty('props', props)
with
project.ext.props = props
Just to supplement the response given by #Steinar:
it's still possible to use next syntax:
project.ext.set('prop_name', prop_value)
in case you have several properties from file:
props.each({ project.ext.set(it.key, it.value)} )